1. 程式人生 > >Django文件閱讀-Day2

Django文件閱讀-Day2

Django文件閱讀 - Day2

Writing your first Django app, part 1

You can tell Django is installed and which version by running the following command in a shell prompt.

$ python -m django --version

Creating a project

If this is your first time using Django, you’ll have to take care of some initial setup. Namely, you’ll need to auto-generate some code that establishes a Django project – a collection of settings for an instance of Django, including database configuration, Django-specific options and application-specific settings.

From the command line, cd into a directory where you’d like to store your code, then run the following command:

$ django-admin startproject [name]

通過自動生成程式碼建立一個Django Project。

This will create a mysite directory in your current directory. If it didn’t work, see Problems running django-admin.

Let’s look at what startproject

created:

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py

These files are:

  • The outer mysite/ root directory is a container for your project. Its name doesn’t matter to Django; you can rename it to anything you like.

  • 最外層的mysite

    檔名不會影響Django工作

  • manage.py: A command-line utility that lets you interact with this Django project in various ways. You can read all the details about manage.py in django-admin and manage.py.

  • The inner mysite/ directory is the actual Python package for your project. Its name is the Python package name you’ll need to use to import anything inside it (e.g. mysite.urls).

  • 內層的mysite資料夾是一個Python包。

  • mysite/__init__.py: An empty file that tells Python that this directory should be considered a Python package. If you’re a Python beginner, read more about packages in the official Python docs.

  • 告訴Python這個資料夾是一個包。

  • mysite/settings.py: Settings/configuration for this Django project. Django settings will tell you all about how settings work.

  • mysite/urls.py: The URL declarations for this Django project; a “table of contents” of your Django-powered site. You can read more about URLs in URL dispatcher.

  • mysite/asgi.py: An entry-point for ASGI-compatible web servers to serve your project. See How to deploy with ASGI for more details.

  • mysite/wsgi.py: An entry-point for WSGI-compatible web servers to serve your project. See How to deploy with WSGI for more details.

The development server

Let’s verify your Django project works. Change into the outer mysite directory, if you haven’t already, and run the following commands:

$ python manage.py runserver

You’ve started the Django development server, a lightweight Web server written purely in Python. We’ve included this with Django so you can develop things rapidly, without having to deal with configuring a production server – such as Apache – until you’re ready for production.

你已經啟動了Django開發伺服器,一個純粹使用Python開發的輕量級Web伺服器。我們在Django中內建了這個伺服器,這樣你就可以迅速開發了,在產品投入使用之前不必去配置一臺生產環境下的伺服器---例如Apache.

Now’s a good time to note: don’t use this server in anything resembling a production environment. It’s intended only for use while developing. (We’re in the business of making Web frameworks, not Web servers.

現在最佳提示時間,千萬不要在任何類似於生產環境下使用開發伺服器。

Now that the server’s running, visit http://127.0.0.1:8000/ with your Web browser. You’ll see a “Congratulations!” page, with a rocket taking off. It worked!

可通過一下方式改變埠

$ python manage.py runserver [port]

If you want to change the server’s IP, pass it along with the port. For example, to listen on all available public IPs (which is useful if you are running Vagrant or want to show off your work on other computers on the network), use:

$ python manage.py runserver [ip:port]
$ python manage.py runserver 0:8080

Automatic reloading of runserver

The development server automatically reloads Python code for each request as needed. You don’t need to restart the server for code changes to take effect. However, some actions like adding files don’t trigger a restart, so you’ll have to restart the server in these cases.

通常runserver之後會自動載入修改後的程式碼,但是呢,如果是添加了某個檔案,就需要重啟服務了。修改程式碼不必重啟服務,會觸發Django自動重載入。

Creating the Polls app

Now that your environment – a “project” – is set up, you’re set to start doing work.

既然環境配置好了,你就準備開始吧。

Each application you write in Django consists of a Python package that follows a certain convention. Django comes with a utility that automatically generates the basic directory structure of an app, so you can focus on writing code rather than creating directories.

Django的每一個app都會包含一個遵循某些約定的Python包。Django有一個自動生成app目錄結構的工具,所以你可以集中於編寫目錄,而不是建立目錄。

Projects vs. apps

What’s the difference between a project and an app? An app is a Web application that does something – e.g., a Weblog system, a database of public records or a small poll app. A project is a collection of configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.

專案與應用的不同之處?應用是一個Web應用,它可以做很多事,比如一個日誌系統,一個公有資料庫,或者一個投票app。一個專案是配置和應用的集合。一個專案可以包含多個應用,同時一個應用可以用於多個專案。(哇,高度解耦)

Your apps can live anywhere on your Python path. In this tutorial, we’ll create our poll app in the same directory as your manage.py file so that it can be imported as its own top-level module, rather than a submodule of mysite.

**你的app可以建立在任意一個Python可以找到的位置(sys.path),不一定非要建立在當前目錄哦(不要思維定式了,我們將建立我們的投票app在manage.py檔案所在位置。這樣我們app可以被作為頂級模組匯入,而不是mysite的一個子模組。

To create your app, make sure you’re in the same directory as manage.py and type this command:

$ python manage.py startapp polls

That'll create a directory polls, which is laid out like this:

polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

Write your first view

Let’s write the first view. Open the file polls/views.py and put the following Python code in it:

from django.http import HttpResponse #HttpResponse 在http中哦,記住位置啦


def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

This is the simplest view possible in Django. To call the view, we need to map it to a URL - and for this we need a URLconf.

To create a URLconf in the polls directory, create a file called urls.py. Your app directory should now look like:

polls/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    urls.py
    views.py

In the polls/urls.py file include the following code:

from django.urls import path #記住啦,path在urls中。

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]

The next step is to point the root URLconf at the polls.urls module. In mysite/urls.py, add an import for django.urls.include and insert an include() in the urlpatterns list, so you have:

在專案URL配置中建立對映關係:

from django.contrib import admin
from django.urls import include, path #include也在urls裡面哦,路徑相關的都封裝在了urls

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]

The include() function allows referencing other URLconfs. Whenever Django encounters include(), it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.

The idea behind include() is to make it easy to plug-and-play URLs. Since polls are in their own URLconf (polls/urls.py), they can be placed under “/polls/”, or under “/fun_polls/”, or under “/content/polls/”, or any other path root, and the app will still work.

include() 函式允許引用其他URLconfs. 每當Django遇到include()時,它會截斷與該點匹配的URL的任何部分,並將剩餘的字串傳送到包含的URLconf以供進一步處理。

使用include()的目的是為了讓URL更易進行熱插拔(plug-and-play)。 由於polls是在他自己的URLconfpolls/urls.py),他們可以被放置在“/ polls /”,或“/ fun_polls /”下,或“/ content / polls /” ,或任何其他路徑的根,應用程式將仍然工作。

You have now wired an index view into the URLconf. Verify it’s working with the following command:

$ python manage.py runserver

The path() function is passed four arguments, two required: route and view, and two optional: kwargs, and name. At this point, it’s worth reviewing what these arguments are for.

path()引數:route 
route是一個包含URL模式的字串。 在處理請求時,Django從urlpatterns中的第一個正則開始並在列表中向下匹配,將所請求的URL與每個正則進行匹配,直到找到匹配的正則。

正則表示式不搜尋GET和POST引數或域名。 例如,在https://www.example.com/myapp/的請求中,URLconf將查詢myapp /。 在https://www.example.com/myapp/?page=3的請求中,URLconf也會查詢myapp/。

path()引數:view 
當Django找到匹配的正則時,它會以HttpRequest物件作為第一個引數和route中的任何“捕獲”值作為關鍵字引數來呼叫指定的檢視函式。 我們將稍微舉一個例子。

path()引數:kwargs 
任意關鍵字引數可以在字典中傳遞給目標檢視。 我們不打算在教程中使用Django的這個特性。

path()引數:name 
命名您的URL可以讓您從Django其他地方明確地引用它,特別是在模板中。 這個強大的功能允許您在只操作單個檔案的情況下對專案的URL正則進行全域性更改。

當您熟悉基本的請求和響應流程時,請閱讀本教程的第2部分以開始使用資料庫。

Writing your first Django app, part 2

This tutorial begins where Tutorial 1 left off. We’ll setup the database, create your first model, and get a quick introduction to Django’s automatically-generated admin site.

Database setup

Now, open up mysite/settings.py. It’s a normal Python module with module-level variables representing Django settings.

By default, the configuration uses SQLite. If you’re new to databases, or you’re just interested in trying Django, this is the easiest choice. SQLite is included in Python, so you won’t need to install anything else to support your database. When starting your first real project, however, you may want to use a more scalable database like PostgreSQL, to avoid database-switching headaches down the road.

If you wish to use another database, install the appropriate database bindings and change the following keys in the DATABASES 'default' item to match your database connection settings:

  • ENGINE – Either 'django.db.backends.sqlite3', 'django.db.backends.postgresql', 'django.db.backends.mysql', or 'django.db.backends.oracle'. Other backends are also available.
  • NAME – The name of your database. If you’re using SQLite, the database will be a file on your computer; in that case, NAME should be the full absolute path, including filename, of that file. The default value, os.path.join(BASE_DIR, 'db.sqlite3'), will store the file in your project directory.

If you are not using SQLite as your database, additional settings such as USER, PASSWORD, and HOST must be added. For more details, see the reference documentation for DATABASES.

For databases other than SQLite

If you’re using a database besides SQLite, make sure you’ve created a database by this point. Do that with “CREATE DATABASE database_name;” within your database’s interactive prompt.

Also make sure that the database user provided in mysite/settings.py has “create database” privileges. This allows automatic creation of a test database which will be needed in a later tutorial.

If you’re using SQLite, you don’t need to create anything beforehand - the database file will be created automatically when it is needed.

While you’re editing mysite/settings.py, set TIME_ZONE to your time zone.

在編輯mysite/settings.py時,一定要先設定自己的時區哦。

Also, note the INSTALLED_APPS setting at the top of the file. That holds the names of all Django applications that are activated in this Django instance. Apps can be used in multiple projects, and you can package and distribute them for use by others in their projects.

記得關注下INSTALLED_APPS這個設定,它包含了專案中所有啟用的Django應用。應用能在多個專案中使用,你也可以打包釋出,讓別人使用。預設有:

  • django.contrib.admin – The admin site. You’ll use it shortly. 管理站點
  • django.contrib.auth – An authentication system. 認證授權系統
  • django.contrib.contenttypes – A framework for content types. 內容型別框架
  • django.contrib.sessions – A session framework. 會話框架
  • django.contrib.messages – A messaging framework. 訊息框架
  • django.contrib.staticfiles – A framework for managing static files. 管理靜態檔案的框架。這些應用被預設啟用,為了給專案提供方便。

Some of these applications make use of at least one database table, though, so we need to create the tables in the database before we can use them. To do that, run the following command:

預設開啟的某些應用需要至少一個數據表,所以,在使用他們之前需要在資料庫中建立一些表,請執行如下命令。

$ python manage.py migrate

The migrate command looks at the INSTALLED_APPS setting and creates any necessary database tables according to the database settings in your mysite/settings.py file and the database migrations shipped with the app (we’ll cover those later).

這句話告訴我們在建立app是一定要在INSTALLED_APPS中註冊,否則無法建立資料庫的表哦

You’ll see a message for each migration it applies. If you’re interested, run the command-line client for your database and type \dt (PostgreSQL), SHOW TABLES; (MariaDB, MySQL), .schema (SQLite), or SELECT TABLE_NAME FROM USER_TABLES; (Oracle) to display the tables Django created.

migrate命令檢視INSTALLED_APPS設定,並根據mysite/settings.py檔案中的資料庫設定建立所有必要的資料庫表,遷移命令將只對Insted_app中的應用程式執行遷移。 You’ll see a message for each migration it applies. 如果你感興趣的話, 執行你的資料庫命令列客戶端並且輸入命令\dt (PostgreSQL), SHOW TABLES; (MySQL), .schema (SQLite), 或者 SELECT TABLE_NAME FROM USER_TABLES; (Oracle) 來顯示Django建立的表

就像我們上面所說的那樣,預設應用程式包含在常見的情況下,但不是每個人都需要它們。 如果您不需要其中任何一個或全部,請在執行migrate之前自由註釋或刪除INSTALLED_APPS中的相應行。 migrate命令將只對INSTALLED_APPS中的應用程式進行遷移。

Creating models

Now we’ll define your models – essentially, your database layout, with additional metadata.

模型也就是資料庫設計和附加的其他元資料。

設計哲學
模型是關於您的資料的單一,明確的真相來源。 它包含您正在儲存的資料的重要欄位和行為。 Django 遵循 DRY 原理. 目標是在一個地方定義你的資料模型,並從中自動派生東西。

這包括遷移 - 與Ruby On Rails不同,例如,遷移完全從您的模型檔案派生而來,本質上只是Django可以滾動更新資料庫模式以符合當前模型的歷史記錄。

In our poll app, we’ll create two models: Question and Choice. A Question has a question and a publication date. A Choice has two fields: the text of the choice and a vote tally. Each Choice is associated with a Question.

These concepts are represented by Python classes. Edit the polls/models.py file so it looks like this:

from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

Here, each model is represented by a class that subclasses django.db.models.Model. Each model has a number of class variables, each of which represents a database field in the model.

程式碼很簡單。 每個模型都由一個子類來表示django.db.models.Model. 每個模型都有許多類變數,每個變量表示模型中的資料庫欄位。

Each field is represented by an instance of a Field class – e.g., CharField for character fields and DateTimeField for datetimes. This tells Django what type of data each field holds.

每個欄位都由一個欄位類的例項Field表示——例如,用於字元欄位的CharFieldDateTimeField。 這告訴Django每個欄位擁有什麼型別的資料。

The name of each Field instance (e.g. question_text or pub_date) is the field’s name, in machine-friendly format. You’ll use this value in your Python code, and your database will use it as the column name.

每個Field例項(例如question_textpub_date)的名稱是機器友好格式的欄位名稱。 您將在您的Python程式碼中使用此值,並且您的資料庫將使用它作為列名稱。

You can use an optional first positional argument to a Field to designate a human-readable name. That’s used in a couple of introspective parts of Django, and it doubles as documentation. If this field isn’t provided, Django will use the machine-readable name. In this example, we’ve only defined a human-readable name for Question.pub_date. For all other fields in this model, the field’s machine-readable name will suffice as its human-readable name.

您可以使用可選的第一個位置引數指向一個欄位來指定一個人類可讀的名稱。 這在Django的一些內省部分中使用,並且它作為文件加倍。 如果未提供此欄位,則Django將使用機器可讀名稱。 在這個例子中,我們只為Question.pub_date定義了一個人類可讀的名字。 對於此模型中的所有其他欄位,該欄位的機器可讀名稱就足以作為其人類可讀的名稱。

Some Field classes have required arguments. CharField, for example, requires that you give it a max_length. That’s used not only in the database schema, but in validation, as we’ll soon see.

一些Field類具有必需的引數。 CharField, 例如,需要你給它一個 max_length. 這不僅在資料庫模式中使用,而且在驗證中使用,我們很快就會看到。

A Field can also have various optional arguments; in this case, we’ve set the default value of votes to 0.

一個Field也可以有各種可選的引數;在這種情況下,我們已將votesdefault值設定為0。

Finally, note a relationship is defined, using ForeignKey. That tells Django each Choice is related to a single Question. Django supports all the common database relationships: many-to-one, many-to-many, and one-to-one.

最後,請注意使用ForeignKey定義關係。 這告訴Django每個Choice都與單個Question有關(多對一)。 Django支援所有常見的資料庫關係:多對一,多對多和一對一。

Activating models

That small bit of model code gives Django a lot of information. With it, Django is able to:

  • Create a database schema (CREATE TABLE statements) for this app.
  • Create a Python database-access API for accessing Question and Choice objects.

But first we need to tell our project that the polls app is installed.

設計哲學
Django應用程式是“可插入的”:您可以在多個專案中使用應用程式,並且可以分發應用程式,因為它們不必繫結到當前安裝的Django上。

To include the app in our project, we need to add a reference to its configuration class in the INSTALLED_APPS setting. The PollsConfig class is in the polls/apps.py file, so its dotted path is 'polls.apps.PollsConfig'. Edit the mysite/settings.py file and add that dotted path to the INSTALLED_APPS setting. It’ll look like this:

INSTALLED_APPS = [
    'polls.apps.PollsConfig', #注意了哦
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Now Django knows to include the polls app. Let’s run another command:

$ python manage.py makemigrations polls

You should see something similar to the following:

Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice

By running makemigrations, you’re telling Django that you’ve made some changes to your models (in this case, you’ve made new ones) and that you’d like the changes to be stored as a migration.

通過makemigrations,你在告訴Django你已經對你的models做出了改變,並且你想要儲存為資料庫遷移檔案。

Migrations are how Django stores changes to your models (and thus your database schema) - they’re files on disk. You can read the migration for your new model if you like; it’s the file polls/migrations/0001_initial.py. Don’t worry, you’re not expected to read them every time Django makes one, but they’re designed to be human-editable in case you want to manually tweak how Django changes things.

遷移是Django對於模型定義(也就是你的資料庫結構)的變化的儲存形式,其實就是你磁碟的一些檔案。如果你想的話,你可以閱讀一下你模型的遷移資料,它被儲存在polls/migrations/0001_initial.py裡。別擔心,你不需要每次閱讀它們,但是它們被設計成人類可讀形式,這是為了便於你手動修改它們。

There’s a command that will run the migrations for you and manage your database schema automatically - that’s called migrate, and we’ll come to it in a moment - but first, let’s see what SQL that migration would run. The sqlmigrate command takes migration names and returns their SQL:

$ python manage.py sqlmigrate polls 001

Django有一個自動執行資料庫遷移並同步管理你的資料結構的命令這個命令就是migrate,我們馬上就會接觸他,但是首先,讓我們看看遷移命令會執行那些SQL語句。sqlmigrate命令接收一個遷移的名稱,然後返回對應的SQL

You should see something similar to the following (we’ve reformatted it for readability):

BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
    "id" serial NOT NULL PRIMARY KEY,
    "question_text" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL,
    "question_id" integer NOT NULL
);
ALTER TABLE "polls_choice"
  ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id"
    FOREIGN KEY ("question_id")
    REFERENCES "polls_question" ("id")
    DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");

COMMIT;

Note the following:

  • The exact output will vary depending on the database you are using. The example above is generated for PostgreSQL.

確切的輸出將取決於您使用的資料庫。 上面的例子是為PostgreSQL生成的。

  • Table names are automatically generated by combining the name of the app (polls) and the lowercase name of the model – question and choice. (You can override this behavior.)

表名是通過將應用程式的名稱(polls)和模型的小寫名稱questionchoice組合自動生成的。 (您可以覆蓋此行為。)

  • Primary keys (IDs) are added automatically. (You can override this, too.)

主鍵(ID)會自動新增。 (你也可以覆蓋它。)

  • By convention, Django appends "_id" to the foreign key field name. (Yes, you can override this, as well.)

按照慣例,Django將“_id”附加到外來鍵欄位名稱。 (是的,你也可以重寫這個。)

  • The foreign key relationship is made explicit by a FOREIGN KEY constraint. Don’t worry about the DEFERRABLE parts; it’s telling PostgreSQL to not enforce the foreign key until the end of the transaction.

外來鍵關係通過FOREIGN KEY約束來顯式化。 不要擔心DEFERRABLE部分;這只是告訴PostgreSQL在事務結束之前不執行外來鍵。

  • It’s tailored to the database you’re using, so database-specific field types such as auto_increment (MySQL), serial (PostgreSQL), or integer primary key autoincrement (SQLite) are handled for you automatically. Same goes for the quoting of field names – e.g., using double quotes or single quotes.

它針對您所使用的資料庫量身定做,因此特定於資料庫的欄位型別(如auto_increment(MySQL),serial(PostgreSQL)或integer primary key autoincrement(SQLite)。 欄位名稱的引用也是如此 - 例如,使用雙引號或單引號。

  • The sqlmigrate command doesn’t actually run the migration on your database - instead, it prints it to the screen so that you can see what SQL Django thinks is required. It’s useful for checking what Django is going to do or if you have database administrators who require SQL scripts for changes.

**sqlmigrate命令實際上並不在資料庫上執行遷移 - 它只是將它列印到螢幕上,以便您可以看到SQL Django認為需要什麼。 這對於檢查Django將要做什麼或者如果您有需要SQL指令碼進行更改的資料庫管理員很有用。**

If you’re interested, you can also run python manage.py check; this checks for any problems in your project without making migrations or touching the database.

如果您有興趣,您也可以執行python manage.py check;這可以檢查專案中的任何問題,且不會對資料庫進行操作。

現在,再次執行migrate以在您的資料庫中建立這些模型表:

Now, run migrate again to create those model tables in your database:

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Rendering model states... DONE
  Applying polls.0001_initial... OK

The migrate command takes all the migrations that haven’t been applied (Django tracks which ones are applied using a special table in your database called django_migrations) and runs them against your database - essentially, synchronizing the changes you made to your models with the schema in the database.

這個migrate命令選中所有還沒有執行過得遷移(Django通過在資料庫中建立一個特殊的表django—migrations來跟蹤執行過那些遷移)並應用在資料庫上,也就是將你對模型的更改同步到資料庫結構上。

Migrations are very powerful and let you change your models over time, as you develop your project, without the need to delete your database or tables and make new ones - it specializes in upgrading your database live, without losing data. We’ll cover them in more depth in a later part of the tutorial, but for now, remember the three-step guide to making model changes:

遷移是非常強大的功能,他能夠讓你在開發過程中持續的改變資料庫中的資料結構而不需要刪除或建立表,它專注於是資料庫平滑升級而不丟失資料。記住改變模型的三步

  • Change your models (in models.py).
  • Run python manage.py makemigrations to create migrations for those changes
  • Run python manage.py migrate to apply those changes to the database.

The reason that there are separate commands to make and apply migrations is because you’ll commit migrations to your version control system and ship them with your app; they not only make your development easier, they’re also usable by other developers and in production.

Read the django-admin documentation for full information on what the manage.py utility can do.

在Day1中我猜測,資料遷移命令由一步變兩步的原因有誤,這裡Django官方給出了答案:資料庫遷移被分解成生成和應用兩個命令是為了讓開發者能夠在程式碼控制系統中提交遷移資料並使其能夠在多個應用中使用;這不僅會使的開發更加簡單,也給別的開發者和生產環境中的使用帶來了方便。

Playing with the API

Now, let’s hop into the interactive Python shell and play around with the free API Django gives you. To invoke the Python shell, use this command:

$ python manage.py shell

We’re using this instead of simply typing “python”, because manage.py sets the DJANGO_SETTINGS_MODULE environment variable, which gives Django the Python import path to your mysite/settings.py file.

Once you’re in the shell, explore the database API:

>>> from polls.models import Choice, Question  # Import the model classes we just wrote.

# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>

# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone #劃重點,Django中使用時間,現在設定中設定自己的時區,之後使用python提供的時間工具。在utils中,timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID.
>>> q.id
1

# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()

# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

Wait a minute. <Question: Question object (1)> isn’t a helpful representation of this object. Let’s fix that by editing the Question model (in the polls/models.py file) and adding a __str__() method to both Question and Choice:

from django.db import models

class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text #列印物件是有人性化的提示

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

It’s important to add __str__() methods to your models, not only for your own convenience when dealing with the interactive prompt, but also because objects’ representations are used throughout Django’s automatically-generated admin.

設定__str__()不僅為了自己除錯方便,admin還對其有所依賴。

Let’s also add a custom method to this model:

import datetime

from django.db import models
from django.utils import timezone


class Question(models.Model):
    # ...
    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

Note the addition of import datetime and from django.utils import timezone, to reference Python’s standard datetime module and Django’s time-zone-related utilities in django.utils.timezone, respectively. If you aren’t familiar with time zone handling in Python, you can learn more in the time zone support docs.

Save these changes and start a new Python interactive shell by running python manage.py shell again:

>>> from polls.models import Choice, Question

# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.
#=========================================================================
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>

# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>

# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

For more information on model relations, see Accessing related objects. For more on how to use double underscores to perform field lookups via the API, see Field lookups. For full details on the database API, see our Database API reference.

Introducing the Django Admin

Philosophy

Generating admin sites for your staff or clients to add, change, and delete content is tedious work that doesn’t require much creativity. For that reason, Django entirely automates creation of admin interfaces for models.

Django was written in a newsroom environment, with a very clear separation between “content publishers” and the “public” site. Site managers use the system to add news stories, events, sports scores, etc., and that content is displayed on the public site. Django solves the problem of creating a unified interface for site administrators to edit content.

The admin isn’t intended to be used by site visitors. It’s for site managers.

Creating an admin user

First we’ll need to create a user who can login to the admin site. Run the following command:

建立使用者:

$ python manage.py createsuperuser

Enter your desired username and press enter.

Username: admin

You will then be prompted for your desired email address:

Email address: [email protected]

The final step is to enter your password. You will be asked to enter your password twice, the second time as a confirmation of the first.

Password: **********
Password (again): *********
Superuser created successfully.

Start the development server

The Django admin site is activated by default. Let’s start the development server and explore it.

If the server is not running start it like so:

$ python manage.py runserver

Enter the admin site

Now, try logging in with the superuser account you created in the previous step. You should see the Django admin index page

You should see a few types of editable content: groups and users. They are provided by django.contrib.auth, the authentication framework shipped by Django.

所看到的幾種可編輯內容是有django.contrib.auth提供的,這是Python開發的認證框架。

Make the poll app modifiable in the admin

But where’s our poll app? It’s not displayed on the admin index page.

Only one more thing to do: we need to tell the admin that Question objects have an admin interface. To do this, open the polls/admin.py file, and edit it to look like this:

但是我們的投票應用在哪呢?他沒在索引頁面顯示。

只需要做一件事: 我們得告訴管理頁面,問題Question物件需要被管理。開啟polls/admin.py檔案,把它編輯成下面這樣:

from django.contrib import admin

from .models import Question

admin.site.register(Question)

Explore the free admin functionality

Things to note here:

  • The form is automatically generated from the Question model.
  • The different model field types (DateTimeField, CharField) correspond to the appropriate HTML input widget. Each type of field knows how to display itself in the Django admin.
  • Each DateTimeField gets free JavaScript shortcuts. Dates get a “Today” shortcut and calendar popup, and times get a “Now” shortcut and a convenient popup that lists commonly entered times.

The bottom part of the page gives you a couple of options:

  • Save – Saves changes and returns to the change-list page for this type of object.
  • Save and continue editing – Saves changes and reloads the admin page for this object.
  • Save and add another – Saves changes and loads a new, blank form for this type of object.
  • Delete – Displays a delete confirmation page.

If the value of “Date published” doesn’t match the time when you created the question in Tutorial 1, it probably means you forgot to set the correct value for the TIME_ZONE setting. Change it, reload the page and check that the correct value appears.

Change the “Date published” by clicking the “Today” and “Now” shortcuts. Then click “Save and continue editing.” Then click “History” in the upper right. You’ll see a page listing all changes made to this object via the Django admin, with the timestamp and username of the person who made the change

今日收穫單詞

throughout 遍及,貫穿
walk 引導
poll 投票
vote 投票,選舉
assume 假設,設想
compatible 相容的,能共處的
namely 也就是,換句話說
take care of 注意
conflict 衝突
risk 冒...風險
utility  /juːˈtɪləti/  實用,實用程式
interact 相互作用,互相影響,互動
dispatcher 排程員,排程程式
identify iden tify 確認,認出,鑑定,找到,發現
unapplied 未被應用
resemble re sem ble 看起來像(not used in the progressive tenses)
internal 內部的
show off 炫耀
be set to 準備
certain 某些,確實,確定,無疑
convention 習慣,習俗,約定
come with 與...一起,伴隨著
house v.覆蓋,把...儲藏在房內
be laid out 展開
encounter 遭遇,邂逅,遇到
counter n.櫃檯,計數器 v.反擊,還擊,反駁
chop off 砍掉
arbitrary 任意的,專制的,武斷的
leave off 中斷,停止
head over 前往,駛往
hold 擁有,包含
make use of 利用,使用
essential 本質上,必要的;本質,要素,要點
derive 源於,得自,獲得
definitive 明確的,最佳的
machine 機器機械
machine-friendly 機器友好的
introspective 內省的,反省的
tweak 扭,輕微調整
by convention 按照慣例
tailored 定製的,裁縫做的
transaction 事務,交易
deferrabel 可延期的,可退吃的
over time 隨著時間的過去
specialize  專門從事;詳細說明;特化
invoke 呼叫
interactive 互動式的
hop into 跳進,進入
hop 單足跳行
respectively 分別地,各自地,獨自地
exact 準確的,精密的,要求,強求
lookup 查詢
identical 完全相同的,同一的
construct 概念,設計,構圖
tedious 沉悶的,冗長乏味的
automate 使自動化,自動化
unified 統一的,一致標準的
unify 統一,使一致
explore 探索
modifiable 可修改的