若本文有任何內容錯誤,望各位大佬指出批評,並請直接聯繫做者修改,謝謝!小白學習不易。css
模型類操做數據表:html
python manage.py shell
製做遷移文件:python
python manage.py makemigrations
執行遷移文件:mysql
python manage.py migrate
from booktest.models import BookInfo
實例化對象,設置對象實例屬性值,調用對象.save()方法jquery
查詢:ajax
b = BookInfo.objects.get #要查詢的條件,如id=1
b是根據條件查詢到的內容,類型爲BookInfo對象正則表達式
實體類之間的主外鍵:主類:sql
hbook = models.ForeignKey('BookInfo')
h2.hbook = b #h2爲實例化對象,b爲bookInfo的實例化對象,主外鍵對應
b.heroinfo_set.all()查詢與外鍵相關聯的主鍵集合shell
class AreaInfo(models.Model): atitle = models.CharField(verbose_name='地區',max_length=20) # verbose_name指定屬性列列名稱 def title(self): return self.atitle title.admin_order_field = 'atitle' #指定該列點擊列標題根據atitle進行排序 title.short_description = '地區名稱' #指定該列列標題爲地區名稱
重寫str方法可以讓管理頁面顯示正確的中文內容數據庫
在admin中註冊實體類信息,管理員可進行後臺管理,實行數據的CRUD,此外,在admin中創建自定義模型管理類class,繼承admin.ModelAdmin能夠設置頁面顯示內容:
class AreaInfoAdmin(admin.ModelAdmin): list_display = ['id','btitle','bpub_date'] #頁面數據顯示格式 list_per_page=['10'] #能夠設置每頁顯示數據條數, list_filter=['atitle'] #列表右側過濾欄,一標題進行過濾,可進行快速查找 actions_on_bottom = True # 操做欄顯示在下面 search_fields=['atitle'] #列表頁上方的搜索框,以標題進行搜索 fields=['字段1','字段2'] #指定編輯頁的上下順序 admin.site.register(AreaInfo, AreaInfoAdmin)
一對多的關係中,在一端的編輯頁面中編輯多端的對象,可嵌入表格或塊兩種,InlineModelAdmin:在編輯頁面嵌入關聯的模型;TabularInline:以表格形式嵌入;StackedInline:以塊形式嵌入:
booktest/admin.py:
class AreaStackedInline(admin.StatickedInline): model = AreaInfo # 關聯子對象 extra = 2 # 增長兩個額外的子對象
在booktest/admin.py中,AreaAdmin類:
class AreaAdmin(admin.ModelAdmin): ...... inlines = [AreaStackedInline]
from django.http import HttpResponse
函數,參數爲request,返回 HttpResponse()
在新建urls裏配置url,
from django.conf.urls import url from booktest import views url(r'^index$',views.index) #創建index和視圖index之間的關係,嚴格匹配開頭和結尾
在系統urls中添加配置項
url(r'^', include('booktest.urls')) # 包含booktest應用中的應用文件
settings裏TRMPLATES的DIRS設置模板路徑:
'DIRS':[os.path.join(BASE_DIR,,'templates')]
DATABASES: 'NAME':'數據庫名', 'USER':'用戶名', 'PASSWORD':'密碼', 'HOST':'IP', 'PORT':3306,
__init__.py裏:
import pymysql pymysql.install_as_MySQLdb()
在views裏寫index方法:
from django.template import loader def index(request): temp = loader.get_template('booktest/index.html') # 加載模板文件 context = RequestContext(request,{ }) # 定義模板上下文,給模板傳數據 res_html = temp.render(context) # 模板渲染:產生標準的HTML內容 return HttpResponse(res_html) # 返回給瀏覽器
簡化方法一:*******將此函數封裝成固定函數
def my_render(request,template_path,context_dict): temp = loader.get_template(template_path) # 加載模板文件 context = RequestCOntext(request,context_dict) # 定義模板上下文,給模板傳數據 res_html = temp.render(context) # 模板渲染:產生標準的HTML內容 return HttpResponse(res_html) # 返回給瀏覽器
簡化方法二:*******直接調用系統方法
return render(request,'booktest/index.html',{'grent':'hello django!'})
HTML頁面用{{ content }}顯示傳輸的數據
傳輸列表:
render(request,'booktest/index.html',{'list':list(range(1,10))})
HTML頁面用{{ list }}直接顯示內容
遍歷:
{% for i in list %} <li>{{ i }}</li> {% empty %} 若值問空,則調用此方法 <li>沒有值</li> {% endfor %} 能夠經過{{ forloop.counter }}的到遍歷到了第幾回 {% if 條件 %} {% elif 條件 %} {% else %} {% endif %}
關係比較符:> < >= <= == !=(進行比較操做時,操做符兩邊必須有空格!)
邏輯運算:not and or
連接傳值時的urls設置
url(r'^books/(\d+)$' , views.detail)
(\d+須要加括號),分組。
get 返回的事查詢到的對象,其他返回的是查詢集的對象
等值查詢:
BookInfo.objects.get(id=1) == BookInfo.objects.get(id__exact=1)
模糊查詢: **全部下劃線均爲雙下劃線**
BookInfo.objects.filter(btitle__contains='傳') #包含 BookInfo.objects.filter(btitle__endswith='部') #以關鍵字結尾
空查詢:
BookInfo.objects.filter(btitle__isnull=False) #不爲空
範圍查詢:
BookInfo.objects.filter(id__in=[1,3,5]) #查詢id爲1或3或5的書籍
比較查詢:gt(greatr than)、lt(less than) gte(equals) lte(<=)
BookInfo.objects.filter(id__gt=3) #查詢編號大於3的圖書
日期查詢:
BookInfo.objects.filter(bpub_date__year=1990) #查詢日期爲1990年發表的圖書 BookInfo.objects.filter(bpub_date__gt=date(1990,1,1)) #查詢1990年1月1往後發表的書
BookInfo.objects.exclude(id=3) #查詢id不爲3的書籍
order_by:
BookInfo.objects.all().order_by('id') #根據id從小到大排序 BookInfo.objects.all().order_by('-id') #從大到小
from django.db import Q
或:
BookInfo.objects.filter(Q(id__gt=3)|Q(bread__gt=30))
且:
BookInfo.objects.filter(id__gt=3,bread__gt=30) == BookInfo.objects.filter(Q(id__gt=3)&Q(bread__gt=30))
非:
BookInfo.objects.filter(~Q(id=3))
(類屬性之間的比較)
from django.db import F BookInfo.objects.filter(bread__gt = F('bcomment')) #查詢圖書閱讀量大於2倍評論量圖書信息
aggregate進行聚合操做,返回值是一個字典
sum count avg max min
from django.db.models import Sum,Count,Max,Min,Avg BookInfo.objects.all().aggregate(Count('id')) #返回字典 BookInfo.objects.all().count() #返回數值
只有在真正使用查詢集中的數據的時候纔會真正發生對數據庫的真正查詢;
當使用的是同一個查詢集時,第一次的查詢會將結果緩存,以後使用的是緩存中的結果;
可對查詢集進行切片,可是下標不能爲負數;
一對多:models.ForeignKey() ——必須定義在多的類中
多對多:models.ManyToManyField()
一對一:models.OneToOneField()
id爲1的圖書關聯英雄信息:
b = BookInfo.objects.get(id=1) b.heroinfo_set.all()
BoojInfo圖書類 —— 一類 HeroInfo英雄人物類 —— 多類
b.heroinfo_set.all() —— 一查多
h.hbook —— 多查一
objects爲models。Manager類對象,每一個類都有
通常自定義模型管理類,繼承自models.Manager,可自定義函數改變查詢的結果集
類中使用self.model()能夠建立跟自定義管理器對應的模型類對象。
圖一:管理器流程圖
在項目中遇到中途須要修改項目名等狀況時,能夠指定元類,讓模型表名不依賴於對應的表名:
class Meta: db_table = 'bookinfo'
視圖函數:
request參數必須有,參數名能夠變化,是一個HttpRequest類型的對象。
找不到頁面,關閉settings裏的調試模式後,默認會顯示一個標準的錯誤頁面,自定義錯誤頁面,須要在templates目錄下自定義一個404.html文件。
錯誤:404——url沒有配置/url配置錯誤
500——視圖出錯
網站開發完成須要關閉調試模式:
DEBUG = False ALLOWED_HOST = [ '*' ]
將所要捕獲的部分設置成正則表達式組,django會自動將匹配成功的相應組內容做爲參數傳遞給視圖參數。
頁面表單的POST和GET:
POST——數據在請求頭中,多出如今表單
GET——數據在url中,不安全,多出如今超連接
後臺經過request去獲取數據,是一個QueryDict對象,裏面的鍵可重複,取到的是後面的值,用getlist('鍵')可取到某名的全部值,用類字典方式提取,最好用get方法,不存在不會報錯。
重要兩點:訪問地址時須要攜帶的參數;試圖處理完成後返回的json格式。
應用文件下建立static文件夾,在settings裏配置
STATIC_URL = '/static/' #HTML頁面訪問靜態文件對應的url地址 STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
須要先導入jquery文件,並在HTML文件裏引用,隨後:
<script> $(function(){ $('#btnAjax').click(function(){ alert(1) $.ajax({ 'url':請求地址, 'type':請求方式, 'dataType':預期返回的數據格式, 'data':參數 }).success(function(data){ //執行成功後的回調函數 alert(2) if(data.res == 1){ $('#message').show().html('自定義提示信息!') } }) alert(3) }) }) </script> <input tybe='button' id='btnAjax' value='ajax請求'/>
Django返回: return JsonResponse({'res':1})
異步:alert順序1-3-2,也就是在按鈕事件後,會繼續執行ajax中的代碼,而不會等服務器把結果發來以後再執行回調函數success。
同步:在ajax請求里加上 'async':false, 就會是同步的ajax請求。
添加cookie緩存須要HttpResponse對象的一個實例調用.set_cookie()方法,參數爲鍵值對,取出cookie爲request.COOKIES()參數爲鍵名
圖二:session流程圖
以鍵值對存儲,依賴於cookie,默認兩週過時。
設置:
request.session['username']='jery'
取值:
request.session['username']
cookie:記住用戶名,安全性要求不高,
session:安全性比較高,帳戶,密碼,餘額等。
兩部分:靜態內容(css,js,html);動態內容(模板語言:編程語言)
去配置的模板目錄下找模板文件;
去INSTALLED_APPS下每一個應用找模板文件,前提是應用中必須有templates文件夾(templates——>admin——>auth)
模板語言(DTL Django Template Language):
模板變量:
{{ book.btitle }}解析順序:
book當成字典,btitle當成鍵名,取值book['btitle'];
book當成對象,btitle當成屬性,取值book.btitle;
book當成對象,btitle當成對象的方法,取值book.btitle;
{{ book.0 }}解析順序:
book當成字典,0當成鍵名,取值book['0']
book當成列表,0當成下標,取值book[ 0 ]
若解析失敗,產生內容時Django框架會自動用空字符串填充模板變量。
模板變量|過濾器:參數
如:
{{ book.bpub_date|date:'Y年-m月-d日' }} {{ book.btitle|length }} {{ content|default:'爲空' }}
自定義過濾器:應用下新建templatetags
新建自定義名filters.py文件:
from django.template import Library register = Library() @register.filter def mod(num): return num%2 == 0 #判斷num是否爲偶數
HTML引用過濾器:
{% load filters %} {% if book.id|mod %}
(網頁源代碼不會顯示註釋的內容):
單行註釋:{# 註釋內容 #}
多行註釋:{% comment %} 註釋內容 {% endcomment %}
父文件:
{% block 塊名 %} 中間內容可爲空 {% endblock 塊名 %}
子文件:
{% extends 'booktest:/base.html' %}
{% block 塊名 %} 覆蓋子模板內容,也可調用父模板內容{{ block.super }} {% endblock 塊名 %}
模板上下文中的html標籤默認會被轉義,關閉轉義可用:
safe過濾器:{{ 模板變量|safe }}
autoescape標籤:{{% autoescape off %}}被取消轉義的內容 {{% endautoescape %}}
登陸裝飾器:
有些頁面是用戶登陸以後才能訪問的,訪問某些抵制須要先進性登陸的判斷,即攔截器,此過程可定義爲一個裝飾器:
def login_required(view_func): def wrapper(request, *view_args, **view_kwargs): if request.session.has_key('isLogin') return view_func(request, *view_args, **view_kwargs) else: return redirect('/login') return wrapper
view函數前引用@login_required
在已經登陸某網站後,其餘網站或網頁利用緩存數據模擬向網站發出一些請求,即跨站請求。
圖三:csrf攻擊模式
方法:
Django默認啓用csrf防禦,只針對post請求生效;
在表單post提交數據時附加上 {% csrf token %} 標籤可禁止csrf僞造。
防護原理:
1)渲染模板文件時在頁面生成一個名字叫作csrfmiddlewaretoken的隱藏域。
2)服務器交給瀏覽器保存一個名字爲csrftoken的cookie信息。
3)提交表單時兩個值都會發給服務器,服務器進行比對,若是同樣,則csrf驗證經過,不然失敗。
避免網頁名的改變而致使大規模改動名稱,動態生成url地址:<a href="{% url 'booktest:index' %}">首頁</a>
若urls中的url帶name捕獲的位置參數,則在動態生成地址時須要明確指定。
eg:
urls:
url(r'^show_args/(\d+)/(\d+)$', views.show_args, name='show_args')
views:
def show_args(request,a,b): return HttpResponse(a+':'+b)
html:動態產生/show_args/1/2:
<a href="{% url 'booktest:show_args' 1 2 %}">首頁</a>
在重定向時使用反向解析:
from django.core.urlresolvers import reverse
無參數:reverse('namespace 名字: name 名字')
有位置參數:reverse('namespace 名字: name 名字',args=位置參數元組)
應用文件下建立static文件夾,在settings裏配置
STATIC_URL = '/static/' # HTML頁面訪問靜態文件對應的url地址 STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
HTML頁面頂部{% load staticfiles %}
<img src="{% static 'images/a.jpg' %}">
干預和請求問答過程:
使用request對象META屬性在view視圖裏獲取瀏覽器端ip地址:request.META[' REMOTE_ADDR ']
新建middleware.py中間件(在視圖函數調用以前被調用,裝飾器寫法):
class BlockedIPSMiddleware(boject): EXCLUDE_IPS = ['10.10.66.110'] #被禁止訪問的ip地址 def process_view(request, view_func, *view_args, **view_kwargs): user_ip = request.META[' REMOTE_ADDR '] if user_ip in BlockedIPSMiddleware.EXCLUDE_IPS: return HttpResponse('<h1>Forbidden</h1>')
須要在settings裏的MIDDLEWARE_CLASSES裏註冊此類:'booktest.middleware.BlockedIPSMiddleware',
中間件處理流程:
圖四:中間件處理流程圖
middleware.py:
class TestMiddleware(object):
__init__:服務器響應第一個請求時調用;
process_request:產生request對象
process_view:url匹配後,調用視圖函數以前;
process_response(self, request, response):視圖函數調用以後,內容返回給瀏覽器以前;
process_exception:視圖哈數出現異常,會調用此函數。
若是註冊的多箇中間件類中包含process_exception函數時,調用的順序和註冊的順序相反,從下往上,全部異常都是從下往上回找。
settings配置保存文件目錄:MEDIA_ROOT = os.path.join(BASE_DIR, 'static/media')
後臺管理上傳圖片:
設計models模型類:
class PicTest(models.Model): goods_pic = models.ImageField(upload_to = 'booktest')
遷移類文件,註冊模型類即完成
用戶自定義頁面上傳:
表單上傳,HTML頁面:
<form method="post" enctype="multipart/form-data" action="/upload_handle">{#enctype指定全部的值 都是以二進制進行傳遞#} {% csrf_token %} <input type="file" name="pic"> <input type="submit" value="上傳"> </form>
views.py接收:使用reqeust對象的FILES屬性,相似於字典,上傳文件不大於2.5M,文件存放在內存中,上傳文件大於2.5M,文件內容寫到一個臨時文件中。request.FILES只有在請求方法爲POST,且發送請求的form擁有enctype="multipart/form-data" 屬性,纔會包含數據。
def upload_handle(request): pic = request.FILES['pic'] # 獲取處理對象 save_path = '%s/booktest/%s'%(settings.MEDIA_ROOT, pic.name) #保存路徑 with open(save_path, 'wb') as f: for content in pic.chunks(): #一次返回文件的一塊內容 f.write(content) PicTest.objects.create(goods_pic='booktest%s'.pic.name) return HttpResponse("上傳成功!")
from django.core.paginator import Paginator paginator=Paginator(areas, 10) #按每頁10條數據進行分頁
Paginator類對象的屬性:
屬性名 |
說明 |
num_pages |
返回分頁以後的總頁數 |
page_range |
返回分頁後頁碼的列表 |
Paginator類對象的方法:
方法名 |
說明 |
page(self, number) |
返回第number也的Page類實例對象 |
Page類對象的方法:
屬性名 |
說明 |
has_previous |
判斷當前頁是否有前一頁 |
has_next |
判斷當前頁是否有下一頁 |
previous_page_number |
返回前一頁的頁碼 |
next_page_number |
返回下一頁的頁碼 |
booktest/urls.py:
url(r'^show_area(?P<pindex>\d*)$', view.show_area), #分頁,接收頁面傳來的頁碼
views.py:
from django.core.paginator import Paginator def show_area(request, pindex): ares = AreaInfo.objects.filter(aParent__isnull=True) #查詢信息 paginator = Paginator(ares, 10) if pindex =='': pindex = 1 #默認取第一頁內容 else: pindex = int(pindex) page = paginator.page(pindex) #獲取第i頁內容 return render(request, 'booktest/show_area.html', {'page': page})
HTML:
<ul> {% for area in page.object_list %}或者{% for area in page %} <li>{{ area.atitle }}</li> {% endfor %} </ul> {% if page.has_previous %} <a href="/show_area{{ page.previous_page_number }}"><上一頁</a> {% endif %} {% for pindex in page.paginator.page_range %} {% if pindex == page.num %} {{ pindex }} {% else %} <a href="/show_area{{ pindex }}">{{ pindex }}</a> {% endfor %} {% if page.has_next %} <a href="/show_area{{ page.next_page_number }}"><下一頁</a> {% endif %}
Word文檔筆記看起更爽更全面:可聯繫做者