第四章 模板
1.標簽
(1)if/else
{% if %} 標簽檢查(evaluate)一個變量,如果這個變量為真(即,變量存在,非空,不是布爾值假),系統會
顯示在 {% if %} 和 {% endif %} 之間的任何內容,例如:
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% endif %}
{% else %} 標簽是可選的:
{% if today_is_weekend %} <p>Welcome to the weekend!</p> {% else %} <p>Get back to work.</p> {% endif %}
{% if %} 標簽接受 and , or 或者 not 關鍵字來對多個變量做判斷 ,或者對變量取反( not )
(2)for
{% for %} 允許我們在一個序列上迭代。 與Python的 for 語句的情形類似,循環語法是 for X in Y ,Y是要迭代的序列而X是在每一個特定的循環中使用的變量名稱。 每一次循環中,模板系統會渲染在 {% for %} 和
{% endfor %} 之間的所有內容。
例如,給定一個運動員列表 athlete_list 變量,我們可以使用下面的代碼來顯示這個列表:
<ul> {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %} </ul>
給標簽增加一個 reversed 使得該列表被反向迭代:
{% for athlete in athlete_list reversed %}
...
{% endfor %}
可以嵌套使用 {% for %} 標簽:
{% for athlete in athlete_list %} <h1>{{ athlete.name }}</h1> <ul> {% for sport in athlete.sports_played %} <li>{{ sport }}</li> {% endfor %} </ul> {% endfor %}
Django不支持退出循環操作。 如果我們想退出循環,可以改變正在迭代的變量,讓其僅僅包含需要迭代的項目。 同理,Django也不支持continue語句,我們無法讓當前迭代操作跳回到循環頭部。
在每個`` {% for %}``循環里有一個稱為`` forloop`` 的模板變量。這個變量有一些提示循環進度信息的屬性。
forloop.counter 總是一個表示當前循環的執行次數的整數計數器。 這個計數器是從1開始的,所以在第一次循環時 forloop.counter 將會被設置為1。
例子:
def lists(request): lists = [1,2,3,4,5] return render(request,"lists.html",{'lists':lists})
{% for item in lists %} <p>{{ forloop.counter }}:{{ item }}</p> {% endfor %}
結果:
1:1
2:2
3:3
4:4
5:5
-->>forloop.counter0 類似於 forloop.counter ,但是它是從0計數的。 第一次執行循環時這個變量會被設置為0。
-->>forloop.revcounter0 類似於 forloop.revcounter ,但它以0做為結束索引。 在第一次執行循環時,該變量會被置為序列的項的個數減1
forloop.first 是一個布爾值,如果該迭代是第一次執行,那么它被置為````
{% for item in lists %} {% if forloop.first %} <li style="color: red">{{ forloop.counter }}:{{ item }}</li> {% else %} <li>{{ forloop.counter }}:{{ item }}</li> {% endif %} {% endfor %}
結果:

forloop.last 是一個布爾值;在最后一次執行循環時被置為True。
forloop.parentloop 是一個指向當前循環的上一級循環的 forloop 對象的引用(在嵌套循環的情況下)。
2.注釋
就像HTML或者Python,Django模板語言同樣提供代碼注釋。 注釋使用 {# #} :
{# This is a comment #}
如果要實現多行注釋,可以使用`` {% comment %}`` 模板標簽,就像這樣:
{% comment %}
This is a
multi‐line comment.
{% endcomment %}
3.過濾器
模板過濾器是在變量被顯示前修改它的值的一個簡單方法。 過濾器使用管道字符,
{{ name|lower }} #它功能是轉換文本為小寫。
過濾管道可以被* 套接* ,既是說,一個過濾器管道的輸出又可以作為下一個管道的輸入,如此下去
{{ my_list|first|upper }} #查找列表的第一個元素並將其轉化為大寫。
4.locals() 技巧
如果你是個喜歡偷懶的程序員並想讓代碼看起來更加簡明,可以利用 Python 的內建函數 locals() 。它返回的字典對所有局部變量的名稱與值進行映射。 因此,前面的視圖可以重寫成下面這個樣子:
def lists(request): lists = [1,2,3,4,5] return render(request,"lists.html",locals())
locals() 的值,它囊括了函數執行到該時間點時所定義的一切變量
5.模板繼承
(1)定義基礎模板base.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> </head> <body> <h1>My helpful timestamp site</h1> {% block content %}{% endblock %} {% block footer %} <hr> <p>Thanks for visiting my site</p> {% endblock %} </body> </html>
這個叫做 base.html 的模板定義了一個簡單的 HTML 框架文檔,我們將在所有頁面中使用。 子模板的作用就是重載、添加或保留那些塊的內容。
所有的 {% block %} 標簽告訴模板引擎,子模板可以重載這些部分。 每個 {% block %} 標簽所要做的是告訴模板引擎,該模板下的這一塊內容將有可能被子模板覆蓋。
(2)子模板current_time.html
{% extends 'base.html' %} {% block title %}The current time{% endblock%} {% block content %} <p>It is now {{ current_date }}</p> {% endblock %}
(3)views.py
from django.shortcuts import HttpResponse,render import datetime def current_datetime(request): current_date = datetime.datetime.now() return render(request,'cuttent_datetime.html',{'current_date':current_date})
以下是其工作方式:在加載 current_datetime.html 模板時,模板引擎發現了 {% extends %} 標簽,模板引擎立即裝載其父模板,即本例中的 base.html 。此時,模板引擎注意到 base.html 中的三個 {% block %} 標簽,並用子模板的內容替換這些 block 。因此,引擎將會使用我們在 { block title %} 中定義的標題,對 {% block content %} 也是如此。 所以,網頁標題一塊將由 {% block title %} 替換,同樣地,網頁的內容一塊將由 {% block content %} 替換。注意由於子模板並沒有定義 footer 塊,模板系統將使用在父模板中定義的值。 父模板 {% block %} 標簽中的內容總是被當作一條退路。繼承並不會影響到模板的上下文。 換句話說,任何處在繼承樹上的模板都可以訪問到你傳到模板中的每一個模板變量。
如果在模板中使用 {% extends %} ,必須保證其為模板中的第一個模板標記。 否則,模板繼承將不起作
用。
一般來說,基礎模板中的 {% block %} 標簽越多越好。 記住,子模板不必定義父模板中所有的代碼塊,因
此你可以用合理的缺省值對一些代碼塊進行填充,然后只對子模板所需的代碼塊進行(重)定義。 俗話
說,鈎子越多越好。
如果發覺自己在多個模板之間拷貝代碼,你應該考慮將該代碼段放置到父模板的某個 {% block %} 中。
如果你需要訪問父模板中的塊的內容,使用 {{ block.super }} 這個標簽吧,這一個魔法變量將會表現出
父模板中的內容。 如果只想在上級代碼塊基礎上添加內容,而不是全部重載,該變量就顯得非常有用了。
不允許在同一個模板中定義多個同名的 {% block %} 。 存在這樣的限制是因為block 標簽的工作方式是雙
向的。 也就是說,block 標簽不僅挖了一個要填的坑,也定義了在 父 模板中這個坑所填充的內容。如果模
板中出現了兩個相同名稱的 {% block %} 標簽,父模板將無從得知要使用哪個塊的內容。
{% extends %} 對所傳入模板名稱使用的加載方法和 get_template() 相同。 也就是說,會將模板名稱被添
加到 TEMPLATE_DIRS 設置之后。
多數情況下, {% extends %} 的參數應該是字符串,但是如果直到運行時方能確定父模板名,這個參數也
可以是個變量。 這使得你能夠實現一些很酷的動態功能。
第五章 模型
1.MTV and MVC
M:數據存取部分,由django數據庫層處理,本章要講述的內容。
由於 C 由框架自行處理,而 Django 里更關注的是模型(Model)、模板(Template)和視圖(Views),Django 也被稱為MTV 框架。在 MTV 開發模式中:
M:代表模型(Model),即數據存取層。 該層處理與數據相關的所有事務: 如何存取、如何驗證有效性、包含哪些行為以及數據之間的關系等
T:代表模板(Template),即表現層。 該層處理與表現相關的決定: 如何在頁面或其他類型文檔中進行顯示。
V:代表視圖(View),即業務邏輯層。 該層包含存取模型及調取恰當模板的相關邏輯。 你可以把它看作模型與模板之間的橋梁。
2.設置數據庫為Mysql
在settings里面修改配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django', #數據庫名字 'USER': 'root', #賬號 'PASSWORD': '123456', #密碼 'HOST': '127.0.0.1', #IP 'PORT': '3306', #端口 } }
在app的init.py里面導入pymysql模塊
import pymysql pymysql.install_as_MySQLdb()
設置好后打開 python manage.py shell 來進行測試。輸入一下命令,如果沒有報錯說明,說明數據庫配置是正確的
>>> from django.db import connection >>> cursor = connection.cursor()
3.第一個模型
書籍/作者/出版商 數據庫
一個作者有姓,有名及email地址。
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() class Book(models.Model): title = models.CharField(max_length=100) publication_date = models.DateField() authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher,on_delete = models.CASCADE)
打開shell,添加publisher

當我們打印整個publisher列表時,我們沒有得到想要的有用信息,只需要為Publisher對象添加一個__str__方法 ,就可以對Publisher對象更容易理解
from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() def __str__(self): return self.name class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() def __str__(self): return '%s%s'%(self.first_name,self.last_name) class Book(models.Model): title = models.CharField(max_length=100) publication_date = models.DateField() authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher,on_delete = models.CASCADE) def __str__(self): return self.title

4.數據過濾
可以使用`` filter()`` 方法對數據進行過濾:

也可以傳入多個參數
Publisher.objects.filter(country="U.S.A.", state_province="CA")
魔術般的操作
Publisher.objects.filter(name__contains="Apr")

5.獲取單個對象


如果查詢沒有返回結果也會拋出異常:
6.數據排序

我們可以對任意字段進行排序,如果需要以多個字段為標准進行排序(第二個字段會在第一個字段的值相同的情況下被使用到),使用多個參數就可以了,如下:

限制返回的數據

7.更新和刪除對象

update()方法會返回一個整型數值,表示受影響的記錄條數。 在上面的例子中,這個值是2
刪除數據庫中的對象只需調用該對象的delete()方法即可:

第六章 Django站點管理
1.創建admin用戶
python manage.py createsuperuser
訪問:http://127.0.0.1:8000/admin/,輸入用戶名,密碼登錄進入管理界面

可以看到只有Groutps和Users

要向讓app book里面的models顯示在這里面,只需把book注冊到admin
book app下的admin.py
from django.contrib import admin from book import models # Register your models here. admin.site.register(models.Author) admin.site.register(models.Book) admin.site.register(models.Publisher)
然后就可以在管理界面看到

中文顯示的方法:Meta
class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: verbose_name_plural = "出版社" def __str__(self): return self.name
2.Admin工作原理
3.設置字段可選
你或許會發現管理工具有個限制:編輯表單需要你填寫每一個字段,然而在有些情況下,你想要某些字段是可選的。 舉個例子,我們想要Author模塊中的email字段成為可選,即允許不填。 在現實世界中,你可能沒有為每個作者登記郵箱地址。
class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(null=True,blank=True)
這些代碼告訴Django,作者的郵箱地址允許輸入一個空值
4.自定義字段標簽
在編輯頁面中,每個字段的標簽都是從模塊的字段名稱生成的。規則很簡單: 用空格替換下划線;首字母大寫
舉個例子,說明如何將Author.email的標簽改為e-mail,中間有個橫線。
class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(null=True,blank=True,verbose_name='e-mail')
改之前

改之后

5.自定義ModelAdmi類
迄今為止,我們做的blank=True、null=True和verbose_name修改其實是模塊級別,而不是管理級別的。 也就是說,這些修改實質上是構成模塊的一部分,並且正好被管理工具使用,而不是專門針對管理工具的。
(1)自定義列表
默認情況下,Author下面只顯示每個作者的姓名

我們可以在這基礎上改進,添加其它字段,從而改變列表的顯示。比如說:在這個列表中可以看到作者的郵箱地址,為了達到這個目的,我們將為Author模塊定義一個ModelAdmin類。 這個類是自定義管理工具的關鍵,其中最基本的一件事情是允許你指定列表中的字段。
修改admin.py
from django.contrib import admin from book import models class AuthorAdmin(admin.ModelAdmin): list_display = ('first_name','last_name','email') admin.site.register(models.Author,AuthorAdmin) admin.site.register(models.Book) admin.site.register(models.Publisher)
可以看到如下效果

解釋一下代碼:
我們修改了admin.site.register()調用,在Author后面添加了AuthorAdmin。你可以這樣理解:用AuthorAdmin選項注冊Author模塊。
(2)添加快速查詢欄
class AuthorAdmin(admin.ModelAdmin): list_display = ('first_name','last_name','email') search_fields = ('first_name','last_name')
在頁面頂端看到一個查詢欄

(3)添加過濾器
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) admin.site.register(models.Author,AuthorAdmin) admin.site.register(models.Book,BookAdmin) admin.site.register(models.Publisher)
可以看到右邊有filter,Django為日期型字段提供了快捷過濾方式,它包含:今天、過往七天、當月和今年

class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date'
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',)
(5)自定義編輯表單
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) fields = ('title', 'authors', 'publisher', 'publication_date')
改之前:
改之后:

通過fields這個選項,你可以排除一些不想被其他人編輯的fields 只要不選上不想被編輯的field(s)即可。
fields = ('title', 'authors', 'publisher')
class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) filter_horizontal = ('authors',)

加之后,明顯方便多了

filter_vertical = ('authors',)

class BookAdmin(admin.ModelAdmin): list_display = ('title','publisher','publication_date') list_filter = ('publication_date',) date_hierarchy = 'publication_date' ordering = ('-publication_date',) filter_vertical = ('authors',) raw_id_fields = ('publisher',)
效果:


第七章 用戶、用戶組和權限
注釋:
