溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python全棧開發(fā)之Django基礎(chǔ)

發(fā)布時(shí)間:2020-06-09 19:47:13 來源:網(wǎng)絡(luò) 閱讀:5750 作者:灰白世界 欄目:編程語言

No.1 MVC&MTV

MVC

M全拼為Model,主要封裝對(duì)數(shù)據(jù)庫層的訪問,對(duì)數(shù)據(jù)庫中的數(shù)據(jù)進(jìn)行增、刪、改、查操作

V全拼為View,用于封裝結(jié)果,生成頁面展示的html內(nèi)容

C全拼為Controller,用于接收請(qǐng)求,處理業(yè)務(wù)邏輯,與Model和View交互,返回結(jié)果

MTV

M全拼為Model,與MVC中的M功能相同,負(fù)責(zé)和數(shù)據(jù)庫交互,進(jìn)行數(shù)據(jù)處理

V全拼為View,與MVC中的C功能相同,接收請(qǐng)求,進(jìn)行業(yè)務(wù)處理,返回應(yīng)答

T全拼為Template,與MVC中的V功能相同,負(fù)責(zé)封裝構(gòu)造要返回的html

No.2 安裝與配置

虛擬環(huán)境

為什么要使用虛擬環(huán)境?

如果在一臺(tái)機(jī)器上,想開發(fā)不同的項(xiàng)目,這些項(xiàng)目依賴的同一個(gè)包的版本不同,其他項(xiàng)目就無法正常運(yùn)行了,所有我們要用到虛擬環(huán)境,虛擬環(huán)境就是對(duì)真實(shí)Python環(huán)境的復(fù)制,通過建立多個(gè)虛擬環(huán)境,在不同的虛擬環(huán)境中開發(fā)項(xiàng)目就實(shí)現(xiàn)了項(xiàng)目之間的間隔

創(chuàng)建虛擬環(huán)境

pip3 install virtualenv # 安裝虛擬環(huán)境
pip3 install virtualenvwrapper-win # 安裝虛擬環(huán)境擴(kuò)展包
mkvirtualenv 虛擬環(huán)境名稱 # 創(chuàng)建虛擬環(huán)境
deactivate # 退出虛擬環(huán)境
workon # 直接輸入workon查看已創(chuàng)建的虛擬環(huán)境,后面接虛擬環(huán)境名稱進(jìn)入該虛擬環(huán)境
rmvirtualenv 虛擬環(huán)境名稱 # 刪除虛擬環(huán)境
pip list # 查看該虛擬環(huán)境中安裝的包
pip install # 虛擬環(huán)境包管理
pip install django==1.11.11 # 安裝django1.11.11

Django基本使用

創(chuàng)建項(xiàng)目

創(chuàng)建第一個(gè)項(xiàng)目

django-admin startproject mysite;

項(xiàng)目默認(rèn)目錄

manage.py # 項(xiàng)目管理文件,通過它管理項(xiàng)目
與項(xiàng)目同名的目錄,此處為mysite
_init_.py # 一個(gè)空文件,作用是這個(gè)目錄test可以被當(dāng)作包使用
settings.py # 項(xiàng)目的整體配置文件
urls.py # 項(xiàng)目的URL配置文件
wsgi.py # 項(xiàng)目與WSGI兼容的Web服務(wù)器入口

創(chuàng)建應(yīng)用

python manage.py startapp app01;

應(yīng)用目錄結(jié)構(gòu)

__init__.py # 一個(gè)空文件,表示當(dāng)前目錄可以當(dāng)作一個(gè)python包使用
tests.py # 開發(fā)測(cè)試用例,在實(shí)際開發(fā)中會(huì)有專門的測(cè)試人員
models.py # 數(shù)據(jù)庫操作相關(guān)
views.py # 接收瀏覽器請(qǐng)求,進(jìn)行處理,返回頁面相關(guān)
admin.py # 站點(diǎn)管理
migrations: 

安裝應(yīng)用

# mysite/setting.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
]

開發(fā)服務(wù)器

python manage.py runserver ip:端口
設(shè)計(jì)模型

定義模型類

# app01/models.py
from django.db import models

class BookInfo(models.Model):
    """圖書表"""
    btitle = models.CharField(max_length=20)
    bpub_date = models.DateField()

class HeroInfo(models.Model):
    """英雄表"""
    hname = models.CharField(max_length=20)
    hgender = models.BooleanField()
    hcomment = models.CharField(max_length=100)
    hbook = models.ForeignKey(BookInfo)

遷移

python manage makemigration # 生成遷移文件
python manage migrate # 執(zhí)行遷移

數(shù)據(jù)操作

# 進(jìn)入項(xiàng)目并引入模塊
python manage.py shell
from datetime import date
from booktest.models import BookInfo,HeroInfo

# 增刪改查
BookInfo.objects.create(title="射雕英雄傳",bpub_date=date(2018,10,4))
BookInfo.objects.filter(id=1).delete()
BookInfo.objects.filter(id=1).update(title='神雕俠侶')
BookInfo.objects.filter.all()

# 對(duì)象關(guān)聯(lián)操作
HeroInfo.objects.create(hname='a1',hgender=False,hcomment='he is a boy',hbook=BookInfo.objects.get(id=1))

# 獲得關(guān)聯(lián)集合
BookInfo.objects.get(id=1).heroinfo_set.all()
站點(diǎn)管理

管理頁面本地化

# mysite/setting.py
LANGUAGE_CODE = 'zh-hans' #使用中國語言
TIME_ZONE = 'Asia/Shanghai' #使用中國上海時(shí)間

創(chuàng)建管理員

python manage.py createsuperuser

注冊(cè)模型類

# app01/admin.py
from django.contrib import admin
from app01.models import BookInfo,HeroInfo

admin.site.register(BookInfo)
admin.site.register(HeroInfo)

自定義管理界面

# app01/admin.py,list_display表示要顯示的字段
from django.contrib import admin
from booktest.models import BookInfo,HeroInfo

class BookInfoAdmin(admin.ModelAdmin):
    list_display = ['id', 'btitle', 'bpub_date']
class HeroInfoAdmin(admin.ModelAdmin):
    list_display = ['id', 'hname','hgender','hcomment']

admin.site.register(BookInfo,BookInfoAdmin)
admin.site.register(HeroInfo,HeroInfoAdmin)
視圖

定義視圖

# app01/views.py
from django.http import HttpResponse

def index(request):
    return HttpResponse("index")

配置URLconf

請(qǐng)求者在瀏覽器中輸入url,請(qǐng)求到網(wǎng)站后,獲取url信息,然后在URL.conf逐條匹配,如果匹配成功返回相應(yīng)的視圖函數(shù),如果所有URLconf都沒有匹配成功,返回404錯(cuò)誤
# app01/views.py
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^', include('app01.urls')),
]
# mysite/urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^$', views.index),
]
模板

創(chuàng)建模板

# mysite/setting.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, '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',
            ],
        },
    },
]

定義模板

# templtes/app01/index.html
<html>
<head>
    <title>圖書列表</title>
</head>
<body>
    <h2>{{title}}</h2>
    {%for i in list%}
        {{i}}<br>
    {%endfor%}
</body>
</html>

視圖調(diào)用模板

# app01/views.py
from django.shortcuts import render

def index(request):
    context={'title':'圖書列表','list':range(10)}
    return render(request,'app01/index.html',context)

No.3 模型

負(fù)責(zé)和數(shù)據(jù)庫交互,進(jìn)行數(shù)據(jù)處理

ORM

什么是orm?

對(duì)象關(guān)系映射,是隨著面向?qū)ο笏枷氚l(fā)展而產(chǎn)生的,是一種程序技術(shù),用于實(shí)現(xiàn)面向?qū)ο缶幊陶Z言里不同類型系統(tǒng)的數(shù)據(jù)之間的轉(zhuǎn)換,面向?qū)ο笫菑能浖こ袒驹瓌t(如耦合、聚合、封裝)的基礎(chǔ)上發(fā)展起來的,而關(guān)系數(shù)據(jù)庫則是從數(shù)學(xué)理論發(fā)展而來的,兩套理論存在顯著的區(qū)別,為了解決這個(gè)不匹配的現(xiàn)象,對(duì)象關(guān)系映射技術(shù)應(yīng)運(yùn)而生

使用MySQL

# mysite/setting.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'python', #數(shù)據(jù)庫名字,
        'USER': 'root', #數(shù)據(jù)庫登錄用戶名
        'PASSWORD': '123456', #數(shù)據(jù)庫登錄密碼
        'HOST': 'localhost', #數(shù)據(jù)庫所在主機(jī)
        'PORT': '3306', #數(shù)據(jù)庫端口
    }
}
# mysite/__init__.py
import  pymysql
pymysql.install_as_MySQLdb()

定義模型類

字段類型

  • AutoField:自動(dòng)增長的IntegerField,通常不用指定,不指定時(shí)Django會(huì)自動(dòng)創(chuàng)建屬性名為id的自動(dòng)增長屬性
  • BooleanField: 布爾字段,值為True或False
  • NullBooleanField: 支持Null,True,F(xiàn)alse
  • CharField(max_length): 字符串,表示最大字符個(gè)數(shù)
  • TextField: 大文本字段,字符超過4000使用
  • IntgerField: 整數(shù)字段
  • DecimalField(max_digits,decimal_places): 十進(jìn)制浮點(diǎn)數(shù),max_digits表示總位數(shù),decimal_places表示小數(shù)位數(shù)
  • FloatField: 浮點(diǎn)數(shù)
  • DateField(auto_now,auto_now_add): auto_now表示每次保存對(duì)象時(shí),自動(dòng)設(shè)置該字段為當(dāng)前時(shí)間,用于最后一次修改的時(shí)間戳,默認(rèn)為False,auto_now_add表示當(dāng)對(duì)象第一次創(chuàng)建時(shí)自動(dòng)設(shè)置當(dāng)前時(shí)間,用于創(chuàng)建時(shí)的時(shí)間戳,默認(rèn)為False
  • TimeField: 時(shí)間字段,同上
  • DateTimeField: 日期時(shí)間字段,同DateField
  • FileField: 上傳文件字段
  • ImageField: 繼承自FileField,對(duì)上傳的內(nèi)容進(jìn)行校驗(yàn),確保是有效的圖片

字段約束

  • null:如果為True,表示允許為空,默認(rèn)值是False
  • blank:如果為True,則該字段允許為空白,默認(rèn)值是False,null是數(shù)據(jù)庫范疇的概念,blank是表單驗(yàn)證范疇的
  • db_column:字段的名稱,如果未指定,則使用屬性的名稱
  • db_index:若值為True, 則在表中會(huì)為此字段創(chuàng)建索引,默認(rèn)值是False
  • default:默認(rèn)值
  • primary_key:若為True,則該字段會(huì)成為模型的主鍵,默認(rèn)值是False,一般作為AutoField的選項(xiàng)使用
  • unique:如果為True, 這個(gè)字段在表中必須有唯一值,默認(rèn)值是False

條件查詢

查詢

exact 表示判等
list = BookInfo.objects.filter(id__exact=1)
list = BookInfo.objects.filter(id=1)

模糊查詢

contains 是否包含
list = BookInfo.objects.filter(btitle__contains='傳')
list = BookInfo.objects.filter(btitle__icontains='傳') # 不區(qū)分大小寫
startswith 以指定字符開頭
list = BookInfo.objects.filter(btitle__startswith='神')
list = BookInfo.objects.filter(btitle__istartswith='神') # 不區(qū)分大小寫
endswithch 以指定字符結(jié)尾
list = BookInfo.objects.filter(btitle__endswitch='侶')
list = BookInfo.objects.filter(btitle__iendswitch='侶') # 不區(qū)分大小寫

空查詢

isnull 是否為空
list = BookInfo.objects.filter(btitle__isnull=False)

范圍查詢

in 是否包含在范圍內(nèi)
list = BookInfo.objects.filter(id__in=[1, 3, 5])

比較查詢

gt: 大于
gte: 大于等于
lt: 小于
lte:小于等于
list = BookInfo.objects.filter(id__gt=3)

不等于查詢

exclude() 不等于運(yùn)算符
list = BookInfo.objects.exclude(id=3)

日期查詢

year、month、day、week_day、hour、minute、second
list = BookInfo.objects.filter(bpub_date__year=1980)

F對(duì)象

比較一個(gè)對(duì)象中的兩個(gè)屬性
list = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)

Q對(duì)象

多個(gè)過濾器逐個(gè)調(diào)用表示邏輯與關(guān)系,同sql語句中where部分的and關(guān)鍵字
list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)
如果想實(shí)現(xiàn)邏輯或的功能,就要使用到Q對(duì)象查詢,Q對(duì)象可以使用&、|連接,&表示邏輯與,|表示邏輯或,~表示not
list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))

聚合查詢

使用aggregate()過濾器調(diào)用聚合函數(shù),聚合函數(shù)包括:Avg,Count,Max,Min,Sum
list = BookInfo.objects.count()

查詢集

查詢集表示從數(shù)據(jù)庫中查詢到的對(duì)象集合

返回查詢集的過濾器

  • all():返回所有數(shù)據(jù)
  • filter(): 返回滿足條件的數(shù)據(jù)
  • exclude(): 返回不滿足條件的數(shù)據(jù)
  • order_by(): 對(duì)結(jié)果集排序

返回單個(gè)值的過濾器

  • get(): 返回單個(gè)滿足條件的對(duì)象,如果未找到會(huì)拋出DoesNotExist異常,如果返回多條拋出MultipleObjectReturnned異常
  • count(): 返回當(dāng)前查詢結(jié)果的總條數(shù)
  • aggregate(): 聚合,返回一個(gè)字典

判斷一個(gè)查詢集中是否有數(shù)據(jù)

兩個(gè)特性

  • 惰性 創(chuàng)建查詢集不會(huì)訪問數(shù)據(jù)庫,直到調(diào)用數(shù)據(jù)時(shí),才會(huì)訪問數(shù)據(jù)庫
  • 緩存 使用同一個(gè)結(jié)果集,第一次使用會(huì)觸發(fā)查詢數(shù)據(jù)庫,然后將結(jié)果緩存下載,再次使用直接調(diào)用緩存

限制結(jié)果集

可以對(duì)結(jié)果集進(jìn)行切片操作,等同于數(shù)據(jù)庫中的分頁操作,但是不支持負(fù)數(shù)
list = BookInfo.objects.all()[0:2]

關(guān)聯(lián)

關(guān)系字段類型
  • ForeignKey:一對(duì)多,將字段定義在多的一端中
  • ManyToManyField:多對(duì)多,將字段定義在任意一端中
  • OneToOneField:一對(duì)一,將字段定義在任意一端中
  • 可以維護(hù)遞歸的關(guān)聯(lián)關(guān)系,使用'self'指定,詳見"自關(guān)聯(lián)"

一對(duì)多

一本圖書中可以對(duì)應(yīng)多個(gè)英雄,所以圖書和英雄是一對(duì)多的關(guān)系
class BookInfo(models.Model):
    btitle = models.CharField(max_length=20)
    bpub_date = models.DateField()
    bread = models.IntegerField(default=0)
    bcomment = models.IntegerField(default=0)
    isDelete = models.BooleanField(default=False)

class HeroInfo(models.Model):
    hname = models.CharField(max_length=20)
    hgender = models.BooleanField(default=True)
    isDelete = models.BooleanField(default=False)
    hcomment = models.CharField(max_length=200)
    hbook = models.ForeignKey('BookInfo')

多對(duì)多

一個(gè)類別中多條新聞,一條新聞也可以分為不同的類別,所以新聞是多對(duì)多關(guān)系
class TypeInfo(models.Model):
  tname = models.CharField(max_length=20)

class NewsInfo(models.Model):
  ntitle = models.CharField(max_length=60)
  ncontent = models.TextField()
  npub_date = models.DateTimeField(auto_now_add=True)
  ntype = models.ManyToManyField('TypeInfo') 
通過對(duì)象執(zhí)行關(guān)聯(lián)查詢
  • 由一對(duì)多的訪問語法
一端的對(duì)象.多端的類名_set
b = BookInfo.objects.get(id=1)
b.HeroInfo_set.all()
  • 由多對(duì)一的訪問語法
多端的模型對(duì)象.多端模型類的類關(guān)系字段
h = HeroInfo.objects.get(id=1)
h.hbook
  • 訪問一對(duì)應(yīng)的模型類關(guān)聯(lián)對(duì)象的id語法:

多對(duì)應(yīng)的模型類對(duì)象.關(guān)聯(lián)類屬性_id
h = HeroInfo.objects.get(id=1)
h.book_id
通過模型類執(zhí)行關(guān)聯(lián)查詢
  • 由多模型類條件查詢一模型類數(shù)據(jù):
語法:
關(guān)聯(lián)模型類名小寫__屬性名__條件運(yùn)算符=值
list = BookInfo.objects.filter(heroinfo__hcontent__contains='八')
  • 由一模型類條件查詢多模型類數(shù)據(jù):
語法:
一模型類關(guān)聯(lián)屬性名__一模型類屬性名__條件運(yùn)算符=值
list = HeroInfo.objects.filter(hbook__btitle='天龍八部')

No.4視圖

視圖負(fù)責(zé)接受Web請(qǐng)求HttpRequest,進(jìn)行邏輯處理,返回Web響應(yīng)HttpResponse給請(qǐng)求者

URLconf

位置參數(shù)

url(r'^delete(\d+)/$',views.show_arg),

關(guān)鍵字參數(shù)

url(r'^delete(?P<id1>\d+)/$',views.show_arg),

內(nèi)置錯(cuò)誤視圖,如果想看到錯(cuò)誤視圖而不是調(diào)試信息的話,需要修改setting文件的DEBUG選項(xiàng)

# mysite/setting.py 
DEBUG = False
ALLOWED_HOSTS = ['*', ]

HttpReqeust對(duì)象

  • path: 一個(gè)字符串,表示請(qǐng)求的完整路徑,不包含域名和參數(shù)
  • method: 一個(gè)字符串,表示請(qǐng)求方法,常用的有GET、POST
  • encoding: 一個(gè)字符串,表示提交數(shù)據(jù)的編碼類型
  • GET: QueryDict類型對(duì)象,類似于字典,包含get請(qǐng)求方式的所有參數(shù)
  • POST:QueryDict類型對(duì)象,類似于字典,包含post請(qǐng)求方式的所有參數(shù)
  • FILES:一個(gè)類似于字典的對(duì)象,包含所有的上傳文件
  • COOKIES:一個(gè)標(biāo)準(zhǔn)的Python字典,包含所有的cookie,鍵和值都為字符串
  • session:一個(gè)可讀寫的類似于字典的對(duì)象,表示當(dāng)前的會(huì)話,只有當(dāng)Django 啟用會(huì)話的支持時(shí)才可用

HttpResponse對(duì)象

屬性

  • content:表示返回的內(nèi)容。
  • charset:表示response采用的編碼字符集,默認(rèn)為utf-8。
  • status_code:返回的HTTP響應(yīng)狀態(tài)碼。
  • content-type:指定返回?cái)?shù)據(jù)的的MIME類型,默認(rèn)為'text/html'。

方法

  • init:創(chuàng)建HttpResponse對(duì)象后完成返回內(nèi)容的初始化
  • set_cookie:設(shè)置Cookie信息

  • delete_cookie(key):刪除指定的key的Cookie,如果key不存在則什么也不發(fā)生
  • write:向響應(yīng)體中寫數(shù)據(jù)

Cookie

某些網(wǎng)站為了辨別用戶身份、進(jìn)行session跟蹤而儲(chǔ)存在用戶本地終端上的數(shù)據(jù),Cookie是由服務(wù)器端生成,發(fā)送給User-Agent(一般是瀏覽器),瀏覽器會(huì)將Cookie的key/value保存到某個(gè)目錄下的文本文件內(nèi),下次請(qǐng)求同一網(wǎng)站時(shí)就發(fā)送該Cookie給服務(wù)器,Cookie名稱和值可以由服務(wù)器端開發(fā)自己定義,這樣服務(wù)器可以知道該用戶是否是合法用戶以及是否需要重新登錄等,服務(wù)器可以利用Cookies包含信息的任意性來篩選并經(jīng)常性維護(hù)這些信息,以判斷在HTTP傳輸中的狀態(tài)

Cookie特點(diǎn)

  • Cookie以鍵值對(duì)的方式存儲(chǔ)數(shù)據(jù)
  • Cookie基于域名安全,不同域名下的Cookie是不可以互相訪問的
  • 當(dāng)瀏覽器請(qǐng)求某網(wǎng)站時(shí),會(huì)將瀏覽器存儲(chǔ)的跟網(wǎng)站相關(guān)的所以Cookiet提交給網(wǎng)站服務(wù)器

設(shè)置Cookie

def cookie_set(request):
    response = HttpResponse("<h2>設(shè)置Cookie,請(qǐng)查看響應(yīng)報(bào)文頭</h2>")
    response.set_cookie('h2', '你好')
    return response

讀取Cookie

def cookie_get(request):
    response = HttpResponse("讀取Cookie,數(shù)據(jù)如下:<br>")
    if 'h2' in request.COOKIES:
        response.write('<h2>' + request.COOKIES['h2'] + '</h2>')
    return response

Session

對(duì)于敏感、重要的信息,建議要儲(chǔ)在服務(wù)器端,不能存儲(chǔ)在瀏覽器中,如用戶名、余額、等級(jí)、驗(yàn)證碼等信息

禁用Session中間件

存儲(chǔ)方式

存儲(chǔ)在數(shù)據(jù)庫中,如下設(shè)置可以寫,也可以不寫,這是默認(rèn)存儲(chǔ)方式
SESSION_ENGINE='django.contrib.sessions.backends.db'
存儲(chǔ)在緩存中:存儲(chǔ)在本機(jī)內(nèi)存中,如果丟失則不能找回,比數(shù)據(jù)庫的方式讀寫更快
SESSION_ENGINE='django.contrib.sessions.backends.cache'
混合存儲(chǔ):優(yōu)先從本機(jī)內(nèi)存中存取,如果沒有則從數(shù)據(jù)庫中存取
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'

依賴于Cookie

在使用Session后,會(huì)在Cookie中存儲(chǔ)一個(gè)sessionid的數(shù)據(jù),每次請(qǐng)求時(shí)瀏覽器都會(huì)將這個(gè)數(shù)據(jù)發(fā)給服務(wù)器,服務(wù)器在接收到sessionid后,會(huì)根據(jù)這個(gè)值找出這個(gè)請(qǐng)求者的Session

對(duì)象及方法

以鍵值對(duì)的格式寫session
request.session['鍵']=值
根據(jù)鍵讀取值
request.session.get('鍵',默認(rèn)值)
清除所有session,在存儲(chǔ)中刪除值部分
request.session.clear()
清除session數(shù)據(jù),在存儲(chǔ)中刪除session的整條數(shù)據(jù)
request.session.flush()
刪除session中的指定鍵及值,在存儲(chǔ)中只刪除某個(gè)鍵及對(duì)應(yīng)的值
del request.session['鍵']
設(shè)置會(huì)話的超時(shí)時(shí)間,如果沒有指定過期時(shí)間則兩個(gè)星期后過期
request.session.set_expiry(value) 如果value是一個(gè)整數(shù),會(huì)話將在value秒沒有活動(dòng)后過期,如果value為0,那么用戶會(huì)話的Cookie將在用戶的瀏覽器關(guān)閉時(shí)過期,如果value為None,那么會(huì)話永不過期

No.5 模板

負(fù)責(zé)封裝構(gòu)造要返回的html

模板語言

變量

語法:{{變量}}

解析順序:

  • 字典book['title']
  • 先屬性后方法,將book當(dāng)作對(duì)象,先把title當(dāng)作屬性,如果找不到會(huì)認(rèn)為它是方法
  • 如果格式是book 0,則解析為book[0]
標(biāo)簽

for

{% for item in book_list %}
    循環(huán)邏輯
    {{forloop.counter}}表示當(dāng)前是第幾次循環(huán),從1開始
    {%empty%}列表為空?qǐng)?zhí)行此邏輯
{% end for %}

if

{%if ...%}
    邏輯1
{%elif ...%}
    邏輯2
{%else%}
    邏輯3
{%endif%}
過濾器

語法:變量|過濾器:參數(shù)

data|default:'默認(rèn)值'

更多內(nèi)建過濾器

自定義過濾器

在應(yīng)用中創(chuàng)建templatetags目錄

在該目錄下創(chuàng)建filters.py文件

#導(dǎo)入Library類
from django.template import Library

#創(chuàng)建一個(gè)Library類對(duì)象
register=Library()

#使用裝飾器進(jìn)行注冊(cè)
@register.filter
#定義求余函數(shù)mod,將value對(duì)2求余
def mod(value):
    return value%2 == 0

使用load標(biāo)簽引入模塊

{%load filters%}

模板繼承

父模板

如果發(fā)現(xiàn)在多個(gè)模板中某些內(nèi)容相同,那就應(yīng)該把這段內(nèi)容定義到父模板中

標(biāo)簽block:用于在父模板中預(yù)留區(qū)域,留給子模板填充差異性的內(nèi)容,名字不能相同

{%block 名稱%}
預(yù)留區(qū)域,可以編寫默認(rèn)內(nèi)容,也可以沒有默認(rèn)內(nèi)容
{%endblock  名稱%}
字模板

標(biāo)簽extends:繼承,寫在子模板文件的第一行

{% extends "父模板路徑"%}
{%block 名稱%}
實(shí)際填充內(nèi)容
{{block.super}}用于獲取父模板中block的內(nèi)容
{%endblock 名稱%}

CSRF

跨站請(qǐng)求偽造,CSRF指***者盜用了你的身份,以你的名義發(fā)送惡意請(qǐng)求

CSRF能夠做的事情:以你名義發(fā)送郵件,發(fā)消息,盜取你的賬號(hào),甚至于購買商品,虛擬貨幣轉(zhuǎn)賬......

造成的問題:個(gè)人隱私泄露以及財(cái)產(chǎn)安全

Python全棧開發(fā)之Django基礎(chǔ)

如果想防止CSRF,首先是重要的信息傳遞都采用POST方式而不是GET方式

防止CSRF

  • Django提供了csrf中間件用于防止CSRF***,只需要在mysite/settings.py中啟用csrf中間件即可
  • 接下來templates/app01/post.html內(nèi)容,在form表單中使用標(biāo)簽csrf_token

保護(hù)原理

加入csrf_token這個(gè)標(biāo)簽后,會(huì)想客戶端瀏覽器寫入一條cookie,還會(huì)在表單中加入一個(gè)隱藏域,里面存放有一個(gè)value值,然后提交數(shù)據(jù)的時(shí)候,會(huì)將這兩個(gè)值提交到服務(wù)器進(jìn)行校驗(yàn),如果value值cookie值相同,正常執(zhí)行業(yè)務(wù)邏輯,否則,返回403錯(cuò)誤

驗(yàn)證碼

新用戶注冊(cè),為了防止請(qǐng)求過多,可以加入驗(yàn)證碼功能,如果驗(yàn)證碼錯(cuò)誤,不需要執(zhí)行后續(xù)操作,減輕服務(wù)器的壓力

手動(dòng)實(shí)現(xiàn)驗(yàn)證碼
  • 安裝Pillow
pip3 install Pillow
  • 在app01/views中,創(chuàng)建視圖函數(shù)
from PIL import Image, ImageDraw, ImageFont
from django.utils.six import BytesIO
...
def verify_code(request):
    #引入隨機(jī)函數(shù)模塊
    import random
    #定義變量,用于畫面的背景色、寬、高
    bgcolor = (random.randrange(20, 100), random.randrange(
        20, 100), 255)
    width = 100
    height = 25
    #創(chuàng)建畫面對(duì)象
    im = Image.new('RGB', (width, height), bgcolor)
    #創(chuàng)建畫筆對(duì)象
    draw = ImageDraw.Draw(im)
    #調(diào)用畫筆的point()函數(shù)繪制噪點(diǎn)
    for i in range(0, 100):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
        draw.point(xy, fill=fill)
    #定義驗(yàn)證碼的備選值
    str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
    #隨機(jī)選取4個(gè)值作為驗(yàn)證碼
    rand_str = ''
    for i in range(0, 4):
        rand_str += str1[random.randrange(0, len(str1))]
    #構(gòu)造字體對(duì)象,ubuntu的字體路徑為“/usr/share/fonts/truetype/freefont”
    font = ImageFont.truetype('FreeMono.ttf', 23)
    #構(gòu)造字體顏色
    fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
    #繪制4個(gè)字
    draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
    draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
    draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
    draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
    #釋放畫筆
    del draw
    #存入session,用于做進(jìn)一步驗(yàn)證
    request.session['verifycode'] = rand_str
    #內(nèi)存文件操作
    buf = BytesIO()
    #將圖片保存在內(nèi)存中,文件類型為png
    im.save(buf, 'png')
    #將內(nèi)存中的圖片數(shù)據(jù)返回給客戶端,MIME類型為圖片png
    return HttpResponse(buf.getvalue(), 'image/png')
  • 打開app01/urls.py文件,配置url
url(r'^verify_code/$', views.verify_code),
調(diào)用驗(yàn)證碼
  • 在app01/views.py文件中,創(chuàng)建視圖verify_show
def verify_show(request):
    return render(request,'app01/verify_show.html')
  • 打開bapp01/urls.py文件,配置url
    url(r'^verify_show/$', views.verify_show),
  • 在templates/app01/目錄下創(chuàng)建verify_show.html
<html>
<head>
    <title>驗(yàn)證碼</title>
</head>
<body>
<form method="post" action="/verify_yz/">
    {%csrf_token%}
    <input type="text" name="yzm">
    <img id="yzm" src="/verify_code/"/>
    <span id="change">看不清,換一個(gè)</span>
    <br>
    <input type="submit" value="提交">
</form>
</body>
</html>
驗(yàn)證
  • 在app01/views.py文件中,創(chuàng)建視圖verify_yz
def verify_yz(request):
    yzm=request.POST.get('yzm')
    verifycode=request.session['verifycode']
    response=HttpResponse('no')
    if yzm==verifycode:
        response=HttpResponse('ok')
    return response
  • 打開app01/urls.py文件,配置url
    url(r'^verify_yz/$', views.verify_yz),
看不清,換一個(gè)
<script type="text/javascript" src="/static/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#change').css('cursor','pointer').click(function() {
            $('#yzm').attr('src',$('#yzm').attr('src')+1)
        });
    });
</script>
...
<img id="yzm" src="/verify_code/?1"/>
<span id="change">看不清,換一個(gè)</span>

反向解析

  • 在app01/urls.py中為include定義namespace屬性
url(r'^',include('app01.urls',namespace='app01')),
  • 在app01/urls.py中為url定義name屬性,并修改為fan2
    url(r'^fan2/$', views.fan2,name='fan2'),
  • 在模板中使用url標(biāo)簽做超鏈接,此處為templates/app01/fan1.html文件
<html>
<head>
    <title>反向解析</title>
</head>
<body>
普通鏈接:<a href="/fan2/">fan2</a>
<hr>
反向解析:<a href="{%url 'booktest:fan2'%}">fan2</a>
</body>
</html>
  • 在app01/urls.py中,將fan2修改為fan_show
url(r'^fan_show/$', views.fan2,name='fan2'),
  • 反向解析也可以應(yīng)用在視圖的重定向中
from django.shortcuts import redirect
from django.core.urlresolvers import reverse

return redirect(reverse('app01:fan2'))

總結(jié):在定義url時(shí),需要為include定義namespace屬性,為url定義name屬性,使用時(shí),在模板中使用url標(biāo)簽,在視圖中使用reverse函數(shù),根據(jù)正則表達(dá)式動(dòng)態(tài)生成地址,減輕后期維護(hù)成本

No.6 后臺(tái)

內(nèi)容發(fā)布的部分由網(wǎng)站的管理員負(fù)責(zé)查看、添加、修改、刪除數(shù)據(jù),開發(fā)這些重復(fù)的功能是一件單調(diào)乏味、缺乏創(chuàng)造力的工作,為此,Django能夠根據(jù)定義的模型類自動(dòng)地生成管理模塊

頁選項(xiàng)

頁大小,每頁顯示多少條數(shù)據(jù)

list_per_page=100

操作選項(xiàng)的位置

actions_on_top=True 頂部顯示的屬性,True為顯示,默認(rèn)為True,F(xiàn)alse即為不顯示
actions_on_bottom=True 同上,只不過是底部顯示的屬性

字段排序

admin_order_field=[字段1,字段2]

列標(biāo)題

short_description='列標(biāo)題'

側(cè)邊欄過濾器

list_filter=[]

搜索框

search_fields=[]

中文標(biāo)題

在模型類的字段為其指定verbose_name

分組顯示

fieldset=(
    ('組1標(biāo)題',{'fields':('字段1','字段2')}),
    ('組2標(biāo)題',{'fields':('字段3','字段4')}),
)

上傳圖片

創(chuàng)建包含圖片類型字段的模型類

將模型的類型定義成ImageField字段

class Pic(models.Model):
    pic = models.ImageField(upload_to='app01/')

遷移

python managee.py makemigrations
python manage.py migrate

設(shè)置圖片保存位置

MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")
并且在static創(chuàng)建media目錄,在meida目錄下創(chuàng)建應(yīng)用名稱的目錄,此為app01
在管理頁面上傳圖片

在admin中注冊(cè)該模型類

admin.site.register(Pic)
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI