前提
已安裝python3.X
安裝完django
創(chuàng)建項目
#在命令行執(zhí)行
#HelloWorld 項目名稱
django-admin startproject HelloWorld
#進入項目
cd HelloWorld
目錄說明
|-- HelloWorld
| |-- init.py #空文件蛮浑,告訴Python這是一個Python的包
| |-- asgi.py #一個 ASGI 兼容的 Web 服務器的入口,以便運行你的項目。
| |-- settings.py #該 Django 項目的設置/配置盛杰。
| |-- urls.py #該 Django 項目的 URL 聲明; 一份由 Django 驅動的網(wǎng)站"目錄"。
|-- wsgi.py
-- manage.py #一個 WSGI 兼容的 Web 服務器的入口逗嫡,以便運行你的項目。
運行項目
#確保已進入HelloWorld目錄下
#多種運行項目的方式
python manage.py runserver
# 指定端口
python manage.py runserver 8080
# 任意ip接入
python manage.py runserver 0.0.0.0:8080
# 這里和settings.py的配置ALLOWED_HOSTS = []
# 不一樣的地方在于吗坚,這個是服務器監(jiān)聽的IP牡彻,IP不對無法連接到服務严就;
# ALLOWED_HOSTS是已經(jīng)連接到服務渐行,但連接的IP不在ALLOWED_HOSTS范圍內(nèi)就無法正常提供服務
運行完項目訪問 127.0.0.1:8000肴沫,就能看到一個綠色的小火箭孽文!
視圖和URL配置
注意import
HelloWorld 目錄新建一個 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 會執(zhí)行對應的第二個參數(shù) view矾屯。(可用正則表達式)
- view: 用于執(zhí)行與正則表達式匹配的 URL 請求。
- kwargs: 視圖使用的字典類型的參數(shù)。
- name: 用來反向獲取 URL僧著。
route:
- 對應端口號后的路徑
- 例如:http://127.0.0.1:8000/hello/,則route = “hello/”
views:
- from . import views導入的
- views.hello 對應的是views中的一個函數(shù)
kwargs:
- 少用到,暫不學
模板
為什么需要模板?
在上文views的hello中使用 django.http.HttpResponse() 來輸出 "Hello World吮成!"危纫,該方式將數(shù)據(jù)與視圖混合在一起,不符合 Django 的 MVC 思想
模板:模板是一個文本,用于分離文檔的表現(xiàn)形式和內(nèi)容。
建立模板
在 HelloWorld 目錄底下創(chuàng)建 templates 目錄并建立 runoob.html
項目結構
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')]
- 注意導入: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),
]
模板語法
views中的變量與html中變量“綁定”
view:{"HTML變量名" : "views變量名"}
HTML:{{變量名}}
#html頁面中
<h1>{{HTML變量名}}</h1>
#在views中
return render(request, 'runoob.html', {"HTML變量名" : "views變量名"})
網(wǎng)頁導航和頁腳
使用子模版繼承父模版退渗,減少代碼冗余
父模板
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>base</title>
</head>
<body>
<h1>Hello World!</h1>
<p>父模板測試</p>
{% block mainbody %}
<p>base template</p>
{% endblock %}
</body>
</html>
子模板
{%extends "base.html" %}
- 繼承了一個父模板(網(wǎng)頁)
父模板的{% block 名稱%}{% 名稱%}
- 相當于留空位給子模版新增內(nèi)容
- 標簽是可以被繼承者們替換掉的部分
{%extends "base.html" %}
{% block mainbody %}
<p>繼承了 base.html 文件</p>
{% endblock %}
模型
Django 模型使用自帶的 ORM稻薇。
- 對象關系映射(Object Relational Mapping忱屑,簡稱 ORM )用于實現(xiàn)面向對象編程語言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉換从铲。
# 安裝 mysql 驅動
pip install pymysql
在數(shù)據(jù)庫軟件中新建數(shù)據(jù)庫
-- runoob 數(shù)據(jù)庫名
create database runoob default charset=utf8;
修改 HelloWorld/HelloWorld/settings.py 中的DATABASES
DATABASES = {
'default':
{
'ENGINE': 'django.db.backends.mysql', # 數(shù)據(jù)庫引擎
'NAME': 'runoob', # 數(shù)據(jù)庫名稱
'HOST': '127.0.0.1', # 數(shù)據(jù)庫地址,本機 ip 地址 127.0.0.1
'PORT': 3306, # 端口
'USER': 'root', # 數(shù)據(jù)庫用戶名
'PASSWORD': '123456', # 數(shù)據(jù)庫密碼
}
}
告訴 Django 使用 pymysql 模塊連接 mysql 數(shù)據(jù)庫
# 在與 settings.py 同級目錄下的 __init__.py 中引入模塊和進行配置
import pymysql
pymysql.install_as_MySQLdb()
定義模型
Django 規(guī)定警没,如果要使用模型浅碾,必須要創(chuàng)建一個 app绵载。
#命令行中輸入
# TestModel與manage.py在同級目錄下
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ù)庫表名(Test)
類里面的字段代表數(shù)據(jù)表中的字段(name)
數(shù)據(jù)類型則由CharField(相當于varchar)懂版、DateField(相當于datetime)
max_length 參數(shù)限定長度。
告訴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', # 添加此項
)
命令行中運行
python manage.py migrate # 創(chuàng)建表結構
python manage.py makemigrations TestModel # 讓 Django 知道我們在我們的模型有一些變更
python manage.py migrate TestModel # 創(chuàng)建表結構
#如果代碼有報異常,繼續(xù)往下翻付翁。
第二行代碼執(zhí)行后
第三行代碼執(zhí)行后
該表結構
Django 會自動添加一個 id 作為主鍵赫粥。
異常
django.db.utils.OperationalError:(1045,"Access denied for user 'root'@'localhost'
- 確保用戶名和密碼正確后再試一次
- 可以用命令行測試數(shù)據(jù)庫連接
- 開啟服務:net start 服務名(例如:mysql5.7)
- mysql -h 主機名(ip) -u 用戶名 -P 端口 -p
數(shù)據(jù)庫操作
在 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ù)庫操作
def testdb(request):
test1 = Test(name='runoob')
test1.save()
return HttpResponse("<p>數(shù)據(jù)添加成功修噪!</p>")
啟動服務器并訪問
python manage.py runserver #啟動服務器
#訪問 http://127.0.0.1:8000/testdb/
#看到頁面輸出:數(shù)據(jù)添加成功
查看數(shù)據(jù)庫
獲取數(shù)據(jù)、刪除、修改
#獲取
# 通過objects這個模型管理器的all()獲得所有數(shù)據(jù)行强法,相當于SQL中的SELECT * FROM
list = Test.objects.all()
# filter相當于SQL中的WHERE蓖墅,可設置條件過濾結果
response2 = Test.objects.filter(id=1)
# 獲取單個對象
response3 = Test.objects.get(id=1)
# 限制返回的數(shù)據(jù) 相當于 SQL 中的 OFFSET 0 LIMIT 2;(分頁)
Test.objects.order_by('name')[0:2]
#數(shù)據(jù)排序
Test.objects.order_by("id")
# 上面的方法可以連鎖使用
Test.objects.filter(name="runoob").order_by("id")
#修改
#save() 或 update():
# 修改其中一個id=1的name字段贪壳,再save,相當于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()
異常
問題:修改模型后無法更新數(shù)據(jù)庫表結構捆交,刪除后再執(zhí)行命令也不行系忙。參考
解決:
刪除app/migrations/目錄下 “_pycache_” 文件
刪除app下面目錄migrations下面除了init.py其他的所有文件
刪除對應數(shù)據(jù)庫中django_migrations表中app名稱所在的列
(或者delete from django_migrations where app=‘yourappname’;)戒财,解決無法生成表
表單
HTML表單是網(wǎng)站交互性的經(jīng)典方式幽崩。
HTTP協(xié)議以"請求-回復"的方式工作蹄溉。
- 客戶發(fā)送請求時宴霸,可以在請求中附加數(shù)據(jù)。
- 服務器通過解析請求,就可以獲得客戶傳來的數(shù)據(jù)淫痰,并根據(jù)URL來提供特定的服務。
GET
創(chuàng)建一個 search.py 文件瓜客,用于接收用戶的請求
#/HelloWorld/HelloWorld/search.py 文件
from django.http import HttpResponse
from django.shortcuts import render
#表單
def search_form(request):
return render(request,'search_form.html')
#接收請求數(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能匹配正則表達式(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請求 視圖顯示和請求處理分成兩個函數(shù)處理姑原。
POST
提交數(shù)據(jù)時更常用POST方法。
- 一個URL和處理函數(shù),同時顯示視圖和處理請求。
Request對象
表單form通過HTTP POST方法提交請求芋膘,但是表單中可以沒有數(shù)據(jù)。
因此童番,不能使用語句if request.POST來判斷是否使用HTTP POST方法;
應該使用if request.method == "POST"
路由
Django不會匹配域名和協(xié)議
舉例:
請求:訪問http://127.0.0.1:8000/polls/34/
Django項目到urls中順序進行正則匹配/polls/34/,匹配到polls/尿赚,就切掉文本"polls/"躲舌,剩余文本"34/"繼續(xù)進行匹配
- path('polls/',include('polls.urls'))
- path('<int:question_id>/', views.detail, name='detail')
匹配到了views.detail
得到參數(shù)
question_id=34
由<int:question_id>
匹配生成约计。
- 使用尖括號“捕獲”這部分 URL尉桩,且以關鍵字參數(shù)的形式發(fā)送給視圖函數(shù)。
- 上述字符串的
:question_id>
部分定義了將被用于區(qū)分匹配模式的變量名int:
則是一個轉換器決定了應該以什么變量類型匹配這部分的 URL 路徑。
路由簡單的來說就是根據(jù)用戶請求的 URL 鏈接來判斷對應的處理程序止毕,并返回處理結果丸边,
- URL 與 Django 的視圖建立映射關系收叶。
Django 路由在 urls.py 配置嫉沽,urls.py 中的每一條配置對應相應的處理方法。
Django 不同版本 urls.py 配置有點不一樣
Django1.1.x 版本
url() 方法:普通路徑和正則路徑均可使用,需要自己手動添加正則首位限制符號闻镶。
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:用于普通路徑,不需要自己手動添加正則首位限制符號猴凹,底層已經(jīng)添加郊霎。
- re_path:用于正則路徑书劝,需要自己手動添加正則首位限制符號猾昆。
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), # 正則路徑
]
總結:Django1.1.x 版本中的 url 和 Django 2.2.x 版本中的 re_path 用法相同垂蜗。
分組
正則還有分組的概念,但是在Django中把分組分為兩種:
- 無名分組
- 有名分組
無名分組
無名分組:普通的正則匹配中加上()
作用:在后端的views上捆探,會得到一個分組的參數(shù)
- 訪問views.login函數(shù)(下方)的參數(shù)除了request搔弄,還需要添加一個參數(shù)(名字隨意)
- 要設置幾個參數(shù)就要多幾個分組
以下代碼訪問: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 = [
...,
# 記得添加結束標簽 $
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)
]
有名分組
有名分組: 有名分組其實就是在無名的分組的基礎上加上了名字
語法為:(?P<名字> 正則表達式)
#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一致,否則會報錯兑障!
注意:官方規(guī)定,有名分組和無名分組不能一起使用!
路由分發(fā)(include)
問題:
- 項目里多個app目錄共用一個 urls 容易造成混淆
- 后期維護不方便
解決:
- 使用路由分發(fā)(include)业稼,讓每個app目錄都單獨擁有自己的 urls。
步驟:
- 1、在每個 app 目錄里都創(chuàng)建一個 urls.py 文件沛膳。
- 2、在項目名稱目錄下的 urls 文件里落追,統(tǒng)一將路徑分發(fā)給各個 app 目錄妹卿。
舉例:
有兩個app尝偎,都有index.html頁面
- 如果在項目的urls中配置慷吊,則會造成混淆
- 且如果有太多的url,則維護十分難
所以應該把各種的url分給各自去管理
#路由 未分發(fā)
#項目主目錄下的urls.py
urlpatterns = [
url(r'^app-one/index/$',views.index),
url(r'^app-two/index/$',views.index)
]
新建兩個app
# 語法:python manage.py startapp <app名稱>
# 命令行中運行
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頁面庞呕!')
2.新建urls.py文件
from . import views
from django.conf.urls import url #沒有引入會報錯: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)
]
項目主目錄下的urls.py
urlpatterns = [
url(r'^app-one/',include('app01.urls')),
url(r'^app-two/',include('app02.urls'))
]
訪問
注意訪問路徑:
- app-one/index/
- 對照上面的urls.py文件榄攀,就能理解路由轉發(fā)了愧捕!
app01
運行項目:python manage.py runserver
app02
反向解析
目的:解耦
- 路由層的 url 發(fā)生變化治力,就需要去更改對應的視圖層和模板層的 url国章,不便維護
反向解析
- 當路由層 url 發(fā)生改變,在視圖層和模板層動態(tài)反向解析出更改后的 url跛溉,免去修改的操作。
- 一般用在模板中的超鏈接及視圖中的重定向
問題舉例
#urls.py 中的一條url
...
url(r'^login/$',views.login)
...
#html頁面中的提交表單
<form action="/login/" method="P=post">
...
</form>
當更改路由中的url時瓷产,需要在html頁面也做相應的更改循头!
解耦目的:只更改路由中的url,html中會自動做出更改,我們無需去改變!
反向解析
方法:給路由器起別名
應用:
1.普通路徑:name="路由別名
重定向:
- redirect(reverse("login"))
超鏈接:
- <form action="{% url 'login' %}" method="post">
2.正則路徑:無名分組
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 %}
命名空間
命名空間(英語:Namespace)是表示標識符的可見范圍渡八。
一個標識符可在多個命名空間中定義,它在不同命名空間中的含義是互不相干的逮壁。
一個新的命名空間中可定義任何標識符窥淆,它們不會與任何重復的標識符發(fā)生沖突,因為重復的定義都處于其它命名空間中眷昆。
存在問題:路由別名 name 沒有作用域,Django 在反向解析 URL 時帅刊,會在項目全局順序搜索,當查找到第一個路由別名 name 指定 URL 時栏饮,立即返回。當在不同的 app 目錄下的urls 中定義相同的路由別名 name 時伺通,可能會導致 URL 反向解析錯誤箍土。
解決:使用命名空間。
普通路徑
方式一:
#主目錄下的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 里面是一個元組)
include(("app名稱:urls"罐监,"app名稱"))
實例
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名稱:路由別名" %}
視圖
每個視圖必須要做的只有兩件事:
- 返回一個包含被請求頁面內(nèi)容的
HttpResponse
對象- 或者拋出一個異常吴藻,比如
Http404
。
Admin 管理工具
介紹
Django 提供了基于 web 的管理工具弓柱。
Django 自動管理工具是 django.contrib 的一部分。
在項目的 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基本代碼的組成部分。
激活管理工具
在生成項目時會在 urls.py 中自動設置好俊犯,我們只需去掉注釋即可妇多。
配置如下
# urls.py
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
使用管理工具
創(chuàng)建超級用戶
# 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)
復雜模型
TestModel/models.py 中增加一個更復雜的數(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])
現(xiàn)在只是有了Concate和Tag模型燕侠,在數(shù)據(jù)庫中還沒有對應的表
(Test是文章前面建的)
使用以下命令創(chuàng)建表結構
python manage.py makemigrations TestModel # 讓 Django 知道我們在我們的模型有一些變更
python manage.py migrate TestModel # 創(chuàng)建表結構
第一條命令執(zhí)行完者祖,多了一個文件
第二條命令執(zhí)行完,創(chuàng)建了對應的表
(有關數(shù)據(jù)庫連接請看“模型”)
自定義admin界面
自定義表單
1.把Age隱藏起來
修改 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"
代碼說明
定義了一個 ContactAdmin 類绢彤,用以說明管理頁面的顯示格式七问。
- fields 屬性定義了要顯示的字段
- 該類對應的是 Contact 數(shù)據(jù)模型,我們在注冊的時候茫舶,需要將它們一起注冊
刷新后顯示效果如下
2.將輸入欄分塊械巡,每個欄也可以定義自己的格式。
注意字母拼寫不要錯誤H氖稀<ズ摹!
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])
刷新頁面
點擊“Show”
說明
上面的欄目分為了 Main 和 Advance 兩部分疹启。
classes 說明它所在的部分的 CSS 格式古程。這里讓 Advance 部分隱藏
內(nèi)聯(lián)(Inline)顯示
上面的 Contact 是 Tag 的外部鍵,所以有外部參考的關系喊崖。
問題:在默認的頁面顯示中挣磨,將兩者分離開來,無法體現(xiàn)出兩者的從屬關系荤懂。
解決:可以使用內(nèi)聯(lián)顯示茁裙,讓 Tag 附加在 Contact 的編輯頁面上顯示。
修改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]) #修改代碼
刷新顯示
列表頁的顯示
在 Contact 輸入數(shù)條記錄后节仿,Contact 的列表頁看起來如下
目的:在列表中顯示更多的欄目
- 在 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
一個項目中可以創(chuàng)建很多個app
app可以用路由分發(fā)解決url沖突
使用命名空間也可以減少模板沖突等等
應用1
qyvxtest:項目名
charlist:新建的app
app可以成為絕對路徑的引入呜达,解決的導入模塊時的問題
例如:在一個項目中,新建了一個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