django項目mysite

項目創建

創建項目mysitehtml

各文件和目錄解釋:python

  • 外層的mysite/目錄與Django無關,只是你項目的容器,能夠任意重命名。
  • manage.py:一個命令行工具,用於與Django進行不一樣方式的交互腳本,很是重要!
  • 內層的mysite/目錄是真正的項目文件包裹目錄,它的名字是你引用內部文件的包名,例如:mysite.urls
  • mysite/__init__.py:一個定義包的空文件。
  • mysite/settings.py:項目的主配置文件,很是重要!
  • mysite/urls.py:路由文件,全部的任務都是從這裏開始分配,至關於Django驅動站點的內容表格,很是重要!
  • mysite/wsgi.py:一個基於WSGI的web服務器進入點,提供底層的網絡通訊功能,一般不用關心。

 啓動開發服務器mysql

 

或進入mystie項目的根目錄,輸入下面的命令:程序員

$ python manage.py runserver

Django提供了一個用於開發的web服務器,使你無需配置一個相似Ngnix的生產服務器,就能讓站點運行起來。這是一個由Python編寫的輕量級服務器,簡易而且不安全,所以不要將它用於生產環境。web

打開瀏覽器,訪問http://127.0.0.1:8000/,你將看到Django的火箭歡迎界面,一切OK!正則表達式

建立投票應用(app)

在 Django 中,每個應用(app)都是一個 Python 包,而且遵循着相同的約定。Django 自帶一個工具,能夠幫你生成應用的基礎目錄結構。sql

app應用與project項目的區別:shell

  • 一個app實現某個功能,好比博客、公共檔案數據庫或者簡單的投票系統;
  • 一個project是配置文件和多個app的集合,這些app組合成整個站點;
  • 一個project能夠包含多個app;
  • 一個app能夠屬於多個project!

一般app將它們放在與manage.py腳本同級的目錄下,這樣方便導入文件。數據庫

進入mysite項目根目錄,確保與manage.py文件處於同一級,輸入下述命令django

python manage.py startapp polls

  系統會自動生成 polls應用的目錄,其結構以下

在Pycharm中,沒有能夠建立app的圖形化按鈕,須要在下方的Terminal終端中輸入命令

編寫視圖

polls/views.py文件中,編寫代碼

from django.http import HttpResponse


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

爲了調用該視圖,咱們還須要編寫urlconf,也就是路由。如今,在polls目錄中新建一個文件,名字爲urls.py,在其中輸入代碼以下:

from django.urls import path

from . import views

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

接下來,在項目的主urls.py文件中添加urlpattern條目,指向咱們剛纔創建的polls這個app獨有的urls文件,

這裏須要導入include模塊。打開mysite/urls.py文件,代碼以下

from django.contrib import admin
from django.urls import include, path

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

include語法至關於多級路由,它把接收到的url地址去除與此項匹配的部分,將剩下的字符串傳遞給下一級路由

include的背後是一種即插即用的思想。項目根路由不關心具體app的路由策略,只管往指定的二級路由轉發,實現了應用解耦。

app所屬的二級路由能夠根據本身的須要隨意編寫,不會和其它的app路由發生衝突。app目錄能夠放置在任何位置,而不用修改路由。這是軟件設計裏很常見的一種模式。

好了,路由設置成功後,啓動服務器,而後在瀏覽器中訪問地址http://localhost:8000/polls/。一切正常的話,你將看到「Hello, world. You’re at the polls index.」

path()方法

路由系統中最重要的path()方法能夠接收4個參數,其中2個是必須的:routeview,以及2個可選的參數:kwargsname

route:

route 是一個匹配 URL 的準則(相似正則表達式)。當 Django 響應一個請求時,它會從 urlpatterns 的第一項開始,按順序依次匹配列表中的項,直到找到匹配的項,

而後執行該條目映射的視圖函數或下級路由,其後的條目將再也不繼續匹配。所以,url路由的編寫順序很是重要!

須要注意的是,route不會匹配 GET 和 POST 參數或域名。例如,URLconf 在處理請求 https://www.example.com/myapp/時,

它會嘗試匹配 myapp/。處理請求 https://www.example.com/myapp/?page=3 時,也只會嘗試匹配 myapp/

view:

view指的是處理當前url請求的視圖函數。當Django匹配到某個路由條目時,自動將封裝的HttpRequest對象做爲第一個參數,被「捕獲」的參數以關鍵字參數的形式,傳遞給該條目指定的視圖view。

kwargs:

任意數量的關鍵字參數能夠做爲一個字典傳遞給目標視圖。

name:

對你的URL進行命名,讓你可以在Django的任意處,尤爲是模板內顯式地引用它。這是一個很是強大的功能,至關於給URL取了個全局變量名,不會將url匹配地址寫死

 

數據庫配置

打開mysite/settings.py配置文件,這是整個Django項目的設置中心。Django默認使用SQLite數據庫,

由於Python源生支持SQLite數據庫,因此你無須安裝任何程序,就能夠直接使用它。固然,若是你是在建立一個實際的項目,可使用相似PostgreSQL的數據庫

# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

若是你想使用其餘的數據庫,請先安裝相應的數據庫操做模塊,並將settings文件中DATABASES位置的’default’的鍵值進行相應的修改,用於鏈接你的數據庫。其中:

  • ENGINE(引擎):能夠是django.db.backends.sqlite3django.db.backends.postgresqldjango.db.backends.mysqldjango.db.backends.oracle,固然其它的也行。

  • NAME(名稱):相似Mysql數據庫管理系統中用於保存項目內容的數據庫的名字。若是你使用的是默認的SQLite,那麼數據庫將做爲一個文件將存放在你的本地機器內,

           此時的NAME應該是這個文件的完整絕對路徑包括文件名,默認值os.path.join(BASE_DIR, ’db.sqlite3’),將把該文件儲存在你的項目目錄下。

基於pymysql操做Mysql數據庫的例子

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

import pymysql         # 必定要添加這兩行!經過pip install pymysql!
pymysql.install_as_MySQLdb()


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'cnblog',
        'USER': 'root',
        'PASSWORD': '111',
        'HOST': '127.0.0.1',
        'PORT': 3306
      
    }
}


# mysql orm轉換sql日誌
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

 

注意:

  • 在使用非SQLite的數據庫時,請務必預先在數據庫管理系統的提示符交互模式下建立數據庫,你可使用命令:CREATE DATABASE database_name;。Django不會自動幫你作這一步工做。
  • 確保你在settings文件中提供的數據庫用戶具備建立數據庫表的權限,由於在接下來的教程中,咱們須要自動建立一個test數據表。(在實際項目中也須要確認這一條要求。)
  • 若是你使用的是SQLite,那麼你無需作任何預先配置,直接使用就能夠了。

在修改settings文件時,請順便將TIME_ZONE設置爲國內所在的時區Asia/Shanghai

同時,請注意settings文件中頂部的INSTALLED_APPS設置項。它列出了全部的項目中被激活的Django應用(app)。你必須將你自定義的app註冊在這裏。每一個應用能夠被多個項目使用,而且能夠打包和分發給其餘人在他們的項目中使用。

默認狀況,INSTALLED_APPS中會自動包含下列條目,它們都是Django自動生成的:

  • django.contrib.admin:admin管理後臺站點
  • django.contrib.auth:身份認證系統
  • django.contrib.contenttypes:內容類型框架
  • django.contrib.sessions:會話框架
  • django.contrib.messages:消息框架
  • django.contrib.staticfiles:靜態文件管理框架

上面的一些應用也須要創建一些數據庫表,因此在使用它們以前咱們要在數據庫中建立這些表。使用下面的命令建立數據表:

python manage.py migrate

  

建立模型

如今,咱們來定義模型model,模型本質上就是數據庫表的佈局,再附加一些元數據。

Django經過自定義Python類的形式來定義具體的模型,每一個模型的物理存在方式就是一個Python的類Class,每一個模型表明數據庫中的一張表,每一個類的實例表明數據表中的一行數據,類中的每一個變量表明數據表中的一列字段。

Django經過模型,將Python代碼和數據庫操做結合起來,實現對SQL查詢語言的封裝。也就是說,你能夠不會管理數據庫,能夠不會SQL語言,你一樣能經過Python的代碼進行數據庫的操做。

Django經過ORM對數據庫進行操做,奉行代碼優先的理念,將Python程序員和數據庫管理員進行分工解耦。

在這個簡單的投票應用中,咱們將建立兩個模型:QuestionChoice。Question包含一個問題和一個發佈日期。Choice包含兩個字段:該選項的文本描述和該選項的投票數。

每一條Choice都關聯到一個Question。這些都是由Python的類來體現,編寫的全是Python的代碼,不接觸任何SQL語句。如今,編輯polls/models.py文件

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)

 

上面的代碼很是簡單明瞭。每個類都是django.db.models.Model的子類。每個字段都是Field類的一個實例,例如用於保存字符數據的CharField和用於保存時間類型的DateTimeField,它們告訴Django每個字段保存的數據類型。

每個Field實例的名字就是字段的名字(如: question_text 或者 pub_date )。在你的Python代碼中會使用這個值,你的數據庫也會將這個值做爲表的列名。

一些Field類必須提供某些特定的參數。例如CharField須要你指定max_length。這不只是數據庫結構的須要,一樣也用於數據驗證功能。

有必填參數,固然就會有可選參數,好比在votes裏咱們將其默認值設爲0.

最後請注意,咱們使用ForeignKey定義了一個外鍵關係。它告訴Django,每個Choice關聯到一個對應的Question(注意要將外鍵寫在‘多’的一方)。Django支持通用的數據關係:一對一,多對一和多對多。

啓用模型

上面的代碼看着有點少,其實包含了大量的信息,據此,Django會作下面兩件事:

  • 建立該app對應的數據庫表結構
  • 爲Question和Choice對象建立基於Python的數據庫訪問API

可是,首先咱們得先告訴Django項目,咱們要使用投票app。

要將應用添加到項目中,須要在INSTALLED_APPS設置中增長指向該應用的配置文件的連接。對於本例的投票應用,它的配置類文件PollsConfig是polls/apps.py

因此它的點式路徑爲polls.apps.PollsConfig。咱們須要在INSTALLED_APPS中,將該路徑添加進去,實際上,在多數狀況下,咱們簡寫成‘polls’就能夠了:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'polls'
]

如今Django已經知道你的投票應用的存在了,並把它加入了項目你們庭。

咱們須要再運行下一個命令:

 python manage.py makemigrations polls

  

經過運行makemigrations命令,Django 會檢測你對模型文件的修改,也就是告訴Django你對模型有改動,而且你想把這些改動保存爲一個「遷移(migration)」。

migrations是Django保存模型修改記錄的文件,這些文件保存在磁盤上。在例子中,它就是polls/migrations/0001_initial.py,你能夠打開它看看,裏面保存的都是人類可讀而且可編輯的內容,方便你隨時手動修改。

接下來有一個叫作migrate的命令將對數據庫執行真正的遷移動做。可是在此以前,讓咱們先看看在migration的時候實際執行的SQL語句是什麼。有一個叫作sqlmigrate的命令能夠展現SQL語句

python manage.py sqlmigrate polls 0001

  

請注意:

  • 實際的輸出內容將取決於您使用的數據庫會有所不一樣。上面的是mySQL的輸出。
  • 表名是自動生成的,經過組合應用名 (polls) 和小寫的模型名questionchoice 。 ( 你能夠重寫此行爲。)
  • 主鍵 (IDs) 是自動添加的。( 你也能夠重寫此行爲。)
  • 按照慣例,Django 會在外鍵字段名上附加 "_id" 。 (你仍然能夠重寫此行爲。)
  • 生成SQL語句時針對你所使用的數據庫,會爲你自動處理特定於數據庫的字段,例如 auto_increment (MySQL), serial (PostgreSQL), 或integer primary key (SQLite) 。 在引用字段名時也是如此 – 好比使用雙引號或單引號。
  • 這些SQL命令並無在你的數據庫中實際運行,它只是在屏幕上顯示出來,以便讓你瞭解Django真正執行的是什麼。

若是你感興趣,也能夠運行python manage.py check命令,它將檢查項目中的錯誤,並不實際進行遷移或者連接數據庫的操做。

$ python manage.py migrate

  

migrate命令對全部還未實施的遷移記錄進行操做,本質上就是將你對模型的修改體現到數據庫中具體的表上面。Django經過一張叫作django_migrations的表,記錄並跟蹤已經實施的migrate動做,經過對比得到哪些migrations還沒有提交。

migrations的功能很是強大,容許你隨時修改你的模型,而不須要刪除或者新建你的數據庫或數據表,在不丟失數據的同時,實時動態更新數據庫。咱們將在後面的章節對此進行深刻的闡述,可是如今,只須要記住修改模型時的操做分三步:

  • 在models.py中修改模型;
  • 運行python manage.py makemigrations爲改動建立遷移記錄;
  • 運行python manage.py migrate,將操做同步到數據庫。
mysql> show tables;
+----------------------------+
| Tables_in_poll             |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| polls_choice               |
| polls_question             |
+----------------------------+
12 rows in set (0.00 sec)

 

使用模型的API

下面,讓咱們進入Python交互環境,嘗試使用Django提供的數據庫訪問API。要進入Python的shell,請輸入命令

 python manage.py shell

  

相比較直接輸入「python」命令的方式進入Python環境,調用manage.py參數能將DJANGO_SETTINGS_MODULE環境變量導入,

它將自動按照mysite/settings.py中的設置,配置好你的python shell環境,這樣,你就能夠導入和調用任何你項目內的模塊了。

先進入一個純淨的python shell環境,而後啓動Django。

當你進入shell後,嘗試一下下面的API吧:

>>> from polls.models import Question, Choice # 導入咱們寫的模型類
    # 如今系統內尚未questions對象
    >>> Question.objects.all()
    <QuerySet []>

    # 建立一個新的question對象
    # Django推薦使用timezone.now()代替python內置的datetime.datetime.now()
    # 這個timezone就來自於Django的依賴庫pytz
    from django.utils import timezone
    >>> q = Question(question_text="What's new?", pub_date=timezone.now())

    # 你必須顯式的調用save()方法,才能將對象保存到數據庫內
    >>> q.save()

    # 默認狀況,你會自動得到一個自增的名爲id的主鍵
    >>> q.id
    1

    # 經過python的屬性調用方式,訪問模型字段的值
    >>> q.question_text
    "What's new?"
    >>> q.pub_date
    datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

    # 經過修改屬性來修改字段的值,而後顯式的調用save方法進行保存。
    >>> q.question_text = "What's up?"
    >>> q.save()

    # objects.all() 用於查詢數據庫內的全部questions
    >>> Question.objects.all()
    <QuerySet [<Question: Question object>]>

 

上面的<Question: Question object>是一個不可讀的內容展現,你沒法從中得到任何直觀的信息,爲此咱們須要一點小技巧,讓Django在打印對象時顯示一些咱們指定的信息。

返回polls/models.py文件,修改一下question和Choice這兩個類,代碼以下:

from django.db import models


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

    def __str__(self):
        return self.question_text

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

    def __str__(self):
        return self.choice_text

這個技巧不但對你打印對象時頗有幫助,在你使用Django的admin站點時也一樣有幫助。

從新啓動一個新的python shell,再來看看其餘的AP

>>> from polls.models import Question, Choice

# 先看看__str__()的效果,直觀多了吧?
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django提供了大量的關鍵字參數查詢API
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# 獲取今年發佈的問卷
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# 查詢一個不存在的ID,會彈出異常
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.

# Django爲主鍵查詢提供了一個縮寫:pk。下面的語句和Question.objects.get(id=1)效果同樣.
>>> Question.objects.get(pk=1)
<Question: What's up?>

# 看看咱們自定義的方法用起來怎麼樣
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# 讓咱們試試主鍵查詢
>>> q = Question.objects.get(pk=1)

# 顯示全部與q對象有關係的choice集合,目前是空的,尚未任何關聯對象。
>>> q.choice_set.all()
<QuerySet []>

# 建立3個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對象可經過API訪問和他們關聯的Question對象
>>> c.question
<Question: What's up?>

# 一樣的,Question對象也可經過API訪問關聯的Choice對象
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# API會自動進行連表操做,經過雙下劃線分割關係對象。連表操做能夠無限多級,一層一層的鏈接。
# 下面是查詢全部的Choices,它所對應的Question的發佈日期是今年。(重用了上面的current_year結果)
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# 使用delete方法刪除對象
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

 

admin後臺管理站點

Django爲你提供了一個基於項目model建立的一個後臺管理站點admin。

這個界面只給站點管理員使用,並不對大衆開放。雖然admin的界面可能不是那麼美觀,功能不是那麼強大,內容不必定符合你的要求,

可是它是免費的、現成的,而且仍是可定製的,有完善的幫助文檔。

1. 建立管理員用戶

首先,咱們須要經過下面的命令,建立一個能夠登陸admin站點的用戶:

$ python manage.py createsuperuser
Email address: qianyi@123.com
Password:
Password (again):
The password is too similar to the email address.
Bypass password validation and create user anyway? [y/N]: n
Password:
Password (again):
(0.000) INSERT INTO `auth_user` (`password`, `last_login`, `is_superuser`, `username`, `first_name`, `last_name`, `email`, `is_staff`, `is_active`, `date_joined`) VALUES ('pbkdf2_sha256$120000$hxqaIpS92d
rd$eAOzMV+PAlgAmpWe32pUCCbnor4W1qw/Y7ygVwxdsrg=', NULL, 1, 'qianyi', '', '', 'qianyi@123.com', 1, 1, '2019-08-06 14:39:18.192940'); args=['pbkdf2_sha256$120000$hxqaIpS92drd$eAOzMV+PAlgAmpWe32pUCCbnor4W1q
w/Y7ygVwxdsrg=', None, True, 'qianyi', '', '', 'qianyi@123.com', True, True, '2019-08-06 14:39:18.192940']
Superuser created successfully.

 

2. 啓動開發服務器

服務器啓動後,在瀏覽器訪問http://127.0.0.1:8000/admin/。你就能看到admin的登錄界面了:

3.進入admin站點

利用剛纔創建的帳戶,登錄admin,你將看到以下的界面:

 

當前只有兩個可編輯的內容:groups和users。它們是django.contrib.auth模塊提供的身份認證框架。

4. 在admin中註冊投票應用

如今還沒法看到投票應用,必須先在admin中進行註冊,告訴admin站點,請將polls的模型加入站點內,接受站點的管理。

打開polls/admin.py文件,加入下面的內容:

from django.contrib import admin
from polls import models admin.site.register(models.Question) admin.site.register(models.Choice) # Register your models here.

點擊「Questions」,進入questions的修改列表頁面。這個頁面會顯示全部的數據庫內的questions對象,你能夠在這裏對它們進行修改。

看到下面的What's new?了麼?它就是咱們先前建立的一個question對象,而且經過__str__方法的幫助

這裏須要注意的是:

  • 頁面中的表單是由Question模型自動生成的。
  • 不一樣的模型字段類型(DateTimeField, CharField)會表現爲不一樣的HTML input框類型。
  • 每個DateTimeField都會自動生成一個可點擊連接。日期是Today,並有一個日曆彈出框;時間是Now,並有一個通用的時間輸入列表框。

 

在頁面的底部,則是一些可選項按鈕:

  • delete:彈出一個刪除確認頁面
  • save and add another:保存當前修改,並加載一個新的空白的當前類型對象的表單。
  • save and continue editing:保存當前修改,並從新加載該對象的編輯頁面。
  • save:保存修改,返回當前對象類型的列表頁面。

在頁面的右上角,點擊History按鈕,你會看到你對當前對象的全部修改操做都在這裏有記錄,包括修改時間和操做人員,以下圖所示:

視圖和模板

一個視圖就是一個頁面,一般提供特定的功能,使用特定的模板。

編寫視圖

打開polls/views.py文件,輸入下列代碼:

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    # render()函數的第一個位置參數是請求對象(就是view函數的第一個參數),第二個位置參數是模板。還能夠有一個可選的第三參數,
    # 一個字典,包含須要傳遞給模板的數據。最後render函數返回一個通過字典數據渲染過的模板封裝而成的HttpResponse對象。
    return render(request, 'polls/index.html', context)

def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

polls/urls.py文件中加入下面的url模式,將其映射到咱們上面新增的視圖

urlpatterns = [
    path('', views.index, name='index'),
# ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

快捷方式:get_object_or_404()

get_object_or_404()方法將一個Django模型做爲第一個位置參數,後面能夠跟上任意個數的關鍵字參數,若是對象不存在則彈出Http404錯誤。

一樣,還有一個get_list_or_404()方法,和上面的get_object_or_404()相似,只不過是用來替代filter()函數,當查詢列表爲空時彈出404錯誤。

(filter是模型API中用來過濾查詢結果的函數,它的結果是一個列表集。而get則是查詢一個結果的方法,和filter是一個和多個的區別!)

編寫模板

polls/templates/polls/index.html:

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

 

 polls/detail.html

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

 

刪除模板中硬編碼的URLs

polls/index.html文件中,還有一部分硬編碼存在,也就是href裏的「/polls/」部分:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

設想若是你在urls.py文件裏修改了路由表達式,那麼你全部的模板中對這個url的引用都須要修改,這是沒法接受的!

使用前面給urls定義了一個name別名,能夠用它來解決這個問題。具體代碼以下

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

Django會在polls.urls文件中查找name='detail'的url,具體的就是下面這行:

path('<int:question_id>/', views.detail, name='detail'),

  舉個栗子,若是你想將polls的detail視圖的URL更換爲polls/specifics/12/,那麼你不須要在模板中從新修改url地址了,

僅僅只須要在polls/urls.py文件中,將對應的正則表達式改爲下面這樣的就好了,全部模板中對它的引用都會自動修改爲新的連接:

# 添加新的單詞'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),

  

URL names的命名空間

本教程例子中,只有一個app也就是polls,可是在現實中很顯然會有5個、10個、更多的app同時存在一個項目中。Django是如何區分這些app之間的URL name呢?

答案是使用URLconf的命名空間。在polls/urls.py文件的開頭部分,添加一個app_name的變量來指定該應用的命名空間:

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
# ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

如今,讓咱們將代碼修改得更嚴謹一點,將polls/templates/polls/index.html中的

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

 修改成

<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
相關文章
相關標籤/搜索