基本常用命令
django-admin
manage
- python manage.py startapp myapp:創建一個App,其中myapp為App名稱;
- python manage.py runserver 127.0.0.1:8000:啟動Django項目,其中127.0.0.1:8000為項目訪問地址及端口
- python manage.py shell:以終端命令交互的方式啟動Django項目
- python manage.py test:執行Django測試用例,默認為myproject/myapp/tests.py中的用例
- python manage.py makemigrations:創建數據模型變更記錄,當數據模型發生變化時,會在myproject/migrations目錄下生成新的形如"0001_initial.py"的文件
- python manage.py migrate:數據庫遷移,當settings中配置好數據庫后,執行此命令會在數據庫中生成相應的數據表結構
Django架構
MVC & MTV

Model數據模型
|
數據存取層,定義系統的數據表結構
|
View視圖模塊
|
建立用戶與系統的連接頁面,用戶通過request發送請求給Controller,再由Controller分發到指定的路由,經過Model層的數據存取,最終將數據渲染到指定模板文件,並最終呈現到頁面中,由視圖和模板組成
|
Controller控制模塊
|
將用戶提交的request分發給View模塊的視圖函數
|
MTV

Model數據模型
|
數據存取層,定義系統的數據表結構、數據的存取,通過View模塊聯接
|
View視圖模塊
|
業務邏輯層,包括數據模型的存取及調用適當的模板文件的相關邏輯,類型於模型與模板之間的橋梁
|
Template模板文件
|
表現層,渲染View層的數據並最終呈現在頁面中
|
運行流程
URLconf
常用方法:(django.urls模塊)
方法
|
說明
|
示例
|
path
|
指定的地址為確定的地址,不支持正則匹配
|
path("", views.index)
|
re_path
|
指定的地址為不確定的地址,支持正則匹配
|
re_path("user/(?P\d+)", views.user)
|
include
|
path("api/", include("allauth.urls"))
|
|
reverse
|
反向生成URL地址,其參數為urls.py中視圖函數對應的name參數
|
reverse('add')
|
參數說明
- name:類似於網址的別名,可用於templates、models、views中得到對應的網址,只要這個名字不變,即使網址發生了變化,也能通過這個名字找到正確的網址;
在模板文件中的應用




在視圖函數中的應用

- include:路由轉發,用於從根路由出發,將app所屬url請求轉發到子urls.py中,path/re_path中使用;
方法一:只指定urls模塊的字符串

方法二:同時指定urls(模塊字符串、app_name)、命名空間(當存在多個app時,指定namespace很有必要)

api/urls.py

mblog/urls.py

在template中使用命名空間

在views中使用命令空間

Template
配置

TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', # 默認模板引擎 'DIRS': [], # 默認為app目錄下的templates目錄 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
- BACKEND:模板引擎,可使用指定的模板引擎,如django.template.backends.jinja2.Jinga2
- DIRS:模板文件目錄,默認為app目錄下的templates目錄,可指定特定的目錄,常用方式[os.path.join(BASE_DIR, "templates")]
View中的使用
到底使用哪個模板進行渲染,由views.py的視圖函數決定

from django.shortcuts import render # Create your views here. def index(request): return render(request, "index.html")

使用現有模板框架(此處以bootstrap3為例)
目前接觸到使用bootstrap3的方法有兩種,分別是靜態引用和動態加載
- 靜態引用
1.安裝bootstrap3
pip install django-bootstrap3
2.在settings.py的INSTALLED_APPS中添加bootstrap3應用

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', 'bootstrap3', ]
3.在模板文件中引用bootstrap3

<head> <meta charset="UTF-8"> {% load bootstrap3 %} {% bootstrap_css %} {% bootstrap_javascript %} <title>MySite</title> </head>
- 動態加載
直接通過bootstrap官網,找到CDN並復制到<head></head>標簽中

# 在https://getbootstrap.com/docs/3.4/getting-started/#download網址中,找到BootstrapCDN, # 將其復制到模板文件的<head></head>標簽中即可 # jQuery框架同樣可以采用此種方式加載 <head> <meta charset="UTF-8"> <title>MySite</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous"> <!-- 可選的 Bootstrap 主題文件(一般不用引入) --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap-theme.min.css" integrity="sha384-6pzBo3FDv/PJ8r2KRkGHifhEocL+1X2rVCTTkUfGk7/0pbek5mMa1upzvWbrUbOZ" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"> </script> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"> </script> </head>
支持的語法
{%%}{{}}
{% if exp %}
|
條件控制語法,語法同python,使用{% endif %}結束條件控制,可配合{% else %}、{% elif %}使用形成分支結構
|
{% if username %}
登出
{% else %}
登錄
{% endif %}
|
{% for %}
|
循環控制語法,語法同python,使用{% endfor %}結束循環控制
|
{% for user in usersusers %}
{{ user.name }}
{% endfor %}
|
可配合{% empty %}顯示特定內容,內部變量:forloop
注意:內部變量forloop只在{% for %}循環內生效,當檢測到{% endfor %}時,forloop即失效不可用
|
{% for user in usersusers %}
{{ user.name }}
{% empty %}
There are no athletes. Only computer programmers.
{% endfor %}
|
|
forloop.counter:表示循環次數,從1開始開始計數
|
{% for user in users %}
{{ forloop.counter }}: {{ user }}
{% endfor %}
|
|
forloop.counter0:也表示循環次數,但是從0開始計數
|
{% for user in users %}
{{ forloop.counter0 }}: {{ user }}
{% endfor %}
|
|
forloop.revcounter:循環中剩余元素數量,初始值為元素總數,最后一次為1
|
||
forloop.revcounter0:也是循環剩余元素數量,不過初始值為元素總數-1,最后一次為0
|
||
forloop.first:Bool類型,第一次循環時返回True,否則返回False
|
{% for object in objects %}
{% if forloop.first %}
{% else %}
{% endif %}
{{ object }}
{% endfor %}
|
|
forloop.last:Bool類型,最后一次循環時返回True,否則返回False
|
||
{% extends %}
|
html繼承語法,base.html為html模板文件,類比於Python的基類
|
{% extends "base.html" %}
|
{% include %}
|
html引用語法,將其他html模板文件導入到該html文件中,一般用於網頁的頁眉、頁腳
|
{% include "header.html" %}
{% include "footer.html" %}
|
{% load %}
|
html加載靜態文件/框架
|
{% load bootstrap3 %}
{% load static %}
|
{% block %}
|
用於繼承及實現;在base.html模板文件中定義了{% block %}{% endblock %}之后,所有繼承base.html文件的模板文件都必須實現{% block %}{% endblock %}修飾的內容
|
base.html
{% block title %}{% endblock %}
index.html
{% extends "base.html" %}
{% block title %}MySite{% endblock %}
|
使用靜態文件
Django中,使用靜態文件的方式,可以一度程序上提高性能。而Django的靜態文件默認存儲在templates/static中
settings.py中的默認配置

# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/'

# Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, "static"), ]

<hr> {% load static %} # 加載靜態文件 <img src="{% static 'images/logo.png' %}" width=100> <em>Copyright 2016 a <a href="http://www.baidu.com">http://www.baidu.com</a>. All rights reserved. </em>
常用過濾器
過濾器名稱
|
用法
|
示例
|
capfirst
|
將字符串首字母大寫
|
{{ msg | capfirst }},如果msg內容為"django",則html中顯示將變成"Django"
|
center/ljust/rjust
|
為字符串加上指定空格后居中、靠左、靠右對齊
|
{{ msg | center: "15" }}
|
cut
|
在字符串中刪除指定的子字符串
|
{{ msg | cut: " " }},如果msg內容為" How are you",則html中顯示將變成"Howareyou"
|
date
|
設置日期的顯示格式
|
{{ value | date:"D d M Y" }},value為datetime的標准格式。可利用date來設置顯示格式
|
default
|
如果沒有值,就使用默認值
|
{{ msg | default:"沒有信息" }}
|
first/last
|
只取出列表數據中的第一個/最后一個元素
|
{{ values | first }} {{ values | last }},values為列表元素
|
floatformat
|
以指定的浮點數格式顯示數據
|
{{ value | floatformat:3 }},如果value為123.45678,則html中顯示將變成123.457
|
linebreaks
|
將文字內容中的換行符號轉換成HTML的
和
|
{{ msg | linebreaks }}
|
linebreadsbr
|
將文字內容中的換行符號轉換成HTML的
|
{{ msg | linebreaksbr }}
|
linenumber
|
為顯示的文字內容加上行號
|
{{ msg | linenumber}}
|
lower/upper
|
將顯示的文字內容轉換成小寫/大寫
|
{{ msg | lower }} {{ msg | upper }}
|
random
|
以隨機數將數據內容顯示出來
|
{{ values | random }}
|
safe
|
標記字符串為安全的,不需要再處理轉義字符
|
{{ msg | safe }}
|
striptags
|
去掉文字內容中的所有HTML標簽
|
{{ msg | striptags }}
|
truncatechars
|
把過長的字符串裁切成指定的長度,並將最后3個字符轉換成...
|
{{ msg | truncatchars:12 }}
|
yesno
|
按照值的內容True/False/None,顯示出有意義的內容
|
{{ value | yesno:"是,否,可能吧" }}
|
Models
Django中,models負責定義數據模型,通過views中的視圖函數與Django Models機制的交互,調用相應的驅動程序接口,實現對數據的存取
配置

# Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }

# mysql DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 數據庫驅動 'NAME': 'event', # 數據庫名稱(需要先創建) 'USER': 'root', # 數據庫用戶名 'PASSWORD': '123456', # 數據庫密碼 'HOST': '', # 數據庫主機,留空默認為localhost 'PORT': '3306', # 數據庫端口 } }

# postgresql DATABASES = { "default": { "ENGINE": "django.db.backends.postgresql_psycopg2", "NAME": "event", "USER": "postgres", "PASSWORD": "123456", "HOST": "localhost", "PORT": "5432", } }
定義模型類
- 每一個模型都是一個python類,並且繼承自django.db.models.Model類
- 該模型的每個屬性都表示一個數據庫表的字段
- 每個模型自動生成一個auto_increment的id字段,並作為主鍵
- 內部類Meta:用於指定一些特殊屬性,如ordering(排序規則)、unique_together(聯合外鍵)

from django.db import models class Poll(models.Model): name = models.CharField(max_length=200, null=False) create_at = models.DateField(auto_now_add=True) enabled = models.BooleanField(default=False) class Meta: ordering = ("-create_at",) # 定義結果的排序規則,此處按照創建時間進行排序,"-"表示按照倒序排序 def __str__(self): return self.name class PollItem(models.Model): poll = models.ForeignKey(Poll, on_delete=models.CASCADE) # 指定PollItem表的外鍵為Poll name = models.CharField(max_length=200, null=False) image_url = models.CharField(max_length=200, null=True, blank=True) vote = models.PositiveIntegerField(default=0) def __str__(self): return self.name
使用admin后台管理數據模型

from django.contrib import admin from mysite.models import Poll admin.site.register(Poll)

from django.contrib import admin from mysite.models import Poll, PollItem class PollAdmin(admin.ModelAdmin): list_display = ("name", "create_at", "enabled") ordering = ("-create_at",) class PollItemAdmin(admin.ModelAdmin): list_display = ("poll", "name", "vote", "image_url") ordering = ("poll", ) admin.site.register(Poll, PollAdmin) admin.site.register(PollItem, PollItemAdmin)
- list_display:可迭代對象,其中每個對象對應數據模型中定義的屬性,如:list_display = ("name", "create_at", "enabled")
- search_fields:搜索器,可迭代對象,同上,如:search_fields = ("name", "poll")
- ordering:同上,如:ordering = ("-create_at")
- list_filter:過濾器,可迭代對象,如:list_filter = ("enabled")
常用Model屬性類型
admin.Model提供的常用屬性
AutoField
|
一個IntegerField類型的自增字段類型
|
BooleanField
|
用於存入布爾類型的數據(True/False)
|
CharField
|
用於存放字符型的數據,需要指定數據長度,max_length
|
DateField
|
日期類型,必須是"YYYY-MM-DD"格式
|
DateTimeField
|
日期時間類型,必須是"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"
|
DecimalField
|
定點數類型,max_digits指定最大值,decimal_places指定小數位數
|
EmailField
|
電子郵件類型
|
FilePathField
|
文件路徑類型
|
FloatField
|
浮點數類型
|
IntegerField
|
integer類型,數值范圍從-2147483648g到2147483647
|
BigIntegerField
|
用於存放大的integer類型
|
GenericIPAddressField
|
存放IP地址類型,支持IPv4和IPv6的字符串格式
|
NullBooleanField
|
類似BooleanField類型,但允許為NULL
|
PositiveIntegerField
|
integer類型,范圍0~2147483647
|
TextField
|
用於存放文本類型的數據
|
TimeField
|
時間類型,必須是"HH:MM[:ss[.uuuuuu]]"格式
|
URLField
|
用於存放URL地址
|
BinaryField
|
存儲原始二進制數據的字段
|
在models.ForeignKey(Poll, on_delete=models.CASCADE)中on_delete參數,支持五種操作:
- on_delete=models.CASCADE:刪除被引用的對象時,此對象也一並被刪除

# models.py from django.db import models class AClass(models.Model): name = models.CharField(max_length=40) def __str__(self): return self.name class AListClass(models.Model): a_name = models.ForeignKey(AClass, on_delete=models.CASCADE) name = models.CharField(max_length=40) def __str__(self): return self.name # admin.py from django.contrib import admin from mysite.models import AClass, AListClass class AListClassAdmin(admin.ModelAdmin): list_display = ("name", "a_name") # AListClass表顯示name字段及外鍵AClass的name字段 admin.site.register(AClass) admin.site.register(AListClass, AListClassAdmin)



- on_delete=models.PROTECT:禁止刪除並拋出異常ProtectdError

# models.py from django.db import models class BClass(models.Model): name = models.CharField(max_length=40) def __str__(self): return self.name class BListClass(models.Model): b_name = models.ForeignKey(BClass, on_delete=models.PROTECT) name = models.CharField(max_length=40) def __str__(self): return self.name # admin.py from django.contrib import admin from mysite.models import BClass, BListClass class BListClassAdmin(admin.ModelAdmin): list_display = ("name", "b_name") admin.site.register(BClass) admin.site.register(BListClass, BListClassAdmin)




- on_delete=models.SET_NULL:當被引用的對象被刪除后,依賴它的其他對象的該字段都被設置為NULL;設置此操作時,字段必須設置null=True來允許字段值為NULL

# models.py from django.db import models class CClass(models.Model): name = models.CharField(max_length=40) def __str__(self): return self.name class CListClass(models.Model): c_name = models.ForeignKey(CClass, on_delete=models.SET_NULL, null=True) # 必須指定null=True允許字段值為空 name = models.CharField(max_length=40) def __str__(self): return self.name # admin.py from django.contrib import admin from mysite.models import CClass, CListClass class CListClassAdmin(admin.ModelAdmin): list_display = ("name", "c_name") admin.site.register(CClass) admin.site.register(CListClass, CListClassAdmin)


- on_delete=models.SET_DEFAULT:當被引用的對象被刪除后,依賴它的其他對象的該字段都被設置為默認值;設置此操作時,字段必須設置default參數

# models.py from django.db import models class DClass(models.Model): name = models.CharField(max_length=40) def __str__(self): return self.name class DListClass(models.Model): d_name = models.ForeignKey(DClass, on_delete=models.SET_DEFAULT, default=None, null=True) name = models.CharField(max_length=40) def __str__(self): return self.name # admin.py from django.contrib import admin from mysite.models import DClass, DListClass class DListClassAdmin(admin.ModelAdmin): list_display = ("name", "d_name") admin.site.register(DClass) admin.site.register(DListClass, DListClassAdmin)


- on_delete=models.DO_NOTHING:什么事兒都不做?如果你的數據庫后端強制引用完整性,它將引發一個IntegrityError ,除非你手動添加一個ON DELETE 約束給數據庫