感謝自強學堂
[TOC]
Django簡介
urls.py
網址入口,關聯到對應的view.py中的一個函數(或者generic類),訪問網址就對應一個函數
view.py
處理用戶發出的請求,從urls.py中對應過來,通過選人templates中的網頁,可將內容顯示,比如,登陸后的用戶名,用戶請求的數據,輸出到網頁
models.py
與數據庫關聯,存入或讀取數據的時候會用到這個
forms.py
表單,用戶在瀏覽器上輸入數據提交,對數據的驗證工作以及輸入框的生成等工作
templates文件夾
views.py 中的函數渲染templates中的Html模板,得到動態內容的網頁,當然可以用緩存來提高速度。
admin.py
后臺,可以用很少的代碼量,擁有一個強大的后臺
settings.py
Django 的設置,配置文件,比如Debug開關,靜態文件位置等
Django環境搭建
Django 1.5.x 支持 Python 2.6.5 Python 2.7, Python 3.2 和 3.3.
Django 1.6.x 支持 Python 2.6.X, 2.7.X, 3.2.X 和 3.3.X
Django 1.7.x 支持 Python 2.7, 3.2, 3.3, 和 3.4 (注意:Python 2.6 不支持了)
Django 1.8.x 支持 Python 2.7, 3.2, 3.3, 3.4 和 3.5. (長期支持版本 LTS)
Django 1.9.x 支持 Python 2.7, 3.4 和 3.5. 不支持 3.3 了
Django 1.10.x 支持 Python 2.7, 3.4 和 3.5.
Django 1.11.x 下一個長期支持版本,將于2017年4月發布
更詳細的可以參考這里一般來說,選擇長期支持版本比較好。
使用最新版本的問題就是,可能要用到的一些第三方插件沒有及時更新,無法正常使用這些三方包。
如果是學習,可以選擇目前的 Django 1.8.x 來進行,遇到問題也容易找到答案。
當然如果需要新版本的功能也可以使用新版本,畢竟 Django 1.9 以后admin界面還是更漂亮些
Django基礎部分
安裝Django
安裝pip
ubuntu sudo apt-get install python-pip
centos yum -y install python-pip
升級pip
pip install --upgrade pip
利用pip安裝Django
(sudo) pip install Django
或者 (sudo) pip install Django==1.8.16 或者 pip install Django==1.10.3
搭建多個互不干擾的開發環境
# 安裝:
(sudo) pip install virtualenv
mkdir myproject
cd myproject
virtualenv --no-site-packages test
#命令virtualenv就可以創建一個獨立的Python運行環境,我們還加上了參數--no-site-packages,這樣,已經安裝到系統Python環境中的所有第三方包都不會復制過來,這樣,我們就得到了一個不帶任何第三方包的“干凈”的Python運行環境。
source test/bin/activate
#命令行提示符的最前方,會提示當前所在的python環境
#然后就可以在此環境下 進行開發/測試等
deactivate #退出環境
Django的基本命令(請牢牢記住,不能tab)
新建一個django project
django-admin.py startproject zixue
新建app
python manage.py startapp app-name
或 django-admin.py startapp app-name
#一般一個項目有多個app, 當然通用的app也可以在多個項目中使用。
同步數據庫
python manage.py syncdb
#注意:Django 1.7.1及以上的版本需要用以下命令
python manage.py makemigrations
python manage.py migrate
#這種方法可以創建表,當你在models.py中新增了類時,運行它就可以自動在數據庫中創建表了,不用手動創建。
#備注:對已有的 models 進行修改,Django 1.7之前的版本的Django都是無法自動更改表結構的,不過有第三方工具 south,
使用開發服務器
開發服務器,即開發時使用,一般修改代碼后會自動重啟,方便調試和開發,但是由于性能問題,建議只用來測試,不要用在生產環境。
python manage.py runserver
# 當提示端口被占用的時候,可以用其它端口:
python manage.py runserver 8001
python manage.py runserver 9999
(當然也可以kill掉占用端口的進程)
# 監聽所有可用 ip (電腦可能有一個或多個內網ip,一個或多個外網ip,即有多個ip地址)
python manage.py runserver 0.0.0.0:8000
# 如果是外網或者局域網電腦上可以用其它電腦查看開發服務器
# 訪問對應的 ip加端口,比如 http://172.16.20.2:8000
清空數據庫
python manage.py flush
創建超級管理員
python manage.py createsuperuser
# 按照提示輸入用戶名和對應的密碼就好了郵箱可以留空,用戶名和密碼必填
# 修改 用戶密碼可以用:
python manage.py changepassword username
導入導出數據
python manage.py dumpdata appname > appname.json
python manage.py loaddata appname.json
Django羨慕的環境終端
python manage.py shell
數據庫命令行
python manage.py dbshell
Django 會自動進入在settings.py中設置的數據庫,如果是 MySQL 或 postgreSQL,會要求輸入數據庫用戶密碼。
在這個終端可以執行數據庫的SQL語句。如果您對SQL比較熟悉,可能喜歡這種方式。
更多命令
終端上輸入 python manage.py 可以看到詳細的列表,在忘記子名稱的時候特別有用。
Django的視圖與網址
創建項目
django-admin.py startproject mysite
創建成功后,目錄如下
mysite
├── manage.py
└── mysite
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
新建了一個 mysite 目錄,其中還有一個 mysite 目錄,這個子目錄 mysite 中是一些項目的設置settings.py 文件,總的urls配置文件 urls.py 以及部署服務器時用到的 wsgi.py 文件, __init__.py 是python包的目錄結構必須的,與調用有關。
新建應用(app) 名字叫learn
python manage.py startapp learn #learn只是一個app的名稱
把我們新定義的app加到settings.py中的INSTALL_APPS
mysite/mysite/settings.py
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'learn',
)
#備注,這一步是干什么呢? 新建的 app 如果不加到 INSTALL_APPS 中的話, django 就不能自動找到app中的模板文件(app-name/templates/下的文件)和靜態文件(app-name/static/中的文件) , 后面你會學習到它們分別用來干什么.
定義視圖函數 (訪問頁面的內容)
修改 應用 learn 中的view.py
#coding:utf-8
from django.http import HttpResponse
def index(request):
return HttpResponse(u'歡迎')
#第一行是聲明編碼為utf-8, 因為我們在代碼中用到了中文,如果不聲明就報錯.
#第二行引入HttpResponse,它是用來向網頁返回內容的,就像Python中的 print 一樣,只不過 HttpResponse 是把內容顯示到網頁上。
#我們定義了一個index()函數,第一個參數必須是 request,與網頁發來的請求有關,request 變量里面包含get或post的內容,用戶瀏覽器,系統等信息#在里面(后面會講,先了解一下就可以)。
#函數返回了一個 HttpResponse 對象,可以經過一些處理,最終顯示幾個字到網頁上。
#那問題來了,我們訪問什么網址才能看到剛才寫的這個函數呢?怎么讓網址和函數關聯起來呢?
定義視圖函數相關的URL(即,訪問什么網址,對應什么內容)
打開mysite下的urls.py
#Django 1.7
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'learn.views.index'), # new
# url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
)
#Django1.8 以上
from django.conf.urls import url
from django.contrib import admin
from learn import views as learn_views # new
urlpatterns = [
url(r'^$', learn_views.index), # new
url(r'^admin/', admin.site.urls),
]
#開啟python測試
python manage.py runserver
#允許遠程訪問
python manager.py runserver 0.0.0.0:8000 (指定IP和端口)
視圖與網址進階
新建項目
新建應用
同上
修改應用下的views.py
from django.shortcuts import render
from django.http import HttpResponse
def add(request):
a = request.GET['a']
b = request.GET['b']
c = int(a)+int(b)
return HttpResponse(str(c))
#注:request.GET 類似于一個字典,更好的辦法是用 request.GET.get('a', 0) 當沒有傳遞 a 的時候默認 a 為 0
修改項目下的urls.py
from django.conf.urls import url
from django.contrib import admin
from learn import views as learn_views
from calc import views as calc_views
urlpatterns = [
url(r'^add/$',calc_views.add,name='add'),
url(r'^$',learn_views.index),
url(r'^admin/', admin.site.urls),
]
打開網址
IP:8000/add/?a=1&b=2
采用add/2/4的方式
進入cala/views.py 定義函數
def add2(request,a,b):
c = int(a) + int(b)
return HttpResponse(str(c))
修改項目下的urls.py
Django 1.7.X
url(r'^add/(\d+)/(\d+)/$', 'calc.views.add2', name='add2'),
Django 1.8+
url(r'^add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
#我們可以看到網址中多了 (\d+), 正則表達式中 \d 代表一個數字,+ 代表一個或多個前面的字符,寫在一起 \d+ 就是一個或多個數字,用括號括起來的意思是保存為一個子組(更多知識請參見 Python 正則表達式),每一個子組將作為一個參數,被 views.py 中的對應視圖函數接收。
訪問 http://127.0.0.1:8000/add/4/5/ 就可以看到和剛才同樣的效果
URL name詳解
url(r'^add/$', calc_views.add,name='add'), 這里的name='add' 是用來干什么的呢?
簡單的來說,name可以在template,models,views中得到對應的網址,相當于給網址去了名字,只要名字不變,網址變不變都是可以獲取到的
修改calc/views.py (應用calc已經在setting.py中INSTALLED_APPS導入,不然模板是找不到的)
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
return render(request, 'home.html')
...
#render 是渲染模板
然后新建templates文件夾,在新建home.html
<!DOCTYPE html>
<html>
<head>
<title>自強學堂</title>
</head>
<body>
<a href="/add/4/5/">計算 4+5</a>
</body>
</html>
修改項目中的urls.py
...
from learn import views as learn_views
from calc import views as calc_views
urlpatterns = [
url(r'^$',calc_views.index,name='home'),
url(r'^add/$',calc_views.add,name='add'),
url(r'^add/(\d+)/(\d+)/$',calc_views.add2,name='add2'),
url(r'^admin/', admin.site.urls),
]
然后運行服務,訪問頁面就會出現 計算4+5 的鏈接
<a href="/add/4/5/">計算 4+5</a>
如果這樣寫“死網址”,會使得在改了網址(正則)后,模板(template),視圖(views.py,用以用于跳轉),模型(models.py,可以用用于獲取對象對應的地址)用了此網址的,都得進行相應的更改,修改的代價很大,一不小心,有的地方沒改過來,就不能用了。
那么有沒有更優雅的方式來解決這個問題呢?
不帶參數的:
{% url 'name' %}
帶參數的:參數可以是變量名
{% url 'name' 參數 %}
例如:
<a href="{% url 'add2' 4 5 %}">link</a>
當 urls.py 進行更改,前提是不改 name(這個參數設定好后不要輕易改),獲取的網址也會動態地跟著變,比如改成:
url(r'^new_add/(\d+)/(\d+)/$', calc_views.add2, name='add2')
#add 變成了 new_add,但是后面的 name='add2' 沒改,這時 {% url 'add2' 4 5 %} 就會渲染對應的網址成 /new_add/4/5/
另外,比如用戶收藏夾中收藏的URL是舊的,如何讓以前的 /add/3/4/自動跳轉到現在新的網址呢?
要知道Django不會幫你做這個,這個需要自己來寫一個跳轉方法:
具體思路是,在 views.py 寫一個跳轉的函數:
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse # django 1.4.x - django 1.10.x
# from django.urls import reverse # new in django 1.10.x
def old_add2_redirect(request, a, b):
return HttpResponseRedirect(
reverse('add2', args=(a, b))
)
urls.py中
url(r'^add/(\d+)/(\d+)/$', calc_views.old_add2_redirect),
url(r'^new_add/(\d+)/(\d+)/$', calc_views.add2, name='add2'),
這樣,假如用戶收藏夾中有 /add/4/5/ ,訪問時就會自動跳轉到新的 /new_add/4/5/ 了
templates
創建一個項目和app
django-admin.py startproject zqxt_tmpl
cd zqxt_tmpl
python manage.py startapp learn
把 learn 加入到 settings.INSTALLED_APPS中
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'learn',
)
打開 learn/views.py 寫一個首頁的視圖
from django.shortcuts import render
def home(request):
return render(request, 'home.html')
創建templates/home.html
然后將輸入和網址對應
from django.conf.urls import include, url
from django.contrib import admin
from learn import views as learn_views
urlpatterns = [
url(r'^$', learn_views.home, name='home'),
url(r'^admin/', include(admin.site.urls)),
]
#Django1.10+
#url(r'^admin/', admin.site.urls), #include
項目中有多個應用,所以就會有多個templates以及多個index.html
默認情況下Django是不會去區分的,最先找到那個就顯示那個,所以如果為了區分的話
就在各個應用的templates下進行在劃分
project
├── app1
|....
│ ├── templates
│ │ └── app1
│ │ ├── index.html
│ │ └── search.html
├── app2
|.....
│ ├── templates
│ │ └── app2
│ │ ├── index.html
│ │ └── poll.html
模版補充知識點
網站模板的設計,一般的,我們做網站有一些通用的部分,比如導航,底部,訪問統計代碼等等
可以寫一個 base.html 來包含這些通用文件(include)
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}默認標題{% endblock %} - test</title>
</head>
<body>
{% include 'nav.html' %}
{% block content %}
<div>這里是默認內容,所有繼承自這個模板的,如果不覆蓋就顯示這里的默認內容。</div>
{% endblock %}
{% include 'bottom.html' %}
{% include 'tongji.html' %}
</body>
</html>
#如果需要,寫足夠多的 block 以便繼承的模板可以重寫該部分,include 是包含其它文件的內容,就是把一些網頁共用的部分拿出來,重復利用,改動的時候也方便一些,還可以把廣告代碼放在一個單獨的html中,改動也方便一些,在用到的地方include進去。其它的頁面繼承自 base.html 就好了,繼承后的模板也可以在 block 塊中 include 其它的模板文件。
templatesde 進階
主要講解模板中的循環,條件判斷,常用的標簽,過濾器的使用
基本字節的顯示
views.py
# -*- coding: utf-8 -*-
from django.shortcuts import render
def home(request):
string = u"學習Django,用它來建網站"
return render(request, 'home.html', {'string': string})
#在視圖中我們傳遞了一個字符串名稱是 string(引號內的表示可悲html調用的) 到模板 home.html
home.html
{{ string }}
for循環
views.py
def home(request):
TutorialList = ["HTML", "CSS", "jQuery", "Python", "Django"]
return render(request, 'home.html', {'TutorialList': TutorialList})
home.html
{% for i in TutorialList %}
{{ i }}
{% endfor %}
for循環要有個結束標記
一般的變量聲明使用{{}}
功能性的 比如循環,條件判斷等使用{% %}
顯示字典的內容
views.py
def home(request):
info_dict = {'site': u'學堂', 'content': u'IT技術教程'}
return render(request, 'home.html', {'info_dict': info_dict})
home.html
站點:{{ info_dict.site }} 內容:{{ info_dict.content }}
遍歷字典
{% for key, value in info_dict.items %}
{{ key }}: {{ value }}
{% endfor %}
條件判斷和 for 循環
views.py
def home(request):
List = map(str, range(100))# 一個長度為100的 List
return render(request, 'home.html', {'List': List})
home.html
{% for item in List %}
{{ item }}, #每次結束都會在值得后面添加最后,最后一個依然會添加 99,
{% endfor %}
所以,如何判讀是不是最后一次遍歷呢
forloop.last變量 判斷是否為最后一項,如果是則為真,反之。
{% for item in List %}
{{ item }}{% if not forloop.last %}, {% endif %} ##判斷不是最后一個則加逗號
{% endfor %}
for循環的其他變量
變量 | 描述 |
---|---|
forloop.counter | 索引從1開始計算 |
forloop.counter0 | 索引從0開始計算 |
forloop.revcounter | 索引最大長度到1 |
forloop.revcounter0 | 索引最大長度到0 |
forloop.first | 遍歷元素為第一項時,返回真 |
forloop.last | 遍歷元素為最后一項,返回真 |
forloop.parentloop | 用在嵌套for循環中,獲取上一層for循環的forloop |
當列表可能為空的時候用 for empty
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}</li>
{% empty %}
<li>抱歉,列表為空</li>
{% endfor %}
</ul>
模板上得到視圖對應的網址
# views.py
def add(request, a, b):
c = int(a) + int(b)
return HttpResponse(str(c))
# urls.py
urlpatterns = patterns('',
url(r'^add/(\d+)/(\d+)/$', 'app.views.add', name='add'),
)
# template html
{% url 'add' 4 5 %}
#name 的方便之處。
#當urls文件發生改變的生后,并不需要去修改html
#因為html中我們使用的是name 也就是add
還可以使用 as 語句將內容取別名(相當于定義一個變量)
{% url 'some-url-name' arg arg2 as the_url %}
<a href="{{ the_url }}">鏈接到:{{ the_url }}</a>
模板中使用邏輯操作
==, !=, >=, <=, >, < 這些比較都可以在模板中使用
{% if var >= 90 %}
成績優秀,自強學堂你沒少去吧!學得不錯
{% elif var >= 80 %}
成績良好
{% elif var >= 70 %}
成績一般
{% elif var >= 60 %}
需要努力
{% else %}
不及格啊,大哥!多去自強學堂學習啊!
{% endif %}
and, or, not, in, not in 也可以在模板中使用
{% if num <= 100 and num >= 0 %}
num在0到100之間
{% else %}
數值不在范圍之內!
{% endif %}
判斷是否在某個列表中
{% if 'ZILI' in List %}
自強學堂在名單中
{% endif %}
模板中獲取當前網址,當前用戶名等
修改setting
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
...
'django.template.context_processors.request',
...
],
},
},
]
然后在模板中就可以調用了
獲取用戶
{{ request.user }}
判斷登錄
{% if request.user.is_authenticated %}
{{ request.user.username }},您好!
{% else %}
請登陸,這里放登陸鏈接
{% endif %}
獲取網址
{{ request.path}}
獲取當前get 參數
{{ request.GET.urlencode}}
合并到一起舉例
<a href="{{ request.path }}?{{ request.GET.urlencode }}&delete=1">當前網址加參數 delete</a>
模型(數據庫)
Django模型適合數據庫相關的,與數據庫相關的代碼一般寫在models.py中,Django支持 sqlite3,Mysql,PostgreSQL等數據庫,只要在setting.py中進行配置即可
django-admin.py startproject learn_models # 新建一個項目
cd learn_models # 進入到該項目的文件夾
django-admin.py startapp people # 新建一個 people 應用(app)
一個項目包含多個應用,一個應用也可以在多個項目中
添加新的項目到settings.py -- INSTALLED_APPS下
修改models.py
與數據庫相關的代碼一般寫在models.py中
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
#新建了一個Person類,繼承自models.Model, 一個人有姓名和年齡。這里用到了Field,
#上面代碼其實就相當于原生sql
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"name" varchar(30) NOT NULL,
"age" int() NOT NULL
);
表名person_person由Django自動生成:項目名稱+下劃線+小寫類名
同步數據庫
(默認使用SQLite3.0 無需配置)
Django 1.9 默認使用
python manage.py makemigrations
python manage.py migrate
#同步數據庫 migrate代替老版本的syscdb
#這兩行命令會對models.py 進行檢測,自動發現需要更改的,應用到數據庫中去。
127.0.0.1:8000/admin就可以看到簡易的CMS系統了
同步數據庫命令返回值
[root/myProject/learn_models] ]$python manage.py makemigrations
Migrations for 'people':
0001_initial.py:
- Create model Person
[root/myProject/learn_models] ]$python manage.py migrate
Operations to perform:
Apply all migrations: people, sessions, auth, contenttypes, admin
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying people.0001_initial... OK
Applying sessions.0001_initial... OK
[root/myProject/learn_models] ]$
#創建superuser
python manage.py createsuperuser
Username (leave blank to use 'root'):
Email address: ****@qq.com
Password:
Password (again):
Superuser created successfully.
#此時我們登錄 ipaddress:8000/admin 就能看到簡單的CMS
Django shell操作數據表
Django中的交互式shell來進行數據庫的增刪改查等操作
增加 查詢
python manage.py shell
#數據增加
In [1]: from people.models import Person
In [2]: Person.objects.create(name='lizili',age=18)#新加數據
Out[2]: <Person: Person object>
#數據庫查詢
#查詢所有,返回一個列表,無對象返回空
In [6]: Person.objects.all()
Out[6]: [<Person: Person object>]
#查詢指定對象
In [4]: a=Person.objects.get(id=1)
In [17]: a.name
Out[17]: 'lizili'
#每次都要賦值才能查找,很麻煩,所以可以去modules.py中對語句進行修改
from django.db import models
# Create your models here.
class Person(models.Model):
name =models.CharField(max_length=30)
age = models.IntegerField()
def __str__(self):
return u'name:%s , age:%s' % (self.name,self.age)
#這樣每次就可以直接查詢了
In [1]: from people.models import Person
In [2]: Person.objects.get(id=1)
Out[2]: <Person: name:lizili , age:26>
新建數據
#1
Person.objects.create(name=name,age=age)
#2
p = Person(name="WZ", age=23)
p.save()
#3
p = Person(name="TWZ")
p.age = 23
p.save()
#4這種方法是防止重復很好的方法,但速度要相對慢些
#返回一個元組,第一個為Person對象,第二個為True或False, 新建時返回的是True, 已經存在時返回False.
Person.objects.get_or_create(name="WZT", age=23)
查詢數據
Person.objects.all()#查詢所有
Person.objects.all()[:10] #切片操作,獲取10個人,不支持負索引,切片可以節約內存
Person.objects.get(name='lizili') #關鍵字
#get方法
#get是用來獲取一個對象的,如果需要獲取滿足條件的一些人,就要用到filter
#filter方法
Person.objects.filter(name="abc") # 等于Person.objects.filter(name__exact="abc") 名稱嚴格等于 "abc" 的人
Person.objects.filter(name__iexact="abc") # 名稱為 abc 但是不區分大小寫,可以找到 ABC, Abc, aBC,這些都符合條件
Person.objects.filter(name__contains="abc") # 名稱中包含 "abc"的人
Person.objects.filter(name__icontains="abc") #名稱中包含 "abc",且abc不區分大小寫
Person.objects.filter(name__regex="^abc") # 正則表達式查詢
Person.objects.filter(name__iregex="^abc")# 正則表達式不區分大小寫
#filter是找出滿足條件的,當然也有排除符合某條件的
Person.objects.exclude(name__contains="WZ") # 排除包含 WZ 的Person對象
Person.objects.filter(name__contains="abc").exclude(age=23) # 找出名稱含有abc, 但是排除年齡是23歲的
自定義Field
以后補
數據表的更改
當數據庫設計完后,發現不滿意,需要更改,添加/刪除字段。
Django 1.7+
#直接修改models.py 然后執行以下語句即可
python manage.py makemigrations
python manage.py migrate
#會出現一下提示,選 1
# 1) Provide a one-off default now (will be set on all existing rows)
# 2) Quit, and let me add a default in models.py
#新增了字段,但是原來已經的數據沒有這個字段,
#當你這個字段沒有默認值,又不能為空的時候它就不知道怎么做
#需要選擇 1 來指定一個 “一次性的值” 給已有字段。
QuerySet API
數據庫接口相關的接口(QuerySet API)
從數據庫中查詢出來的結果一般是一個集合,這個集合叫做 QuerySet