第十八章 Django入門
一最筒、建立項目
項目規(guī)范:項目規(guī)范詳細(xì)說明了項目的目標(biāo)晦鞋,闡述了項目的功能谋币,并討論了項目的外觀和用戶界面
要使用Django暑竟,首先要建立一個虛擬工作環(huán)境斋射。虛擬環(huán)境是系統(tǒng)的一個位置,你可以 其中安裝包但荤,并將其與其他Python包隔離罗岖,將項目的庫與其他項目分離是有益的,且為了部署到服務(wù)器腹躁,這也是必須的桑包。
先為項目建立一個目錄,并在這個目錄下創(chuàng)建一個虛擬環(huán)境
d:\python\Django>python-m venv ll_env
激活虛擬環(huán)境
ll_env\scripts\activate.bat
停止使用虛擬環(huán)境
ll_env\scripts\deactivate.bat
安裝Django
pip install Django
在Django中創(chuàng)建目錄
django-admin.py startproject learning_log .
末尾的句點讓新項目使用合適的目錄結(jié)構(gòu)纺非,千萬別忘記這個句點哑了,否則部署應(yīng)用程序時將遇一些配置問題。
創(chuàng)建數(shù)據(jù)庫
python manage.py migrate
首次執(zhí)行命令migrate時烧颖,將讓Django確保數(shù)據(jù)庫與項目的當(dāng)前狀態(tài)匹配弱左,創(chuàng)建必要的數(shù)據(jù)庫表,用于存儲我們將在這個項目中的信息炕淮,再確保數(shù)據(jù)庫結(jié)構(gòu)與當(dāng)前代碼匹配拆火,此時生成
db.sqlite3
數(shù)據(jù)庫文件,SQLite是一種使用單個文件的數(shù)據(jù)庫涂圆,是編寫簡單應(yīng)用程序的理想選擇们镜。
查看項目
python manage.py runserver
Django啟動一個服務(wù)器,能查看系統(tǒng)中的項目润歉,了解它們的工作情況模狭。當(dāng)在瀏覽器輸入URL:http://127.0.0.1:8000/請求網(wǎng)頁時,Django服務(wù)器將進(jìn)行響應(yīng)卡辰,生成網(wǎng)頁胞皱,并發(fā)送給瀏覽器邪意。
ctrl + c
關(guān)閉服務(wù)器
二九妈、創(chuàng)建應(yīng)用程序
Django項目由一系列應(yīng)用程序組成,它們協(xié)同工作雾鬼,讓項目成為一個整體萌朱。
創(chuàng)建應(yīng)用
python manage.py startapp learning_logs
startapp <appname>
命令讓Django建立創(chuàng)建應(yīng)用程序的基礎(chǔ)設(shè)施(models.py,admin.py和views.py)
定義模型
打開models.py,新增Topic
類
from django.db import models
class Topic(models.Model):
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.text
CharField
是由字符或文本組成的數(shù)據(jù)策菜,max_lenght=200
最多存儲200個字符晶疼;
DateTimeField
是記錄日期和時間的數(shù)據(jù)酒贬,auot_now_add=True
,當(dāng)新增時翠霍,Django將這個字段設(shè)置成當(dāng)前日期和時間锭吨;
__str__()
返回存儲在屬性text中的字符串
激活模型
要使用模型,必須讓Django將應(yīng)用程序包含到項目中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'learning_logs',
]
在
settings.py
文件中寒匙,將應(yīng)用程序learing_logs
添加到INSTALLED_APPS
元組零如,接下來,讓Django修改數(shù)據(jù)庫python manage.py makemigrations learning_logs
锄弱,命令makemigrations
讓Django該如何修改數(shù)據(jù)庫
python manage.py makemigrations learning_logs
輸出:Migrations for 'learning_logs':
0001_initial.py: - Create model Topi考蕾,并創(chuàng)建一個名為0001_initial.py的遷移文件,這個文件將在數(shù)據(jù)庫中為模型Topic創(chuàng)建一個表会宪。
應(yīng)用遷移肖卧,Django修改數(shù)據(jù)庫:
python manage.py migrate
輸出:
Running migrations:
Rendering model states... DONE
Applying learning_logs.0001_initial... OK
每當(dāng)需要修改管理的數(shù)據(jù)時,都采取如下三個步驟:1掸鹅、修改models.py
塞帐;
2、對learning_logs調(diào)用makemigrations
(python manage.py makemigrations learning_logs)巍沙;
3壁榕、讓Django遷移項目python manage.py migrate
管理網(wǎng)站
1、創(chuàng)建超級用戶
python manage.py createsuperuser
#提示輸入超級用戶名赎瞎,eMail牌里,兩次密碼
2、向管理網(wǎng)站注冊模型
打開admin.py
务甥,向管理網(wǎng)站注冊Topic
from learning_logs.models import Topic
admin.site.register(Topic)
admin.site.register()讓Django通過管理網(wǎng)站管理模型
3牡辽、定義模型Entry
class Topic(models.Model):
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.text
class Entry(models.Model):
topic = models.ForeignKey(Topic,on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
return self.text[:20]+ "..."
models.ForeignKey(Topic):關(guān)聯(lián)Topic外鍵
on_delete=models.CASCADE:當(dāng)主表刪除時從表中的數(shù)據(jù)也一起刪除
4、Django shell
python manage.py shell
>>>from learning_logs import Topic
>>>Topic.objects.all()
#輸出:
<QuerySet [<Topic: Study Django>, <Topic: Study python>]>
>>>topics = Topic.objects.all()
>>>for topic in topics:
print(ttopic.id,topic)
>>>t = Topic.objects.get(id=1)
>>>t.text
#通過外鍵獲取Entry數(shù)據(jù)
>>>t.entry_set.all()
每次修改模型后敞临,都需要重啟shell态辛,這樣才能看到修改后的效果,退出shell挺尿,Linux:Ctrl + D奏黑,Windows:Ctrl + Z,再按回車编矾。
三熟史、創(chuàng)建網(wǎng)頁
使用Django創(chuàng)建網(wǎng)頁分三個階段:定義URL;編寫視圖和編寫模板窄俏。URL定義讓Django知道如何將瀏覽器請求與網(wǎng)站URL匹配蹂匹,以確定返回哪個網(wǎng)頁。
1凹蜈、映射URL
打開項目文件夾learning_log中的文件urls.py.
"""learning_log URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
#添加learning_logs的URL和APP_NAME限寞,實參namespace將同項目中的其它URL區(qū)分開來 path(r'',include(('learning_logs.urls','learning_logs'),namespace='learning_logs')),#
]
在learing_logs目錄下創(chuàng)建urls.py
#導(dǎo)入url
from django.conf.urls import url
#導(dǎo)入views
from . import views
urlpatterns = [
#主頁
url(r'^$',views.index,name='index')
#顯示所有主題
url(r'^topics/$',views.topics,name='topics')
#顯示特定主題的詳細(xì)頁面
url(r'^topics/(?P<topic_id>\d+)/$',views.topic,name='topic')
]
url()參數(shù):第一參數(shù)正則表達(dá)式匹配請求URL,正則表達(dá)式通常被為regex忍啸,幾乎每種語言都使用它
第二參數(shù)指定要調(diào)用的視圖函數(shù)
第三個參數(shù)將這個URL模式的名稱指定為index,可以其它地方引用它履植,當(dāng)需要提供這個鏈接時计雌,直接使用這個名稱,而不用編寫URL
2玫霎、編寫視圖
視圖函數(shù)接受請求中的信息白粉,準(zhǔn)備好生成網(wǎng)頁所需的數(shù)據(jù),再將這些數(shù)據(jù)發(fā)送給瀏覽器
learning_logs中的文件views.py在執(zhí)行
python manage.py startapp
時自動生成的鼠渺。
#導(dǎo)入render()函數(shù)鸭巴,根據(jù)視圖提供的數(shù)據(jù)渲染響應(yīng)
from django.shortcuts import render
def index(request):
return render(request,'learning_logs/index.html')
def topics(request):
topics = Topic.objects.order_by('date_added')
context = {'topics':topics}
return render(request,'learning_logs/topics.html',context)
def topic(request,topic_id):
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('date_added')
context = {'topic':topic,'entries':entries}
return render(request,'learning_logs/topic.html',context)
URL請求與定義的模式匹配時,Django將在文件views.py中查找函數(shù)index()拦盹,再將請求對象傳遞給視圖函數(shù)
3鹃祖、編寫模板
模板定義網(wǎng)頁的結(jié)構(gòu),指定網(wǎng)頁是什么樣的普舆,每當(dāng)網(wǎng)頁請求時恬口,Django填入相關(guān)數(shù)據(jù),模板能訪問視圖提供的任何數(shù)據(jù)沼侣。
在文件夾learning_logs下建立templates目錄祖能,在再templates目錄下建立learning_logs目錄,然后在learning_logs下建立index.html
<p>Learing_Log</p>
<p>Learning Log helps you keep track of your learning,for any topic you're learning about.</p>
4蛾洛、模板繼承
創(chuàng)建網(wǎng)站時养铸,很多頁面都有可能包含相同的元素,所以轧膘,編寫一個包含通用元素的父模板钞螟,并讓每個網(wǎng)頁都繼承這個模板,不必在每個頁面中重復(fù)定義這些通用元素谎碍。
#父模板base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a>
-
<a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>
{% block content %}{% endblock content %}
#子模板index.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Learning Log helps you keep track of your learning,for any topic you're learning about.</p>
{% endblock content%}
#子模板topics.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</li>
{% empty %}
<li>No topics have been added yet </li>
{% endfor %}
</ul>
{% endblock content%}
#子模板topic.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic:{{ topic }}</p>
<p>Entries:</p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d,Y H:i'}}</p>
<p>{{ entry.text|linebreaks }}</p>
</li>
{% empty %}
<li>No entry for this topic yet </li>
{% endfor %}
</ul>
{% endblock content%}
在Django模板中鳞滨,豎線(|)表示模板過濾器--對模板變量的值進(jìn)行修改的函數(shù),過濾器
M d,Y H:i
以這樣的格式顯示時間戳蟆淀;過濾器linebreaks
將包含換行符的長條目轉(zhuǎn)換為瀏覽器能夠理解的格式拯啦。