您好,登錄后才能下訂單哦!
M全拼為Model,主要封裝對數據庫層的訪問,對數據庫中的數據進行增、刪、改、查操作
V全拼為View,用于封裝結果,生成頁面展示的html內容
C全拼為Controller,用于接收請求,處理業務邏輯,與Model和View交互,返回結果
M全拼為Model,與MVC中的M功能相同,負責和數據庫交互,進行數據處理
V全拼為View,與MVC中的C功能相同,接收請求,進行業務處理,返回應答
T全拼為Template,與MVC中的V功能相同,負責封裝構造要返回的html
為什么要使用虛擬環境?
如果在一臺機器上,想開發不同的項目,這些項目依賴的同一個包的版本不同,其他項目就無法正常運行了,所有我們要用到虛擬環境,虛擬環境就是對真實Python環境的復制,通過建立多個虛擬環境,在不同的虛擬環境中開發項目就實現了項目之間的間隔
創建虛擬環境
pip3 install virtualenv # 安裝虛擬環境
pip3 install virtualenvwrapper-win # 安裝虛擬環境擴展包
mkvirtualenv 虛擬環境名稱 # 創建虛擬環境
deactivate # 退出虛擬環境
workon # 直接輸入workon查看已創建的虛擬環境,后面接虛擬環境名稱進入該虛擬環境
rmvirtualenv 虛擬環境名稱 # 刪除虛擬環境
pip list # 查看該虛擬環境中安裝的包
pip install # 虛擬環境包管理
pip install django==1.11.11 # 安裝django1.11.11
創建第一個項目
django-admin startproject mysite;
項目默認目錄
manage.py # 項目管理文件,通過它管理項目
與項目同名的目錄,此處為mysite
_init_.py # 一個空文件,作用是這個目錄test可以被當作包使用
settings.py # 項目的整體配置文件
urls.py # 項目的URL配置文件
wsgi.py # 項目與WSGI兼容的Web服務器入口
創建應用
python manage.py startapp app01;
應用目錄結構
__init__.py # 一個空文件,表示當前目錄可以當作一個python包使用
tests.py # 開發測試用例,在實際開發中會有專門的測試人員
models.py # 數據庫操作相關
views.py # 接收瀏覽器請求,進行處理,返回頁面相關
admin.py # 站點管理
migrations:
安裝應用
# mysite/setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
]
開發服務器
python manage.py runserver ip:端口
定義模型類
# 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 # 執行遷移
數據操作
# 進入項目并引入模塊
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()
# 對象關聯操作
HeroInfo.objects.create(hname='a1',hgender=False,hcomment='he is a boy',hbook=BookInfo.objects.get(id=1))
# 獲得關聯集合
BookInfo.objects.get(id=1).heroinfo_set.all()
管理頁面本地化
# mysite/setting.py
LANGUAGE_CODE = 'zh-hans' #使用中國語言
TIME_ZONE = 'Asia/Shanghai' #使用中國上海時間
創建管理員
python manage.py createsuperuser
注冊模型類
# 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
請求者在瀏覽器中輸入url,請求到網站后,獲取url信息,然后在URL.conf逐條匹配,如果匹配成功返回相應的視圖函數,如果所有URLconf都沒有匹配成功,返回404錯誤
# 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),
]
創建模板
# 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>
視圖調用模板
# app01/views.py
from django.shortcuts import render
def index(request):
context={'title':'圖書列表','list':range(10)}
return render(request,'app01/index.html',context)
負責和數據庫交互,進行數據處理
什么是orm?
對象關系映射,是隨著面向對象思想發展而產生的,是一種程序技術,用于實現面向對象編程語言里不同類型系統的數據之間的轉換,面向對象是從軟件工程基本原則(如耦合、聚合、封裝)的基礎上發展起來的,而關系數據庫則是從數學理論發展而來的,兩套理論存在顯著的區別,為了解決這個不匹配的現象,對象關系映射技術應運而生
使用MySQL
# mysite/setting.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'python', #數據庫名字,
'USER': 'root', #數據庫登錄用戶名
'PASSWORD': '123456', #數據庫登錄密碼
'HOST': 'localhost', #數據庫所在主機
'PORT': '3306', #數據庫端口
}
}
# mysite/__init__.py
import pymysql
pymysql.install_as_MySQLdb()
字段類型
字段約束
查詢
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='傳') # 不區分大小寫
startswith 以指定字符開頭
list = BookInfo.objects.filter(btitle__startswith='神')
list = BookInfo.objects.filter(btitle__istartswith='神') # 不區分大小寫
endswithch 以指定字符結尾
list = BookInfo.objects.filter(btitle__endswitch='侶')
list = BookInfo.objects.filter(btitle__iendswitch='侶') # 不區分大小寫
空查詢
isnull 是否為空
list = BookInfo.objects.filter(btitle__isnull=False)
范圍查詢
in 是否包含在范圍內
list = BookInfo.objects.filter(id__in=[1, 3, 5])
比較查詢
gt: 大于
gte: 大于等于
lt: 小于
lte:小于等于
list = BookInfo.objects.filter(id__gt=3)
不等于查詢
exclude() 不等于運算符
list = BookInfo.objects.exclude(id=3)
日期查詢
year、month、day、week_day、hour、minute、second
list = BookInfo.objects.filter(bpub_date__year=1980)
F對象
比較一個對象中的兩個屬性
list = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)
Q對象
多個過濾器逐個調用表示邏輯與關系,同sql語句中where部分的and關鍵字
list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)
如果想實現邏輯或的功能,就要使用到Q對象查詢,Q對象可以使用&、|連接,&表示邏輯與,|表示邏輯或,~表示not
list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))
聚合查詢
使用aggregate()過濾器調用聚合函數,聚合函數包括:Avg,Count,Max,Min,Sum
list = BookInfo.objects.count()
查詢集表示從數據庫中查詢到的對象集合
返回查詢集的過濾器
返回單個值的過濾器
判斷一個查詢集中是否有數據
兩個特性
限制結果集
可以對結果集進行切片操作,等同于數據庫中的分頁操作,但是不支持負數
list = BookInfo.objects.all()[0:2]
一對多
一本圖書中可以對應多個英雄,所以圖書和英雄是一對多的關系
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')
多對多
一個類別中多條新聞,一條新聞也可以分為不同的類別,所以新聞是多對多關系
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')
一端的對象.多端的類名_set
b = BookInfo.objects.get(id=1)
b.HeroInfo_set.all()
多端的模型對象.多端模型類的類關系字段
h = HeroInfo.objects.get(id=1)
h.hbook
多對應的模型類對象.關聯類屬性_id
h = HeroInfo.objects.get(id=1)
h.book_id
語法:
關聯模型類名小寫__屬性名__條件運算符=值
list = BookInfo.objects.filter(heroinfo__hcontent__contains='八')
語法:
一模型類關聯屬性名__一模型類屬性名__條件運算符=值
list = HeroInfo.objects.filter(hbook__btitle='天龍八部')
視圖負責接受Web請求HttpRequest,進行邏輯處理,返回Web響應HttpResponse給請求者
位置參數
url(r'^delete(\d+)/$',views.show_arg),
關鍵字參數
url(r'^delete(?P<id1>\d+)/$',views.show_arg),
內置錯誤視圖,如果想看到錯誤視圖而不是調試信息的話,需要修改setting文件的DEBUG選項
# mysite/setting.py
DEBUG = False
ALLOWED_HOSTS = ['*', ]
屬性
方法
set_cookie:設置Cookie信息
某些網站為了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據,Cookie是由服務器端生成,發送給User-Agent(一般是瀏覽器),瀏覽器會將Cookie的key/value保存到某個目錄下的文本文件內,下次請求同一網站時就發送該Cookie給服務器,Cookie名稱和值可以由服務器端開發自己定義,這樣服務器可以知道該用戶是否是合法用戶以及是否需要重新登錄等,服務器可以利用Cookies包含信息的任意性來篩選并經常性維護這些信息,以判斷在HTTP傳輸中的狀態
Cookie特點
設置Cookie
def cookie_set(request):
response = HttpResponse("<h2>設置Cookie,請查看響應報文頭</h2>")
response.set_cookie('h2', '你好')
return response
讀取Cookie
def cookie_get(request):
response = HttpResponse("讀取Cookie,數據如下:<br>")
if 'h2' in request.COOKIES:
response.write('<h2>' + request.COOKIES['h2'] + '</h2>')
return response
對于敏感、重要的信息,建議要儲在服務器端,不能存儲在瀏覽器中,如用戶名、余額、等級、驗證碼等信息
禁用Session中間件
存儲方式
存儲在數據庫中,如下設置可以寫,也可以不寫,這是默認存儲方式
SESSION_ENGINE='django.contrib.sessions.backends.db'
存儲在緩存中:存儲在本機內存中,如果丟失則不能找回,比數據庫的方式讀寫更快
SESSION_ENGINE='django.contrib.sessions.backends.cache'
混合存儲:優先從本機內存中存取,如果沒有則從數據庫中存取
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
依賴于Cookie
在使用Session后,會在Cookie中存儲一個sessionid的數據,每次請求時瀏覽器都會將這個數據發給服務器,服務器在接收到sessionid后,會根據這個值找出這個請求者的Session
對象及方法
以鍵值對的格式寫session
request.session['鍵']=值
根據鍵讀取值
request.session.get('鍵',默認值)
清除所有session,在存儲中刪除值部分
request.session.clear()
清除session數據,在存儲中刪除session的整條數據
request.session.flush()
刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值
del request.session['鍵']
設置會話的超時時間,如果沒有指定過期時間則兩個星期后過期
request.session.set_expiry(value) 如果value是一個整數,會話將在value秒沒有活動后過期,如果value為0,那么用戶會話的Cookie將在用戶的瀏覽器關閉時過期,如果value為None,那么會話永不過期
負責封裝構造要返回的html
語法:{{變量}}
解析順序:
for
{% for item in book_list %}
循環邏輯
{{forloop.counter}}表示當前是第幾次循環,從1開始
{%empty%}列表為空執行此邏輯
{% end for %}
if
{%if ...%}
邏輯1
{%elif ...%}
邏輯2
{%else%}
邏輯3
{%endif%}
語法:變量|過濾器:參數
data|default:'默認值'
更多內建過濾器
在應用中創建templatetags目錄
在該目錄下創建filters.py文件
#導入Library類
from django.template import Library
#創建一個Library類對象
register=Library()
#使用裝飾器進行注冊
@register.filter
#定義求余函數mod,將value對2求余
def mod(value):
return value%2 == 0
使用load標簽引入模塊
{%load filters%}
如果發現在多個模板中某些內容相同,那就應該把這段內容定義到父模板中
標簽block:用于在父模板中預留區域,留給子模板填充差異性的內容,名字不能相同
{%block 名稱%}
預留區域,可以編寫默認內容,也可以沒有默認內容
{%endblock 名稱%}
標簽extends:繼承,寫在子模板文件的第一行
{% extends "父模板路徑"%}
{%block 名稱%}
實際填充內容
{{block.super}}用于獲取父模板中block的內容
{%endblock 名稱%}
跨站請求偽造,CSRF指***者盜用了你的身份,以你的名義發送惡意請求
CSRF能夠做的事情:以你名義發送郵件,發消息,盜取你的賬號,甚至于購買商品,虛擬貨幣轉賬......
造成的問題:個人隱私泄露以及財產安全
如果想防止CSRF,首先是重要的信息傳遞都采用POST方式而不是GET方式
防止CSRF
保護原理
加入csrf_token這個標簽后,會想客戶端瀏覽器寫入一條cookie,還會在表單中加入一個隱藏域,里面存放有一個value值,然后提交數據的時候,會將這兩個值提交到服務器進行校驗,如果value值cookie值相同,正常執行業務邏輯,否則,返回403錯誤
新用戶注冊,為了防止請求過多,可以加入驗證碼功能,如果驗證碼錯誤,不需要執行后續操作,減輕服務器的壓力
pip3 install Pillow
from PIL import Image, ImageDraw, ImageFont
from django.utils.six import BytesIO
...
def verify_code(request):
#引入隨機函數模塊
import random
#定義變量,用于畫面的背景色、寬、高
bgcolor = (random.randrange(20, 100), random.randrange(
20, 100), 255)
width = 100
height = 25
#創建畫面對象
im = Image.new('RGB', (width, height), bgcolor)
#創建畫筆對象
draw = ImageDraw.Draw(im)
#調用畫筆的point()函數繪制噪點
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)
#定義驗證碼的備選值
str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
#隨機選取4個值作為驗證碼
rand_str = ''
for i in range(0, 4):
rand_str += str1[random.randrange(0, len(str1))]
#構造字體對象,ubuntu的字體路徑為“/usr/share/fonts/truetype/freefont”
font = ImageFont.truetype('FreeMono.ttf', 23)
#構造字體顏色
fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
#繪制4個字
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,用于做進一步驗證
request.session['verifycode'] = rand_str
#內存文件操作
buf = BytesIO()
#將圖片保存在內存中,文件類型為png
im.save(buf, 'png')
#將內存中的圖片數據返回給客戶端,MIME類型為圖片png
return HttpResponse(buf.getvalue(), 'image/png')
url(r'^verify_code/$', views.verify_code),
def verify_show(request):
return render(request,'app01/verify_show.html')
url(r'^verify_show/$', views.verify_show),
<html>
<head>
<title>驗證碼</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">看不清,換一個</span>
<br>
<input type="submit" value="提交">
</form>
</body>
</html>
def verify_yz(request):
yzm=request.POST.get('yzm')
verifycode=request.session['verifycode']
response=HttpResponse('no')
if yzm==verifycode:
response=HttpResponse('ok')
return response
url(r'^verify_yz/$', views.verify_yz),
<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">看不清,換一個</span>
url(r'^',include('app01.urls',namespace='app01')),
url(r'^fan2/$', views.fan2,name='fan2'),
<html>
<head>
<title>反向解析</title>
</head>
<body>
普通鏈接:<a href="/fan2/">fan2</a>
<hr>
反向解析:<a href="{%url 'booktest:fan2'%}">fan2</a>
</body>
</html>
url(r'^fan_show/$', views.fan2,name='fan2'),
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
return redirect(reverse('app01:fan2'))
總結:在定義url時,需要為include定義namespace屬性,為url定義name屬性,使用時,在模板中使用url標簽,在視圖中使用reverse函數,根據正則表達式動態生成地址,減輕后期維護成本
內容發布的部分由網站的管理員負責查看、添加、修改、刪除數據,開發這些重復的功能是一件單調乏味、缺乏創造力的工作,為此,Django能夠根據定義的模型類自動地生成管理模塊
頁大小,每頁顯示多少條數據
list_per_page=100
操作選項的位置
actions_on_top=True 頂部顯示的屬性,True為顯示,默認為True,False即為不顯示
actions_on_bottom=True 同上,只不過是底部顯示的屬性
字段排序
admin_order_field=[字段1,字段2]
列標題
short_description='列標題'
側邊欄過濾器
list_filter=[]
搜索框
search_fields=[]
中文標題
在模型類的字段為其指定verbose_name
分組顯示
fieldset=(
('組1標題',{'fields':('字段1','字段2')}),
('組2標題',{'fields':('字段3','字段4')}),
)
將模型的類型定義成ImageField字段
class Pic(models.Model):
pic = models.ImageField(upload_to='app01/')
遷移
python managee.py makemigrations
python manage.py migrate
設置圖片保存位置
MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")
并且在static創建media目錄,在meida目錄下創建應用名稱的目錄,此為app01
在admin中注冊該模型類
admin.site.register(Pic)
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。