day17 2018-08-12 Django框架02 1. 今日內容: 1. 新建Django項目梳理 1. 模板文件路徑配置 2. 數據庫配置 3. 靜態文件配置 4. 註釋掉csrf中間件那一行 2. Django默認sqlite3數據庫的簡單用法 3. 路由系統進階:https://www.cnblogs.com/liwenzhou/articles/8271147.html - 動態路由 urls.py中經過正則表達式的分組匹配,捕獲用戶訪問的url中的值,傳遞給視圖函數 分組匹配: 至關於給視圖函數傳遞 位置參數 分組命名匹配: 至關於給視圖函數傳遞 關鍵字參數 - name 防止將url硬編碼到咱們的業務邏輯代碼中,給url起別名 經過別名,反向找到 url 在views.py中: from django.urls import reverse 具體的url = reverse('url別名') 4. 視圖函數進階:https://www.cnblogs.com/liwenzhou/articles/8305104.html 1. views.py 1. 基礎必會三件套 1. HttpResponse('字符串') 2. render(request, "xx.html", {"key": value}) 3. redirect("/其它的url/") 2. FBV(Function Base View) 基於函數的視圖 經過request.method == "POST" 去判斷 3. CBV(Class Base View) 基於類的視圖 1. 必須繼承views.View --> from django import views 2. 寫一個本身的視圖類 3. 經過定義不一樣的方法,來處理用戶不一樣的請求 4. 在urls.py中註冊視圖的時候要寫 views.類名.as_view() 2. request對象的經常使用屬性和方法 request表示的是和用戶請求相關的全部數據 1. request.method --> 用戶當前請求的請求方法 2. request.GET --> 用戶請求中url中的參數 3. request.POST --> 用戶POST請求的數據 4. request.path_info --> 用戶訪問的url路徑是什麼 3. Django上傳文件 1. 前端頁面 1. form表單必定要有action,method必須是post 2. 必定要配置enctype="multipart/form-data 2. 後端: def post(self, request): # 拿到用戶發送的文件數據 file_obj = request.FILES.get("code") # 保存下來 # 1. 拿到用戶上傳的文件名 filename = file_obj.name # 2. 在服務端建立一個同名的文件 with open(filename, "wb") as f: # 3. 從用戶上傳的文件對象中一點一點讀數據,往我本地建立的文件句柄裏一點一點寫 for i in file_obj.chunks(): f.write(i) return HttpResponse("上傳成功!") 4. JsonResponse 專門用來返回JSON格式數據的響應對象 from django.http import JsonResponse 5. 模板引擎進階:https://www.cnblogs.com/liwenzhou/p/7931828.html 1. 已經學過的Django模板語言的語法 1. 兩個語法: 1. {{ }} --> 跟變量相關的操做 2. {% %} --> 跟邏輯相關的操做 2. 變量相關 1. 傳字典或對象類型的數據 obj.name/obj.age 2. 傳數組類型的數據 obj.索引值 3. 日期格式化 <p>{{ today|date:"Y-m-d H:i:s"}}</p> 4. 顯示真正的html代碼 <p>{{ link|safe }}</p> 2. 母板 1. 爲何要用母版? 不一樣的頁面有大量重複的代碼,咱們能夠把公用的部分提取出來放在單獨一個文件 2. 怎麼使用? 1. 在子頁面 經過使用 {% extends ‘模板名’ %} --> 放在子頁面的最上面 2. {% block xx %}{% endblock %} 3. 組件 把單獨的一段html代碼放在一個文件 使用 {% include '組件名' %}導入 6. CSRF 1. 爲何要有csrf_token? 2. Django中如何使用? 在render的頁面上寫上{% csrf_token %} 3. 若是是form表單形式提交,必須放在form表單中 7. ORM單表查詢13條+外鍵操做(一對多): 1. ORM上週知識點: 1. 查詢 1. 查全部 models.Publisher.objects.all() 2. 查某個具體的記錄 models.Publisher.objects.get(id=1) --> 注意查詢條件不成立就報錯 2. 刪除一條記錄 models.Publisher.objects.get(id=1).delete() 3. 建立一條記錄 models.Publisher.objects.create(name="新出版社名字", addr="出版社地址") 4. 修改一條記錄 obj = models.Publisher.objects.get(id=1) obj.name = "新名字" obj.save() 2. 字段和參數: https://www.cnblogs.com/liwenzhou/p/8688919.html 1. 上週字段和參數: 1. models.AutoField(primary_key=True) 2. models.CharField(max_length=32) 2. 經常使用字段和參數 1. 字段 1. CharField 2. AutoField 3. DateField 4. DateTimeField() 5. IntergeField() 2. 參數 1. null=True 2. default=默認值 3. unique=True 4. 時間字段 1. auto_now_add=True 第一次建立時 2. auto_add=True 每次更新時 3. ORM必知必會單表查詢13條 1. all() --> 查詢全部結果 2. filter() --> 根據查詢條件查詢數據庫的 3. get() --> 獲取一個惟一的值 4. exclude() --> 將符合條件的都剔除掉,留下不符合條件的 5. values('字段名', ...) --> 返回一個QuerySet,裏面是字典 6. values_list(字段名', ...) --> 返回一個QuerySet,裏面是元祖 7. order_by() --> 對查詢結果排序 8. reverse() --> 對一個有序的查詢結果集作反轉 9. distinct() --> 去重,跨表查詢時去掉重複的記錄,MySQL不支持按字段去重 10. count() --> 返回數據條數 11. first() --> 取第一個數據 12. last() --> 取最後一條數據 13. exists() --> 判斷表裏有沒有數據 分類: 1. 返回QuerySet列表的有哪一些? 1. all() 2. filter() 3. exclude() 4. order_by() 5. reverse() 6. distinct() 7. values('字段名', ...) --> 查詢結果的列表裏,都是字典 8. values_list(字段名', ...) --> 查詢結果的列表裏,都是元祖 2. 返回具體對象的 1. first() 2. last() 3. get() 3. 返回數字的 1. count() 4. 返回布爾值 1. exists() 4. 單表查詢神奇的雙下劃線 查詢操做:https://www.cnblogs.com/liwenzhou/p/8660826.html 1. 外鍵 ForeignKey 經過Foreignkey字段 ,可以獲得和我關聯的那個對象 數據庫中保存的字段名是 外鍵字段_id 2. 外鍵增刪改查 3. 跨表查詢 1. 基於對象的查詢 1. 正向查 2. 反向查 2. 基於QuerySet的查詢 1. 正向查 2. 反向查 8. cookie&session:https://www.cnblogs.com/liwenzhou/p/8343243.html 1. Cookie 1. 是什麼? 保存在瀏覽器端的鍵值對! 服務端在返回響應的時候,告訴瀏覽器保存的鍵值對!瀏覽器能夠拒絕保存Cookie. 2. 爲何要有cookie? HTTP請求是無狀態的,咱們須要保存狀態 --> cookie 3. Django中cookie的使用 1. 設置cookie rep = HttpResponse("ok") rep.set_cookie("key", "value", max_age=xx秒) rep.set_signed_cookie("key", "value", salt="ooxx", max_age=xx秒) 2. 獲取cookie request.COOKIES.get("key") request.get_signed_cookie("key", default="", salt="ooxx") 3. cookie有失效時間 1. Django中不設置,關閉瀏覽器就失效了 2. 經過max_age設置超時時間 4. 補充3點: 1. 如何登錄後再跳轉回以前訪問的頁面 --> next參數實現 2. 如何將FBV的裝飾器應用到CBV上 --> from django.utils.decorators import method_decorator 3. 裝飾器修復技術 --> from functools import wraps 2. session 1. 保存在服務端的鍵值對! 下週講! 2. 練習題: 1. django請求生命週期 2. values和values_list的區別? 3. session和cookie是什麼?以及區別? 4. django路由系統中name的做用? 5. filter和exclude的區別? 6. ORM查詢示例: 表結構: 出版社表: ID 名稱 圖書表: ID 書名稱 價格 出版社ID 題目: 1. 查詢老男孩出版社出版過的價格大於200的書籍 2. 查詢全部以py開頭的書籍名稱 3. 查詢價格爲50,100或者150的全部書籍名稱及其出版社名稱 4. 查詢價格在100到200之間的全部書籍名稱及其價格 5. 查詢全部人民出版社出版的書籍的價格(從高到低排序,去重) 6. 查詢價格大於200的書籍的個數 7. 查詢價格不等於100的全部書籍 3. 做業:主機管理【02】:主機管理 1. 基於django建立表: 用戶表:ID、用戶名、密碼 業務線表:ID、名稱 主機表:ID、主機名、密碼、業務線ID 2. 主機管理:增刪改查(一對多,不須要作業務線管理,只要在數據庫錄入業務線數據便可) 3. 使用母板和動態路由 4. 套用BootStrap樣式 採分點: 練習題:20 實現全部功能:70 代碼寫的清晰、健壯、可擴展:10
sqlite3文件數據庫,點開便可使用
sqlite3數據庫添加時間類型 可能有問題。
urls---views(寫函數)----html
1、路由系統
1.Django的路由系統;用戶請求與url'內容中是否匹配
2.正則表達式
動態匹配路由的方式傳參數
分組匹配------------^edit_publisher/(\d+)/$
url(r'^admin/', admin.site.urls), url(r'^publisher_list/$', views.publisher_list, name="alex"), url(r'^edit_publisher/(?P<edit_id>\d+)/$', views.EditPublisher.as_view(), name="alex"),
def edit_publisher(request): if request.method == "POST": # 接收用戶提交過來的數據 edit_id = request.POST.get("id") new_name = request.POST.get("name888") # 去數據庫修改出版社名字 obj = models.Publisher.objects.get(id=edit_id) obj.name = new_name obj.save() return redirect("/publisher_list/") # 取url攜帶的參數 print(request.GET.get("id")) edit_id = request.GET.get("id") # 去數據庫找編輯的出版社 publisher_obj = models.Publisher.objects.get(id=edit_id) return render(request, "edit_publisher.html", {"obj": publisher_obj})
def edit_publisher(request, edit_id): print(reverse('alex')) print("=" * 120) if request.method == "POST": new_name = request.POST.get("name888") # 去數據庫修改出版社名字 obj = models.Publisher.objects.get(id=edit_id) obj.name = new_name obj.save() return redirect(reverse('alex')) print(edit_id) publisher_obj = models.Publisher.objects.get(id=edit_id) return render(request, "edit_publisher.html", {"obj": publisher_obj})
分組命名匹配---^edit_publisher/(?P<edit_id>\d+)/$
分組匹配:
至關於給視圖函數傳遞 位置參數
分組命名匹配:
至關於給視圖函數傳遞 關鍵字參數css
?P<pk>給分組取一個名字 將捕獲的值當成關鍵字參數傳入
修改list html中a標籤編輯、刪除取值路徑
reverse
# CBV class EditPublisher(views.View): def get(self, request, edit_id): publisher_obj = models.Publisher.objects.get(id=edit_id) return render(request, "edit_publisher.html", {"obj": publisher_obj}) def post(self, request, edit_id): new_name = request.POST.get("name888") # 去數據庫修改出版社名字 obj = models.Publisher.objects.get(id=edit_id) obj.name = new_name obj.save() return redirect(reverse('alex'))
2、視圖函數
1.import views 是dj中自帶的函數
cbv views.類名.as_view()
2,dj上傳文件 ,
1. 前端頁面
1. form表單必定要有action,method必須是post
2. 必定要配置enctype="multipart/form-datahtml
2.後端:chunks()不寫也可實現功能,此功能是django提供的方法,通常寫上。前端
# Django上傳文件示例 class Upload(views.View): def get(self, request): return render(request, "upload.html") def post(self, request): # 拿到用戶發送的文件數據 file_obj = request.FILES.get("code") # 保存下來 # 1. 拿到用戶上傳的文件名 filename = file_obj.name # 2. 在服務端建立一個同名的文件 with open(filename, "wb") as f: # 3. 從用戶上傳的文件對象中一點一點讀數據,往我本地建立的文件句柄裏一點一點寫 for i in file_obj.chunks(): f.write(i) return HttpResponse("上傳成功!")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>上傳文件</title> </head> <body> <form action="/upload/" method="post" enctype="multipart/form-data"> <input type="file" name="code"> <input type="submit" value="提交"> </form> </body> </html>
json格式的數據---相似於{‘code’:0,'data':'alex'}
from django.http import JsonResponse
# 返回JSON格式數據 class JsonTest(views.View): def get(self, request): res = {"code": 0, "data": "alex"} res2 = ["alex", "污Sir", "金老闆", "小姨媽", "MJJ"] # 1. 先將字典序列化成json格式的字符串 # import json # s = json.dumps(res2, ensure_ascii=False) #ensure_ascii=False確保輸出漢字 # return HttpResponse(s) return JsonResponse(res2, safe=False) # 列表類型要寫safe=False
xss攻擊(跨站腳本攻擊) : js代碼--死循環
3、模板引擎
1. {{ }} --> 跟變量相關的操做
2. {% %} --> 跟邏輯相關的操做mysql
{% for teacher in data %} {% if forloop.last %} {{ teacher }} {% else %} {{ teacher }}, {% endif %} {% endfor %}
4. 顯示真正的html代碼
<p>{{ link|safe }}</p>jquery
import datetime now = datetime.datetime.now() print(now, type(now)) ret = now.strftime("%Y-%m-%d %H:%M:%S") # 日期類型轉換爲字符串類型 print(ret, type(ret))
模板語言不支持連續判斷
不支持:{#<p>{% if 3 > 2 > 1 %}{% endif %}</p>#}
須要這樣寫:{#<p>{% if 3 > 2 and 2 > 1 %}{% endif %}</p>#}
默認找屬性,屬性優先級大於方法
# 測試模板語法 def template_test(request): data = ["金老闆", "景女神", "MJJ"] # data = "" filesize = 1234567890 import datetime today = datetime.datetime.today() link = "<script>for(;;){alert(123)}</script>" class Person(object): def __init__(self, name, dream): self.name = name self.dream = dream def dream(self): return "個人夢想是學好Python!" pw = Person("彭瑋", "不去下一期!") return render(request, "t.html", { "data": data, "file_size": filesize, "today": today, "link": link, "person": pw })
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {#<p>{{ data.1 }}</p>#} <p>{{ data|default:"暫無數據" }}</p> {##管道符先後及冒號先後不要加空格#} <p>{{ file_size|filesizeformat }}</p> <p>{{ today }}</p> {#年月日時分秒#} <p>{{ today|date:"Y-m-d H:i:s"}}</p> <p>{{ link }}</p> {#加safe容許顯示html及頻繁彈出框#} {#<p>{{ link|safe }}</p>#} <hr> <p> {% for teacher in data %} {# 最後一次循環,不加,#} {% if forloop.last %} {{ teacher }} {% else %} {{ teacher }}, {% endif %} {% endfor %} </p> {#<p>{% if 3 > 2 > 1 %}{% endif %}</p>#} {##} {#<p>{% if 3 > 2 and 2 > 1 %}{% endif %}</p>#} <hr> {{ person.name }} {{ person.dream }} </body> </html>
4、母版
bt--css jquery--js
怎麼使用?
1. 在子頁面 經過使用 {% extends ‘模板名’ %} --> 放在子頁面的最上面
2. {% block xx %}{% endblock %}git
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{{ html_title }}</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7/css/bootstrap.min.css"> {% block page-css %} {% endblock %} </head> <body> {% include 'nav.html' %} <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> {% block page-main %} {% endblock %} </div> </div> </div> <script src="/static/jquery.js"></script> {% block page-js %} {% endblock %} </body> </html>
{% extends 'mama.html' %} {% block page-main %} <table class="table table-bordered"> <thead> <tr> <th>#</th> <th>id</th> <th>出版社名稱</th> <th>操做</th> </tr> </thead> <tbody> {% for publisher in publisher_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ publisher.id }}</td> <td>{{ publisher.name }}</td> <td> <a href="/edit_publisher/{{ publisher.id }}/" class="btn btn-info">編輯</a> <a href="/delete_publisher/" class="btn btn-danger">刪除</a> </td> </tr> {% endfor %} </tbody> </table> {% endblock %} {#我這個頁面纔用到的一個js文件#} {% block page-js %} <script src="/static/1.js"></script> {% endblock %}
3. 組件
把單獨的一段html代碼放在一個文件
使用 {% include '組件名' %}導入web
五.跨站請求僞造 CSRF
網站沒法限制誰給他發請求,例如:本身寫的頁面也可跳轉到sougouweb。
釣魚網站 往銀行發請求,獲取你的用戶名、密碼等信息。
value="隨機的字符串"
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="銀行轉帳的api" method="post"> <input type="text" name="key" value="adadaaljqoiqwkqkwqqqrdadq" style="display: none"> <input type="text" name="query"> <input type="submit" value="提交"> </form> <hr> </body> </html>
def csrf_test(request): if request.method == "POST": print(request.POST) return HttpResponse("OK") return render(request, "csrf_test.html")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {# 生成隨機字符串的input框,必須在form表單裏 #} {% csrf_token %} <input type="text" name="name"> <input type="submit" value="提交"> </form> </body> </html>
6、ORM單表查詢13條+外鍵操做(一對多)
1.字段和參數
1. 字段 1. CharField 2. AutoField 3. DateField 4. DateTimeField() 5. IntergeField() 2. 參數 1. null=True 2. default=默認值 3. unique=True 4. 時間字段 1. auto_now_add=True 第一次建立時 2. auto_add=True 每次更新時
AutoField(Field) - int自增列,必須填入參數 primary_key=True BigAutoField(AutoField) - bigint自增列,必須填入參數 primary_key=True 注:當model中若是沒有自增列,則自動會建立一個列名爲id的列 from django.db import models class UserInfo(models.Model): # 自動建立一個列名爲id的且爲自增的整數列 username = models.CharField(max_length=32) class Group(models.Model): # 自定義自增列 nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) SmallIntegerField(IntegerField): - 小整數 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整數 0 ~ 32767 IntegerField(Field) - 整數列(有符號的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整數 0 ~ 2147483647 BigIntegerField(IntegerField): - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field) - 布爾值類型 NullBooleanField(Field): - 能夠爲空的布爾值 CharField(Field) - 字符類型 - 必須提供max_length參數, max_length表示字符長度 TextField(Field) - 文本類型 EmailField(CharField): - 字符串類型,Django Admin以及ModelForm中提供驗證機制 IPAddressField(Field) - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制 GenericIPAddressField(Field) - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 - 參數: protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both" URLField(CharField) - 字符串類型,Django Admin以及ModelForm中提供驗證 URL SlugField(CharField) - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號) CommaSeparatedIntegerField(CharField) - 字符串類型,格式必須爲逗號分割的數字 UUIDField(Field) - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能 - 參數: path, 文件夾路徑 match=None, 正則匹配 recursive=False, 遞歸下面的文件夾 allow_files=True, 容許文件 allow_folders=False, 容許文件夾 FileField(Field) - 字符串,路徑保存在數據庫,文件上傳到指定目錄 - 參數: upload_to = "" 上傳文件的保存路徑 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路徑保存在數據庫,文件上傳到指定目錄 - 參數: upload_to = "" 上傳文件的保存路徑 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage width_field=None, 上傳圖片的高度保存的數據庫字段名(字符串) height_field=None 上傳圖片的寬度保存的數據庫字段名(字符串) DateTimeField(DateField) - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 時間格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型 FloatField(Field) - 浮點型 DecimalField(Field) - 10進制小數 - 參數: max_digits,小數總長度 decimal_places,小數位長度 BinaryField(Field) - 二進制類型 字段合集
如下內容參考博客地址:https://www.cnblogs.com/liwenzhou/p/8660826.html
2.ORM必知必會單表查詢13條
1. all() --> 查詢全部結果 2. filter() --> 根據查詢條件查詢數據庫的 3. get() --> 獲取一個惟一的值 4. exclude() --> 將符合條件的都剔除掉,留下不符合條件的 5. values('字段名', ...) --> 返回一個QuerySet,裏面是字典 6. values_list(字段名', ...) --> 返回一個QuerySet,裏面是元祖 7. order_by() --> 對查詢結果排序 8. reverse() --> 對一個有序的查詢結果集作反轉 9. distinct() --> 去重,跨表查詢時去掉重複的記錄,MySQL不支持按字段去重 10. count() --> 返回數據條數 11. first() --> 取第一個數據 12. last() --> 取最後一條數據 13. exists() --> 判斷表裏有沒有數據
# 如何在一個py文件中 使用Django項目的相關配置或內容 import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") # manage.py中第6行 import django django.setup() from app01 import models # 查詢age=18的第一我的 # ret = models.Person.objects.get(age=18) # pk(主鍵) unique # print(ret) # 查詢age=18的全部人 # ret = models.Person.objects.filter(age=18) #獲取的是對象的列表,多個值 # print(ret[0]) # ret[0]取一個值 # ret = models.Person.objects.filter(age=18).values("age", "phone") # print(ret) # 打印指定的兩個字段,字典內容 # ret = models.Person.objects.filter(age=18).values_list("age", "phone") # print(ret) # 打印指定的兩個字段,小元組內容,只有值,無key了 # 排序 # ret = models.Person.objects.all().order_by("age") # print(ret) # 神奇的雙下劃線 # 查詢年齡大於18歲的 # ret = models.Person.objects.filter(age__gt=18, id__gt=1) # print(ret) # 查詢id值在 [1, 2]的人 # ret = models.Person.objects.filter(id__in=[1, 2, 20000]) # print(ret) # 取1,2的人,不會報錯 # # 查詢id值不在[1,2]的人 # ret = models.Person.objects.exclude(id__in=[1,2]) # print(ret) # 查詢名字中包含 JJ 的那我的 # ret = models.Person.objects.filter(name__contains="JJ") # print(ret) # 不區分大小寫查詢 # ret = models.Person.objects.filter(name__icontains="jj") # print(ret) # 查詢id在1-3區間內的數據 # ret = models.Person.objects.filter(id__range=[1, 3]) # print(ret) # 查詢以JJ結尾的人 # ret = models.Person.objects.filter(name__endswith='JJ') # print(ret) # print(models.Person.objects.first().birthday) #sqlite3中顯示None,日期的格式有問題,mysql能夠顯示 # 查詢 生日 是 2018年的全部人 # ret = models.Person.objects.filter(birthday__year=2018) # print(ret) #外鍵 # 查詢第一本書關聯的出版社的名字 # 1. 基於對象的查詢 # book_obj = models.Book.objects.first() # ret = book_obj.publisher.name # print(ret) # 2. 基於queryset的雙下劃線查詢,雙下劃線表示跨表 # ret = models.Book.objects.all().values_list("publisher__name").distinct() # print(ret) # 反向查詢 # 1. 由出版社反向查詢書籍(基於對象的查詢) # publisher_obj = models.Publisher.objects.get(id=2) # 找到張江出版社 # 張江出版社出版的全部書籍 # ret = publisher_obj.book_set.all() # print(ret) # 2. 基於queryset的雙下劃線 # 江出版社出版的全部書籍的書名 ret = models.Publisher.objects.filter(id=2).values_list("book__title") print(ret)
注:
查詢:
1.根據惟一值查詢:用get
2.通常會用filter
1256789 11 12 經常使用
id__gt=1 #id大於1的數據
分類: 1. 返回QuerySet列表的有哪一些? 1. all() 2. filter() 3. exclude() 4. order_by() 5. reverse() 6. distinct() 7. values('字段名', ...) --> 查詢結果的列表裏,都是字典 8. values_list(字段名', ...) --> 查詢結果的列表裏,都是元祖 2. 返回具體對象的 1. first() 2. last() 3. get() 3. 返回數字的 1. count() 4. 返回布爾值 1. exists()
不一樣的對象有不一樣的方法,能夠根據對象調用方法。返回QuerySet的使用加[0]
3. 單表查詢神奇的雙下劃線
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 獲取id大於1 且 小於10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 獲取id等於十一、22、33的數據 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") # 獲取name字段包含"ven"的 models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感 models.Tb1.objects.filter(id__range=[1, 3]) # id範圍是1到3的,等價於SQL的bettwen and 相似的還有:startswith,istartswith, endswith, iendswith date字段還能夠: models.Class.objects.filter(first_day__year=2017)
4.外鍵操做--重點!正則表達式
經過Foreignkey字段 ,可以獲得和我關聯的那個對象,例如: book.publisher.name
一對多--外鍵操做
外鍵關聯--查、增刪、改
關聯字段__被查名稱 能夠跨表查詢
基於例子練習跨表查詢(正向、反向),例子見上 orm_test.py或以下
#外鍵 # 查詢第一本書關聯的出版社的名字 # 1. 基於對象的查詢 # book_obj = models.Book.objects.first() # ret = book_obj.publisher.name # print(ret) # 2. 基於queryset的雙下劃線查詢,雙下劃線表示跨表 # ret = models.Book.objects.all().values_list("publisher__name").distinct() #全部書籍出版社的名字 # ret = models.Book.objects.filter(id=1).values_list("publisher__name")#id爲1的書籍出版社的名字 # print(ret) # 反向查詢 # 1. 由出版社反向查詢書籍(基於對象的查詢) # publisher_obj = models.Publisher.objects.get(id=2) # 找到張江出版社 # 張江出版社出版的全部書籍 # ret = publisher_obj.book_set.all() # print(ret) # 2. 基於queryset的雙下劃線 # 江出版社出版的全部書籍的書名 ret = models.Publisher.objects.filter(id=2).values_list("book__title") print(ret)
from django.db import models # Create your models here. class Publisher(models.Model): name = models.CharField(max_length=12) # 書籍表 class Book(models.Model): title = models.CharField(max_length=32) publisher = models.ForeignKey(to="Publisher", on_delete=models.CASCADE) #on_delete級聯刪除 class Person(models.Model): name = models.CharField(max_length=12, default="alex") age = models.IntegerField(default=18) birthday = models.DateField() birthday2 = models.DateTimeField(null=True) phone = models.CharField(max_length=11, unique=True) # 建立該記錄時自動把當前時間保存到該字段 join_date = models.DateField(auto_now_add=True) # 更新該記錄的值時 自動把當前時間保存到該字段 last_date = models.DateField(auto_now=True) def __str__(self): return "{}-{}".format(self.age, self.phone)
from django.conf.urls import url from django.contrib import admin from app01 import views # from django.urls import path urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/$', views.publisher_list, name="alex"), url(r'^edit_publisher/(?P<edit_id>\d+)/$', views.EditPublisher.as_view(), name="alex"), # 測試上傳你文件 url(r'^upload/$', views.Upload.as_view()), # 測試返回Json格式數據 url(r'^json_test/$', views.JsonTest.as_view()), # 測試模板語法 url(r'^template_test/$', views.template_test), # 測試跨站請求僞造 (CSRF) url(r'^csrf_test/$', views.csrf_test), url(r'^book_list/$', views.book_list), url(r'^add_book/$', views.AddBook.as_view()), url(r'^delete_book/(?P<pk>\d+)/$', views.DeleteBook.as_view()), url(r'^edit_book/(?P<pk>\d+)/$', views.EditBook.as_view()), url(r'^login/$', views.login), ]
@login_check def book_list(request): # 去數據庫查詢全部的書籍 data = models.Book.objects.all() return render(request, "book_list.html", {"book_list": data}) class AddBook(views.View): @method_decorator(login_check) def get(self, request): data = models.Publisher.objects.all() return render(request, "add_book.html", {"publisher_list": data}) def post(self, request): book_name = request.POST.get("title") publisher_id = request.POST.get("publisher") # publisher_obj = models.Publisher.objects.get(id=publisher_id) # 建立書籍 models.Book.objects.create( title=book_name, publisher_id=publisher_id # publisher=publisher_obj #麻煩,不推薦 ) return redirect("/book_list/") class DeleteBook(views.View): def get(self, request, pk): models.Book.objects.filter(id=pk).delete() return redirect("/book_list/") class EditBook(views.View): def get(self, request, pk): book_obj = models.Book.objects.get(id=pk) publisher_list = models.Publisher.objects.all() return render(request, "edit_book.html", {"book": book_obj, "publisher_list": publisher_list}) def post(self, request, pk): book_obj = models.Book.objects.get(id=pk) new_title = request.POST.get("title") new_publisher_id = request.POST.get("publisher") # 更新 book_obj.title = new_title book_obj.publisher_id = new_publisher_id # 同步到數據庫 book_obj.save() return redirect("/book_list/")
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>編輯書籍</title> </head> <body> <form action="" method="post"> {% csrf_token %} <input type="text" name="title" value="{{ book.title }}"> <select name="publisher"> {% for publisher in publisher_list %} {% if book.publisher == publisher %} <option selected value="{{ publisher.id }}">{{ publisher.name }}</option> {% else %} <option value="{{ publisher.id }}">{{ publisher.name }}</option> {% endif %} {% endfor %} </select> <input type="submit" value="提交"> </form> </body> </html>
# 登陸 def login(request): if request.method == "POST": next = request.GET.get("next") username = request.POST.get("username") pwd = request.POST.get("pwd") if username == "alex" and pwd == "alexdsb": if next: rep = redirect(next) else: rep = redirect("/publisher_list/") # 在返回響應的時候 告訴瀏覽器保存我指定的鍵值對(cookie) # rep.set_cookie("s21", "hao", max_age=7) # 7秒鐘有效的Cookie rep.set_signed_cookie("s21", "hao", salt="ooxx", max_age=7) # 設置加鹽的cookie return rep else: return HttpResponse("滾~") return render(request, "login.html") # 裝飾器版本登陸認證 def login_check(func): @wraps(func) def inner(request, *args, **kwargs): next = request.path_info # 登陸驗證 # v = request.COOKIES.get("s21") # 取正常的cookie v = request.get_signed_cookie("s21", default="", salt="ooxx") # 獲取加鹽的cookie if v == "hao": return func(request, *args, **kwargs) else: return redirect("/login/?next={}".format(next)) return inner
7、cookie和session
瀏覽器能夠拒絕保存Cookie.在瀏覽器的settings中搜索cookie,禁用便可!
補充3點:
1. 如何登錄後再跳轉回以前訪問的頁面 --> next參數實現
2. 如何將FBV的裝飾器應用到CBV上 --> from django.utils.decorators import method_decorator
3. 裝飾器修復技術 --> from functools import wraps
form表單中的action不要寫死 ,應是<form action="" method="post">
函數的裝飾器可否 直接給類使用??--不能夠
須要用method_decorator 裝飾一下
# 登陸 def login(request): if request.method == "POST": next = request.GET.get("next") username = request.POST.get("username") pwd = request.POST.get("pwd") if username == "alex" and pwd == "alexdsb": if next: rep = redirect(next) else: rep = redirect("/publisher_list/") # 在返回響應的時候 告訴瀏覽器保存我指定的鍵值對(cookie) # rep.set_cookie("s21", "hao", max_age=7) # 7秒鐘有效的Cookie rep.set_signed_cookie("s21", "hao", salt="ooxx", max_age=7) # 設置加鹽的cookie return rep else: return HttpResponse("滾~") return render(request, "login.html") #使用 def publisher_list(request): # 從請求中找有沒有我以前登陸時候保存的特殊的鍵值對 print(request.COOKIES) v = request.COOKIES.get("s21") # 若是你請求攜帶的值 和我以前讓你保存的是同一個,就表示你是已經登錄過的用戶,默認放行 if v == "hao": print(request.path_info) data = models.Publisher.objects.all() return render(request, "publisher_list.html", {"publisher_list": data}) else: return redirect("/login/")
# 裝飾器版本登陸認證 def login_check(func): @wraps(func) #裝飾器修復技術 def inner(request, *args, **kwargs): next = request.path_info # 獲取當前路徑 # 登陸驗證 # v = request.COOKIES.get("s21") # 取正常的cookie v = request.get_signed_cookie("s21", default="", salt="ooxx") # 獲取加鹽的cookie if v == "hao": return func(request, *args, **kwargs) # 你要執行的視圖函數 else: return redirect("/login/?next={}".format(next)) return inner # 登陸 def login(request): if request.method == "POST": next = request.GET.get("next") username = request.POST.get("username") pwd = request.POST.get("pwd") if username == "alex" and pwd == "alexdsb": if next: rep = redirect(next) else: rep = redirect("/publisher_list/") # 在返回響應的時候 告訴瀏覽器保存我指定的鍵值對(cookie) # rep.set_cookie("s21", "hao", max_age=7) # 7秒鐘有效的Cookie rep.set_signed_cookie("s21", "hao", salt="ooxx", max_age=7) # 設置加鹽的cookie return rep else: return HttpResponse("滾~") return render(request, "login.html")
@login_check def book_list(request): # 去數據庫查詢全部的書籍 data = models.Book.objects.all() return render(request, "book_list.html", {"book_list": data}) from django.utils.decorators import method_decorator class AddBook(views.View): @method_decorator(login_check) def get(self, request): data = models.Publisher.objects.all() return render(request, "add_book.html", {"publisher_list": data}) def post(self, request): book_name = request.POST.get("title") publisher_id = request.POST.get("publisher") # publisher_obj = models.Publisher.objects.get(id=publisher_id) # 建立書籍 models.Book.objects.create( title=book_name, publisher_id=publisher_id # publisher=publisher_obj #麻煩,不推薦 ) return redirect("/book_list/")
裝飾器修復技術---@warppers
--動態添加功能+顯示被裝飾函數信息
from functools import wraps def wrapper(func): @wraps(func) # 藉助內置的工具修復被裝飾的函數 def inner(*args, **kwargs): print("呵呵") func(*args, **kwargs) return inner @wrapper def foo(arg): """ 這是一個測試裝飾器的函數 :param arg: int 必須是int類型 :return: None """ print("嘿嘿嘿" * arg) foo(10) print(foo.__doc__)