前提
已安裝python3.X
安裝完django
創(chuàng)建項(xiàng)目
#在命令行執(zhí)行
#HelloWorld 項(xiàng)目名稱
django-admin startproject HelloWorld
#進(jìn)入項(xiàng)目
cd HelloWorld
目錄說明
|-- HelloWorld
| |-- init.py #空文件,告訴Python這是一個(gè)Python的包
| |-- asgi.py #一個(gè) ASGI 兼容的 Web 服務(wù)器的入口,以便運(yùn)行你的項(xiàng)目。
| |-- settings.py #該 Django 項(xiàng)目的設(shè)置/配置。
| |-- urls.py #該 Django 項(xiàng)目的 URL 聲明; 一份由 Django 驅(qū)動(dòng)的網(wǎng)站"目錄"。
|-- wsgi.py-- manage.py #一個(gè) WSGI 兼容的 Web 服務(wù)器的入口,以便運(yùn)行你的項(xiàng)目。
運(yùn)行項(xiàng)目
#確保已進(jìn)入HelloWorld目錄下
#多種運(yùn)行項(xiàng)目的方式
python manage.py runserver
# 指定端口
python manage.py runserver 8080
# 任意ip接入
python manage.py runserver 0.0.0.0:8080
# 這里和settings.py的配置ALLOWED_HOSTS = []
# 不一樣的地方在于,這個(gè)是服務(wù)器監(jiān)聽的IP,IP不對(duì)無(wú)法連接到服務(wù);
# ALLOWED_HOSTS是已經(jīng)連接到服務(wù),但連接的IP不在ALLOWED_HOSTS范圍內(nèi)就無(wú)法正常提供服務(wù)
運(yùn)行完項(xiàng)目訪問 127.0.0.1:8000,就能看到一個(gè)綠色的小火箭!
視圖和URL配置
注意import
HelloWorld 目錄新建一個(gè) views.py 文件
#目錄:HelloWorld/HelloWorld/views.py
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world ! ")
綁定 URL 與視圖函數(shù)
from django.conf.urls import url
from . import views
urlpatterns = [
url(, views.hello),
]
path() 函數(shù)
path(route, view, kwargs=None, name=None)
- route: 字符串,表示 URL 規(guī)則,與之匹配的 URL 會(huì)執(zhí)行對(duì)應(yīng)的第二個(gè)參數(shù) view。(可用正則表達(dá)式)
- view: 用于執(zhí)行與正則表達(dá)式匹配的 URL 請(qǐng)求。
- kwargs: 視圖使用的字典類型的參數(shù)。
- name: 用來(lái)反向獲取 URL。
route:
- 對(duì)應(yīng)端口號(hào)后的路徑
- 例如:http://127.0.0.1:8000/hello/,則route = “hello/”
views:
- from . import views導(dǎo)入的
- views.hello 對(duì)應(yīng)的是views中的一個(gè)函數(shù)
kwargs:
- 少用到,暫不學(xué)
模板
為什么需要模板?
在上文views的hello中使用 django.http.HttpResponse() 來(lái)輸出 "Hello World!",該方式將數(shù)據(jù)與視圖混合在一起,不符合 Django 的 MVC 思想
模板:模板是一個(gè)文本,用于分離文檔的表現(xiàn)形式和內(nèi)容。
建立模板
在 HelloWorld 目錄底下創(chuàng)建 templates 目錄并建立 runoob.html
項(xiàng)目結(jié)構(gòu)
HelloWorld/
|-- HelloWorld
| |-- __init__.py
| |-- __init__.pyc
| |-- settings.py
| |-- settings.pyc
| |-- urls.py
| |-- urls.pyc
| |-- views.py
| |-- views.pyc
| |-- wsgi.py
| `-- wsgi.pyc
|-- manage.py
`-- templates
`-- runoob.html
HelloWorld/templates/runoob.html 文件代碼
<h1>{{ hello }}</h1>
修改HelloWorld/settings.py
修改 TEMPLATES 中的 DIRS 為 [os.path.join(BASE_DIR, 'templates')]
- 注意導(dǎo)入:import os
...
import os
...
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR, 'templates')]
...
},
]
...
修改 views.py
from django.shortcuts import render
def runoob(request):
context = {}
context['hello'] = 'Hello World!'
return render(request, 'runoob.html', context)
#context可換成{"name":views_name}
修改HelloWorld/HelloWorld/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('runoob/', views.runoob),
]
模板語(yǔ)法
views中的變量與html中變量“綁定”
view:{"HTML變量名" : "views變量名"}
HTML:{{變量名}}
#html頁(yè)面中
<h1>{{HTML變量名}}</h1>
#在views中
return render(request, 'runoob.html', {"HTML變量名" : "views變量名"})
網(wǎng)頁(yè)導(dǎo)航和頁(yè)腳
使用子模版繼承父模版,減少代碼冗余
父模板
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>base</title>
</head>
<body>
<h1>Hello World!</h1>
<p>父模板測(cè)試</p>
{% block mainbody %}
<p>base template</p>
{% endblock %}
</body>
</html>
子模板
{%extends "base.html" %}
- 繼承了一個(gè)父模板(網(wǎng)頁(yè))
父模板的{% block 名稱%}{% 名稱%}
- 相當(dāng)于留空位給子模版新增內(nèi)容
- 標(biāo)簽是可以被繼承者們替換掉的部分
{%extends "base.html" %}
{% block mainbody %}
<p>繼承了 base.html 文件</p>
{% endblock %}
模型
Django 模型使用自帶的 ORM。
- 對(duì)象關(guān)系映射(Object Relational Mapping,簡(jiǎn)稱 ORM )用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z(yǔ)言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換。

# 安裝 mysql 驅(qū)動(dòng)
pip install pymysql
在數(shù)據(jù)庫(kù)軟件中新建數(shù)據(jù)庫(kù)
-- runoob 數(shù)據(jù)庫(kù)名
create database runoob default charset=utf8;
修改 HelloWorld/HelloWorld/settings.py 中的DATABASES
DATABASES = {
'default':
{
'ENGINE': 'django.db.backends.mysql', # 數(shù)據(jù)庫(kù)引擎
'NAME': 'runoob', # 數(shù)據(jù)庫(kù)名稱
'HOST': '127.0.0.1', # 數(shù)據(jù)庫(kù)地址,本機(jī) ip 地址 127.0.0.1
'PORT': 3306, # 端口
'USER': 'root', # 數(shù)據(jù)庫(kù)用戶名
'PASSWORD': '123456', # 數(shù)據(jù)庫(kù)密碼
}
}
告訴 Django 使用 pymysql 模塊連接 mysql 數(shù)據(jù)庫(kù)
# 在與 settings.py 同級(jí)目錄下的 __init__.py 中引入模塊和進(jìn)行配置
import pymysql
pymysql.install_as_MySQLdb()
定義模型
Django 規(guī)定,如果要使用模型,必須要?jiǎng)?chuàng)建一個(gè) app。
#命令行中輸入
# TestModel與manage.py在同級(jí)目錄下
django-admin.py startapp TestModel
創(chuàng)建表
修改 TestModel/models.py 文件
# models.py
from django.db import models
class Test(models.Model):
name = models.CharField(max_length=20)
類名代表了數(shù)據(jù)庫(kù)表名(Test)
類里面的字段代表數(shù)據(jù)表中的字段(name)
數(shù)據(jù)類型則由CharField(相當(dāng)于varchar)、DateField(相當(dāng)于datetime)
max_length 參數(shù)限定長(zhǎng)度。
告訴django我們安裝的app
在 settings.py 中找到INSTALLED_APPS
- setting.py在HelloWorld目錄下
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'TestModel', # 添加此項(xiàng)
)
命令行中運(yùn)行
python manage.py migrate # 創(chuàng)建表結(jié)構(gòu)
python manage.py makemigrations TestModel # 讓 Django 知道我們?cè)谖覀兊哪P陀幸恍┳兏?python manage.py migrate TestModel # 創(chuàng)建表結(jié)構(gòu)
#如果代碼有報(bào)異常,繼續(xù)往下翻。
第二行代碼執(zhí)行后

第三行代碼執(zhí)行后

該表結(jié)構(gòu)
Django 會(huì)自動(dòng)添加一個(gè) id 作為主鍵。

異常
django.db.utils.OperationalError:(1045,"Access denied for user 'root'@'localhost'
- 確保用戶名和密碼正確后再試一次
- 可以用命令行測(cè)試數(shù)據(jù)庫(kù)連接
- 開啟服務(wù):net start 服務(wù)名(例如:mysql5.7)
- mysql -h 主機(jī)名(ip) -u 用戶名 -P 端口 -p
數(shù)據(jù)庫(kù)操作
在 HelloWorld 目錄中添加 testdb.py 文件,并修改 urls.py
#urls.py
from django.urls import path
from . import views,testdb
urlpatterns = [
path('runoob/', views.runoob),
path('testdb/', testdb.testdb),
]
添加數(shù)據(jù)
from django.http import HttpResponse
from TestModel.models import Test
# 數(shù)據(jù)庫(kù)操作
def testdb(request):
test1 = Test(name='runoob')
test1.save()
return HttpResponse("<p>數(shù)據(jù)添加成功!</p>")
啟動(dòng)服務(wù)器并訪問
python manage.py runserver #啟動(dòng)服務(wù)器
#訪問 http://127.0.0.1:8000/testdb/
#看到頁(yè)面輸出:數(shù)據(jù)添加成功
查看數(shù)據(jù)庫(kù)

獲取數(shù)據(jù)、刪除、修改
#獲取
# 通過objects這個(gè)模型管理器的all()獲得所有數(shù)據(jù)行,相當(dāng)于SQL中的SELECT * FROM
list = Test.objects.all()
# filter相當(dāng)于SQL中的WHERE,可設(shè)置條件過濾結(jié)果
response2 = Test.objects.filter(id=1)
# 獲取單個(gè)對(duì)象
response3 = Test.objects.get(id=1)
# 限制返回的數(shù)據(jù) 相當(dāng)于 SQL 中的 OFFSET 0 LIMIT 2;(分頁(yè))
Test.objects.order_by('name')[0:2]
#數(shù)據(jù)排序
Test.objects.order_by("id")
# 上面的方法可以連鎖使用
Test.objects.filter(name="runoob").order_by("id")
#修改
#save() 或 update():
# 修改其中一個(gè)id=1的name字段,再save,相當(dāng)于SQL中的UPDATE
test1 = Test.objects.get(id=1)
test1.name = 'Google'
test1.save()
# 另外一種方式
Test.objects.filter(id=1).update(name='Google')
# 修改所有的列
Test.objects.all().update(name='Google')
#刪除
# 刪除id=1的數(shù)據(jù)
test1 = Test.objects.get(id=1)
test1.delete()
# 另外一種方式
Test.objects.filter(id=1).delete()
# 刪除所有數(shù)據(jù)
Test.objects.all().delete()
異常
問題:修改模型后無(wú)法更新數(shù)據(jù)庫(kù)表結(jié)構(gòu),刪除后再執(zhí)行命令也不行。參考
解決:
刪除app/migrations/目錄下 “_pycache_” 文件
刪除app下面目錄migrations下面除了init.py其他的所有文件
刪除對(duì)應(yīng)數(shù)據(jù)庫(kù)中django_migrations表中app名稱所在的列
(或者delete from django_migrations where app=‘yourappname’;),解決無(wú)法生成表
表單
HTML表單是網(wǎng)站交互性的經(jīng)典方式。
HTTP協(xié)議以"請(qǐng)求-回復(fù)"的方式工作。
- 客戶發(fā)送請(qǐng)求時(shí),可以在請(qǐng)求中附加數(shù)據(jù)。
- 服務(wù)器通過解析請(qǐng)求,就可以獲得客戶傳來(lái)的數(shù)據(jù),并根據(jù)URL來(lái)提供特定的服務(wù)。
GET
創(chuàng)建一個(gè) search.py 文件,用于接收用戶的請(qǐng)求
#/HelloWorld/HelloWorld/search.py 文件
from django.http import HttpResponse
from django.shortcuts import render
#表單
def search_form(request):
return render(request,'search_form.html')
#接收請(qǐng)求數(shù)據(jù)
def search(request):
request.encoding='utf-8'
if('q' in request.GET and request.GET['q']):
message = '您搜索的內(nèi)容為:' + request.GET['q']
else:
message = '您提交了空表單'
return HttpResponse(message)
模板目錄 templates 中添加 search_form.html 表單
#/HelloWorld/templates/search_form.html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>form_test</title>
</head>
<body>
<form action="/search/" method="GET">
<input type="text" name="q">
<input type="submit" value="搜索">
</form>
</body>
</html>
urls.py 規(guī)則 添加以下代碼
使用url能匹配正則表達(dá)式(path好像不行)
...
from django.conf.urls import url
urlpatterns = [
...,
url(r'^search-form/$',search.search_form),
url(r'^search/$',search.search)
]
訪問 http://127.0.0.1:8000/search-form/,搜索后提交即可看到效果
GET請(qǐng)求 視圖顯示和請(qǐng)求處理分成兩個(gè)函數(shù)處理。
POST
提交數(shù)據(jù)時(shí)更常用POST方法。
- 一個(gè)URL和處理函數(shù),同時(shí)顯示視圖和處理請(qǐng)求。
Request對(duì)象
表單form通過HTTP POST方法提交請(qǐng)求,但是表單中可以沒有數(shù)據(jù)。
因此,不能使用語(yǔ)句if request.POST來(lái)判斷是否使用HTTP POST方法;
應(yīng)該使用if request.method == "POST"
路由
Django不會(huì)匹配域名和協(xié)議
舉例:
請(qǐng)求:訪問http://127.0.0.1:8000/polls/34/
Django項(xiàng)目到urls中順序進(jìn)行正則匹配/polls/34/,匹配到polls/,就切掉文本"polls/",剩余文本"34/"繼續(xù)進(jìn)行匹配
- path('polls/',include('polls.urls'))
- path('<int:question_id>/', views.detail, name='detail')
匹配到了views.detail
得到參數(shù)
question_id=34由<int:question_id>匹配生成。
- 使用尖括號(hào)“捕獲”這部分 URL,且以關(guān)鍵字參數(shù)的形式發(fā)送給視圖函數(shù)。
- 上述字符串的
:question_id>部分定義了將被用于區(qū)分匹配模式的變量名int:則是一個(gè)轉(zhuǎn)換器決定了應(yīng)該以什么變量類型匹配這部分的 URL 路徑。
路由簡(jiǎn)單的來(lái)說就是根據(jù)用戶請(qǐng)求的 URL 鏈接來(lái)判斷對(duì)應(yīng)的處理程序,并返回處理結(jié)果,
- URL 與 Django 的視圖建立映射關(guān)系。
Django 路由在 urls.py 配置,urls.py 中的每一條配置對(duì)應(yīng)相應(yīng)的處理方法。
Django 不同版本 urls.py 配置有點(diǎn)不一樣
Django1.1.x 版本
url() 方法:普通路徑和正則路徑均可使用,需要自己手動(dòng)添加正則首位限制符號(hào)。
from django.conf.urls import url # 用 url 需要引入
urlpatterns = [
url(r'^admin/$', admin.site.urls),
url(r'^index/$', views.index), # 普通路徑
url(r'^articles/([0-9]{4})/$', views.articles), # 正則路徑
]
Django 2.2.x 之后
- path:用于普通路徑,不需要自己手動(dòng)添加正則首位限制符號(hào),底層已經(jīng)添加。
- re_path:用于正則路徑,需要自己手動(dòng)添加正則首位限制符號(hào)。
from django.urls import re_path # 用re_path 需要引入
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index), # 普通路徑
re_path(r'^articles/([0-9]{4})/$', views.articles), # 正則路徑
]
總結(jié):Django1.1.x 版本中的 url 和 Django 2.2.x 版本中的 re_path 用法相同。
分組
正則還有分組的概念,但是在Django中把分組分為兩種:
- 無(wú)名分組
- 有名分組
無(wú)名分組
無(wú)名分組:普通的正則匹配中加上()
作用:在后端的views上,會(huì)得到一個(gè)分組的參數(shù)
- 訪問views.login函數(shù)(下方)的參數(shù)除了request,還需要添加一個(gè)參數(shù)(名字隨意)
- 要設(shè)置幾個(gè)參數(shù)就要多幾個(gè)分組
以下代碼訪問:login/2222,那么xxx的值為2222
#urls.py
urlpatterns = [
url(r'^login/([0-9]{4})$',views.login),
]
#views.py
def login(request,xxx):
print(xxx)
#search2.py
def divede_group_year(request,year):
return HttpResponse('您的選擇是:%s' % year)
def divede_group_month(request,year,month):
return HttpResponse('選擇的月份是:%s-%s' %(year,month))
#urls.py
from django.urls import path,re_path
...
urlpatterns = [
...,
# 記得添加結(jié)束標(biāo)簽 $
re_path(r'^divede-group/([0-9]{4})/$',search2.divede_group_year),
re_path(r'^divede-group/([0-9]{4})/([0-9]{2})/$',search2.divede_group_month)
]


有名分組
有名分組: 有名分組其實(shí)就是在無(wú)名的分組的基礎(chǔ)上加上了名字
語(yǔ)法為:(?P<名字> 正則表達(dá)式)
#urls.py
...,
urlpatterns = [
...,
url(r'^login/(?P<year>[0-9]{4})$',views.login),
]
#views.py
...,
def login(request,year):
print(year)
舉例
#search2.py
from django.http import HttpResponse
def divede_group_name(request,name):
return HttpResponse('有名分組:%s' %(name))
#urls.py
from . import search2
re_path(r'^divede-group/(?P<name>[a-z]{4})/$',search2.divede_group_name)

視圖函數(shù)的參數(shù)name 要和有名參數(shù)的名字name一致,否則會(huì)報(bào)錯(cuò)!
注意:官方規(guī)定,有名分組和無(wú)名分組不能一起使用!
路由分發(fā)(include)
問題:
- 項(xiàng)目里多個(gè)app目錄共用一個(gè) urls 容易造成混淆
- 后期維護(hù)不方便
解決:
- 使用路由分發(fā)(include),讓每個(gè)app目錄都單獨(dú)擁有自己的 urls。
步驟:
- 1、在每個(gè) app 目錄里都創(chuàng)建一個(gè) urls.py 文件。
- 2、在項(xiàng)目名稱目錄下的 urls 文件里,統(tǒng)一將路徑分發(fā)給各個(gè) app 目錄。
舉例:
有兩個(gè)app,都有index.html頁(yè)面
- 如果在項(xiàng)目的urls中配置,則會(huì)造成混淆
- 且如果有太多的url,則維護(hù)十分難
所以應(yīng)該把各種的url分給各自去管理
#路由 未分發(fā)
#項(xiàng)目主目錄下的urls.py
urlpatterns = [
url(r'^app-one/index/$',views.index),
url(r'^app-two/index/$',views.index)
]
新建兩個(gè)app
# 語(yǔ)法:python manage.py startapp <app名稱>
# 命令行中運(yùn)行
python manage.py startapp app01
python manage.py startapp app02
app1目錄下
1.views文件
from django.http import HttpResponse
def index(request):
return HttpResponse('app01的index頁(yè)面!')
2.新建urls.py文件
from . import views
from django.conf.urls import url #沒有引入會(huì)報(bào)錯(cuò):NameError: name 'url' is not defined django
urlpatterns = [
url(r'^index/$',views.index)
]
app2目錄下
1.views文件
from django.http import HttpResponse
def index(request):
return HttpResponse('app2:index!')
2.新建urls.py文件
from . import views
from django.conf.urls import url
urlpatterns = [
url(r'^index/$',views.index)
]
項(xiàng)目主目錄下的urls.py
urlpatterns = [
url(r'^app-one/',include('app01.urls')),
url(r'^app-two/',include('app02.urls'))
]
訪問
注意訪問路徑:
- app-one/index/
- 對(duì)照上面的urls.py文件,就能理解路由轉(zhuǎn)發(fā)了!
app01
運(yùn)行項(xiàng)目:python manage.py runserver

app02

反向解析
目的:解耦
- 路由層的 url 發(fā)生變化,就需要去更改對(duì)應(yīng)的視圖層和模板層的 url,不便維護(hù)
反向解析
- 當(dāng)路由層 url 發(fā)生改變,在視圖層和模板層動(dòng)態(tài)反向解析出更改后的 url,免去修改的操作。
- 一般用在模板中的超鏈接及視圖中的重定向
問題舉例
#urls.py 中的一條url
...
url(r'^login/$',views.login)
...
#html頁(yè)面中的提交表單
<form action="/login/" method="P=post">
...
</form>
當(dāng)更改路由中的url時(shí),需要在html頁(yè)面也做相應(yīng)的更改!
解耦目的:只更改路由中的url,html中會(huì)自動(dòng)做出更改,我們無(wú)需去改變!
反向解析
方法:給路由器起別名
應(yīng)用:
1.普通路徑:name="路由別名
重定向:
- redirect(reverse("login"))
超鏈接:
- <form action="{% url 'login' %}" method="post">
2.正則路徑:無(wú)名分組
re_path(r"^login/([0-9]{2})/$", views.login, name="login")
重定向:
- reverse("路由別名",args=(符合正則匹配的參數(shù),))
- redirect(reverse("login",args=(10,)))
超鏈接:
- {% url "路由別名" 符合正則匹配的參數(shù) %}
- {% url 'login' 10 %}
3.正則路徑:有名分組
re_path(r"^login/(?P<year>[0-9]{4})/$", views.login, name="login")
重定向:
- reverse("路由別名",kwargs={"分組名":符合正則匹配的參數(shù)})
- redirect(reverse("login",kwargs={"year":3333}))
超鏈接:
- {% url "路由別名" 分組名=符合正則匹配的參數(shù) %}
- {% url 'login' year=3333 %}
命名空間
命名空間(英語(yǔ):Namespace)是表示標(biāo)識(shí)符的可見范圍。
一個(gè)標(biāo)識(shí)符可在多個(gè)命名空間中定義,它在不同命名空間中的含義是互不相干的。
一個(gè)新的命名空間中可定義任何標(biāo)識(shí)符,它們不會(huì)與任何重復(fù)的標(biāo)識(shí)符發(fā)生沖突,因?yàn)橹貜?fù)的定義都處于其它命名空間中。
存在問題:路由別名 name 沒有作用域,Django 在反向解析 URL 時(shí),會(huì)在項(xiàng)目全局順序搜索,當(dāng)查找到第一個(gè)路由別名 name 指定 URL 時(shí),立即返回。當(dāng)在不同的 app 目錄下的urls 中定義相同的路由別名 name 時(shí),可能會(huì)導(dǎo)致 URL 反向解析錯(cuò)誤。
解決:使用命名空間。
普通路徑
方式一:
#主目錄下的urls
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/',include('polls.urls'))
]
# polls中的urls.py
from django.urls import path
from . import views
app_name = 'polls' #命名空間
urlpatterns = [
...
# ex: /polls/5/
path('<int:question_id>/', views.detail, name='detail'),
...
]
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
方式二:
定義命名空間(include 里面是一個(gè)元組)
include(("app名稱:urls","app名稱"))
實(shí)例
path("app01/", include(("app01.urls","app01")))
path("app01/", include(("app02.urls","app02")))
起別名
path("login/", views.login, name="login")
調(diào)用
#重定向
redirect(reverse("app01:login")
#超鏈接
{% url "app名稱:路由別名" %}
視圖
每個(gè)視圖必須要做的只有兩件事:
- 返回一個(gè)包含被請(qǐng)求頁(yè)面內(nèi)容的
HttpResponse對(duì)象- 或者拋出一個(gè)異常,比如
Http404。
Admin 管理工具
介紹
Django 提供了基于 web 的管理工具。
Django 自動(dòng)管理工具是 django.contrib 的一部分。
在項(xiàng)目的 settings.py 中的 INSTALLED_APPS 可以看到
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
)
django.contrib是一套龐大的功能集,它是Django基本代碼的組成部分。
激活管理工具
在生成項(xiàng)目時(shí)會(huì)在 urls.py 中自動(dòng)設(shè)置好,我們只需去掉注釋即可。
配置如下
# urls.py
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
使用管理工具
創(chuàng)建超級(jí)用戶
# python manage.py createsuperuser
Username (leave blank to use 'root'): admin
Email address:
Password:admin
Password (again):
Superuser created successfully.
- 創(chuàng)建模型(model)
- 修改admin.py
- 告知Django模型有更改
- 創(chuàng)建表
之前在 TestModel 中已經(jīng)創(chuàng)建了模型 Test 。修改 TestModel/admin.py:
from django.contrib import admin
from TestModel.models import Test
# Register your models here.
admin.site.register(Test)
復(fù)雜模型
TestModel/models.py 中增加一個(gè)更復(fù)雜的數(shù)據(jù)模型
from django.db import models
# Create your models here.
class Test(models.Model):
name = models.CharField(max_length=20)
class Contact(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField(default=0)
email = models.EmailField()
def __unicode__(self):
return self.name
class Tag(models.Model):
concate = models.ForeignKey(Contact,on_delete=models.CASCADE)
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
TestModel/admin.py中修改
from django.contrib import admin
from TestModel.models import Test,Contact,Tag
# Register your models here.
admin.site.register([Test,Contact,Tag])
刷新 http://127.0.0.1:8000/admin/ 頁(yè)面

現(xiàn)在只是有了Concate和Tag模型,在數(shù)據(jù)庫(kù)中還沒有對(duì)應(yīng)的表
(Test是文章前面建的)

使用以下命令創(chuàng)建表結(jié)構(gòu)
python manage.py makemigrations TestModel # 讓 Django 知道我們?cè)谖覀兊哪P陀幸恍┳兏?python manage.py migrate TestModel # 創(chuàng)建表結(jié)構(gòu)
第一條命令執(zhí)行完,多了一個(gè)文件

第二條命令執(zhí)行完,創(chuàng)建了對(duì)應(yīng)的表
(有關(guān)數(shù)據(jù)庫(kù)連接請(qǐng)看“模型”)

自定義admin界面
自定義表單
1.把Age隱藏起來(lái)

修改 TestModel/admin.py:
from django.contrib import admin
from TestModel.models import Test,Contact,Tag
# Register your models here.
class ContactAdmin(admin.ModelAdmin): #新增代碼
fields = ('name','email') #新增代碼
admin.site.register(Contact,ContactAdmin) #新增代碼
admin.site.register([Test,Tag]) #刪除",Contact"
代碼說明
定義了一個(gè) ContactAdmin 類,用以說明管理頁(yè)面的顯示格式。
- fields 屬性定義了要顯示的字段
- 該類對(duì)應(yīng)的是 Contact 數(shù)據(jù)模型,我們?cè)谧?cè)的時(shí)候,需要將它們一起注冊(cè)
刷新后顯示效果如下

2.將輸入欄分塊,每個(gè)欄也可以定義自己的格式。
注意字母拼寫不要錯(cuò)誤!??!
from django.contrib import admin
from TestModel.models import Test,Contact,Tag
# Register your models here.
class ContactAdmin(admin.ModelAdmin):
fieldsets = (
['Main',{
'fields':('name','email'),
}],
['Advance',{
'classes': ('collapse',), # CSS
'fields': ('age',),
}]
)
admin.site.register(Contact, ContactAdmin)
admin.site.register([Test, Tag])
刷新頁(yè)面

點(diǎn)擊“Show”

說明
上面的欄目分為了 Main 和 Advance 兩部分。
classes 說明它所在的部分的 CSS 格式。這里讓 Advance 部分隱藏
內(nèi)聯(lián)(Inline)顯示
上面的 Contact 是 Tag 的外部鍵,所以有外部參考的關(guān)系。
問題:在默認(rèn)的頁(yè)面顯示中,將兩者分離開來(lái),無(wú)法體現(xiàn)出兩者的從屬關(guān)系。
解決:可以使用內(nèi)聯(lián)顯示,讓 Tag 附加在 Contact 的編輯頁(yè)面上顯示。
修改TestModel/admin.py
from django.contrib import admin
from TestModel.models import Test,Contact,Tag
# Register your models here.
class TagInline(admin.TabularInline): #新增代碼
model = Tag #新增代碼
class ContactAdmin(admin.ModelAdmin):
inlines = [TagInline] #Inline #修改代碼
fieldsets = (
['Main',{
'fields':('name','email'),
}],
['Advance',{
'classes':('cpllapse',), #CSS
'fields':('age',),
}]
)
admin.site.register(Contact,ContactAdmin)
admin.site.register([Test]) #修改代碼
刷新顯示

列表頁(yè)的顯示
在 Contact 輸入數(shù)條記錄后,Contact 的列表頁(yè)看起來(lái)如下

目的:在列表中顯示更多的欄目
- 在 ContactAdmin 中增加 list_display 屬性
from django.contrib import admin
from TestModel.models import Test,Contact,Tag
# Register your models here.
class TagInline(admin.TabularInline):
model = Tag
class ContactAdmin(admin.ModelAdmin):
list_display = ('name','age','email') #新增list_display屬性
inlines = [TagInline] #Inline
fieldsets = (
['Main',{
'fields':('name','email'),
}],
['Advance',{
'classes':('cpllapse',), #CSS
'fields':('age',),
}]
)
admin.site.register(Contact,ContactAdmin)
admin.site.register([Test])
刷新顯示

app
一個(gè)項(xiàng)目中可以創(chuàng)建很多個(gè)app
app可以用路由分發(fā)解決url沖突
使用命名空間也可以減少模板沖突等等
應(yīng)用1

qyvxtest:項(xiàng)目名
charlist:新建的app
app可以成為絕對(duì)路徑的引入,解決的導(dǎo)入模塊時(shí)的問題
例如:在一個(gè)項(xiàng)目中,新建了一個(gè)app,在該app的views中
from . import models
#異常
#RuntimeError: Model class chatlist.models.User doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS
在setting中
INSTALLED_APPS = [
...,
'chatlist',
]
則在該app的view中可以
from . import models
#或者
from chatlist import models