django
- 2020 年 11 月 25 日
- 筆記
1 ajax基本語法
test.html
view.py
def ab_ajax(request):
if request.method == 'POST':
i1 = request.POST.get('i1')
i2 = request.POST.get('i2')
res = int(i1) + int(i2)
return HttpResponse(res)
return render(request, 'test.html')
2 前後端傳輸數據的編碼格式
# 1 我們主要研究post請求數據的編碼格式
"""
get請求數據就是直接放在url後面的,如:
url?username=xpj&password=123
"""
# 2 前後端傳輸數據的三種格式
"""
1 urlencoded: form表單提交數據格式
2 multipart/formdata: 針對文件格式,封裝到request.FILES里
3 json
"""
# 3 可以朝後端發送post請求的方式
"""
1 form表單
默認的數據編碼格式是urlencoded
數據格式:username=xpj&password=123
django後端針對urlencoded編碼格式的數據會自動幫你封裝到request.POST中
如果你把編碼格式改為formdata,那麼針對普通的鍵值對還是解析到request.POST中,而針對文件會解析到request.FILFES中
form表單是沒有辦法傳輸json個是數據的
2 ajax請求
默認的數據編碼格式是urlencoded
數據格式:username=xpj&password=123
django後端針對urlencoded編碼格式的數據會自動幫你封裝到request.POST中
"""
3 ajax發送json格式數據
'''
前後端傳輸數據的時候一定要確保編碼格式跟數據格式是一致的
如果傳輸的是json格式的數據request.post里是找不到的
request.is_ajax(),判斷當前請求是否是ajax請求,返回bool值
django針對json格式的數據不會做任何處理,需要自己處理
解決方法:
1.json_bytes = request.body
json_str = json_bytes.decode('utf-8')
json_dict = json.loads(json_str)
2.json_dict = json.loads(json_bytes)
'''
#1 ajax改變發送的編碼格式
$.ajax({
'''''
cententType: 'application/json', //指定編碼格式
''''''
})
4 ajax發送文件
'''
ajax發送文件需要藉助js內置對象FormData
'''
<script>
$('#d4').on('click', function (){
// 1 需要先利用FormData內置對象生成一個對象
let formdata_obj = new FormData()
// 2 添加普通的鍵值對
formdata_obj.append('username', $('#d1').val());
formdata_obj.append('password', $('#d2').val());
// 3 添加文件對象,$('#d3')是jquery對象, $('#d3')[0]轉成原生js對象標籤對象, $('#d3')[0].files[0]拿到用戶傳進來的文件對象
formdata_obj.append('myfile', $('#d3')[0].files[0])
// 4 將對象基於ajax發送給後端
$.ajax({
url: '',
type: 'post',
data: formdata_obj, //直接將對象放在data後面即可
//ajax發送文件必須要指定的兩個參數
contentType: false, // 不需要使用任何編碼,django後端能夠自動識別formdata對象
processData: false, // 告訴你的遊覽器不要對你的數據進行任何處理
success: function (args){
alert(1)
}
})
})
</script>
5 ajax結合sweetalert實現二次確認
<p>
<button class="del" delete_id="{{ user_obj.pk }}"></button>
</p>
<script>
$('.del').on('click', function (){
alert($(this).attr('delete_id')) //this拿到的是當前標籤.attr拿到標籤的屬性
})
</script>
# bulk_create()
book_list = []
for i in range(100000):
book_obj = models.Book.objects.all()
book_list.append(book_list)
models.Book.objects.bulk_create(book_list)
return render(request, 'ab_pl.html', locals())
# 1 對比用戶名和密碼是否正確
user_obj = auth.authenticate(request, username=username, password=password) # 括弧內必須同時傳入request, 用戶名和密碼
print(user_obj) # 用戶對象 jason
print(user_obj.username) # jason
print(user_obj.password) # 密文
# 2 保存用戶狀態
auth.login(request, user_obj) # 執行了該方法,你可以在任何地方通過request.user獲取當前登錄的對象
# 3 判斷當前用戶是否登錄
request.user.is_authenticated()
# 4 獲取當前登錄用戶
request.user
# 5 校驗用戶是否登錄裝飾器
from django.contrib.auth.decorators import login_required
# 局部配置,用戶沒有登錄會跳轉到login頁面
2 auth模組表拓展
class UserInfo(AbstractUser):
"""
如果繼承了AbstractUser
那麼在執行資料庫遷移命令的時候auth_user表就不會再創建出來了
UserInfo表中會出現auth_user所有的欄位外加自己拓展的欄位
"""
phone = models.BigIntegerFeild()
"""
前提:
1. 必須在auth_user沒有被創建之前繼承
2. 必須在settings.py里聲明
AUTH_USER_MODEL = 'app01.UserInfo'
3. 繼承的類不能出現同名欄位
"""
1 單表操作
測試腳本
models.py
class User(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
register_time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
test.py
# 去manage.py文件中複製前四行程式碼,粘貼進test.py文件中並寫入兩行程式碼,即可在單個py文件中進行測試
import os
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject3.settings')
# 這兩行是新加入的
import django
django.setup()
2 必知必會13條
# 1 create()
models.User.objects.create(name='kerwin', age=24)
# 2 delete()
models.User.objects.filter(pk=2).delete()
(1, {'app01.User': 1}) # 返回剩餘個數
# 3 update()
models.User.objects.filter(pk=1).update(age=18)
1 # 修改成功返回1
# 4 filter()
models.User.objects.filter(pk=1)
<QuerySet [<User: xpj>]> # 拿到的是queryset,不存在返回空
# 5 fisrt()
models.User.objects.filter(pk=1).first()
<User: xpj> # 拿到對象
# 6 get()
models.User.objects.get(pk=1)
<User: xpj> # 拿到的是User對象,但是如果不存在的話會報錯
# 7 values()
models.User.objects.values('name') # 欄位查詢
<QuerySet [{'name': 'xpj'}]> # 列表套字典的queryset
# 8 values_list()
models.User.objects.values_list('name', 'age')
<QuerySet [('xpj', 24)]> # 列表套元組的queryset
# 9 distinct()
models.User.objects.values('name', 'age').distinct()
# 10 order_by()
models.User.objects.order_by('age')
models.User.objects.order_by('-age') # 降序
# 11 count()
models.User.objects.filter(pk=1).count()
# 12 reverser() # 反轉
# 13 exists() # 存在
# 14 exclude() #
3 雙下劃線查詢
#1 年齡大於35歲
models.User.objects.filter(age__gt=35)
#2 年齡小於35歲
models.User.objects.filter(age__lt=35)
#3 年齡大於等於,小於等於35歲
models.User.objects.filter(age__gte=35)
models.User.objects.filter(age__lte=35)
#4 年齡是18,32,40
models.User.objects.filter(age__in=[18,32,40])
#5 年齡是18到40歲之間的
models.User.objects.filter(age__range=[18,40])
2 多表操作
1 多表準備
models.py
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
publish_date = models.DateTimeField(auto_now_add=True)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
email = models.EmailField()
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=64)
2 一對多
# 1 增
# 直接寫id
models.Book.objects.create(title='三國演義', price=123.45, publish_id=1)
# 虛擬欄位對象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='紅樓夢', price=66.21, publish_id=publish_obj.pk)
# 2 刪
models.User.objects.filter(pk=2).delete()
# 3 改
models.User.objects.filter(pk=1).update(publish_id=3)
3 多對多
# 多對多關係表的增刪改查其實就是第三張關係表的增刪改查
# 1 通過book表給author表添加作者,通過第三張表
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors # 相當於進入authorsDetail表
book_obj.authors.add(1)
book_obj.authors.add(2,3)
author_obj = models.Author.objects.filter(pk=2).first()
book_obj.author.add(author_obj.pk)
# 2 刪
remove(2)
# 3 改
括弧內必須傳一個可迭代對象
set([1,2])
# 4 清空
clear()
4 正反向概念
# 正向
看外鍵欄位在哪個表,外鍵欄位所在表查外鍵欄位的表就是正向
book--->外鍵欄位在book表--->publish(正向)
# 反向
反之
"""
正向查詢按欄位
反向查詢按表名小寫
"""
5 多表的跨表查詢
子查詢(基於對象的跨表查詢)
# 1 查詢書籍主鍵為1的出版社名稱
book_obj = models.Book.objects.filter(pk=1).first()
publish_obj = book_obj.publish
publish_obj.name
# 2 查詢書籍主鍵為2的作者
book_obj = models.Book.objects.filter(pk=2).first()
author_obj = book_obj.authors.all() # 結果可能有多個加all
# 3 查詢作者為jason的電話號碼
author_obj = models.Author.objects.filter(name='jason').first()
author_detail_obj = authos_obj.author_detail
# 4 查詢出版社是東方出版社出版的書(反向)
publish_obj = models.Publish.objects.filterr(name='東方出版社').first()
book_obj = publish_obj.book_set.all() # 表名小寫_set一般是對對象
# 5 查詢作者是jason寫過的書(反向)
author_obj = models.Author.objects.filter(name='jason').first()
book_obj = author_obj.book_set.all()
# 6 查詢手機號是110的作者姓名
author_detail_obj = models.AuthorDetil.objects.filter(phone=110).first()
author_obj = author_detail_obj.author_set
連表查詢(基於雙下劃線的跨表查詢)
# 1 查詢jason的手機號和作者姓名
# 正向
phone = models.Author.objects.filter(name='jason').values('author_detail__phone','name')
# 反向
models.AuthorDetail.objects.filter(author__name='jason').values('phone', 'author__name')
# 2 查詢書籍主鍵為1的出版社名稱和書的名字
# 正向
models.Book.objects.filter(pk=1).values('title', 'publish__name')
# 反向
models.Publish.objects.filter(book__id=1).values('name', 'book__title')
# 3 查詢書籍主鍵為1的作者姓名
# 正向
models.Book.objects.filter(pk=1).values('authors__name') # 正向查詢按欄位
# 反向
models.author.objects.filter(book__id=1).values('name')
# 4 查詢書籍主鍵1的作者的手機號
models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
3 聚合查詢
aggregate()
# 一般是配合分組一起使用
from app01 import models
from django.db.models import Max, Min, Count, Avg, Sum
models.Book.objects.aggregate(Max('price'), Min('price'), Avg('price'), Count('pk'), Sum('price'))
4 分組查詢
-
annotate()
內寫聚合函數
-
重點: 只要你寫的orm得出的結果是一個queryset對象,那麼你就可以無限的.queryset的方法,比如.values, .filter等等
-
values
在前表示group by的欄位
-
values
在後表示取某幾個欄位
-
filter
在前表示where
-
filter
在後表示having
# 1 統計每一本書的作者個數
models.Book.objects.annotate(author_num=Count('authors')).values('author_num') # models後面.什麼就按什麼分組,author_num是作者個數的別名,一個變數,本來跨表是要authors__id的,但是orm很智慧,可以省略__id
models.Book.objects.annotate(author_num=Count('authors__id')).values('author_num')
# 2 統計每個出版社賣的最便宜的書的價格
models.Publish.objects.annotate(min_book_pirce=Min('book__price')).values('min_book_price')
print(res)
# 3 統計不止一個作者的圖書
models.Book.objects.annotate(author_num=Count('authors__id')).filter(author_num__gt=1)
# <QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]>
models.Book.objects.annotate(author_num=Count('authors__id')).filter(author_num__gt=1).values('title', 'author_num')
# 4 查詢每個作者書的總價格
models.Author.objects.annotate(total_price=Sum('book__price')).values('total_price')
重點: 只要你寫的orm得出的結果是一個queryset對象,那麼你就可以無限的.queryset的方法,比如.values, .filter等等
5 F查詢
# 1 查詢賣出數大於庫存數的書籍
"""
F能夠幫助你直接獲取數據表中某個欄位在表中對應的數據
"""
from django.db.models import F
models.Book.objects.filter(maichu__gt=F('kucun'))
# 2 將所有書的價格提升50塊
models.Book.objects.update(price=F('price')+50)
# 3 將所有書的名稱後面加上爆款2個字
"""
在操作字元串的時候F不能直接做到字元串的拼接
"""
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F('title').value('爆款')))
6 Q查詢
# 1 查詢賣出數大於100或者價格小於600的書籍
models.Book.objects.filter(maichu__gt=100, price__lt=600)
# <QuerySet []> 因為filter內部多個參數是and的關係
7 django中開啟事務
"""
原子性
一致性
隔離性
持久性
回滾 roolback
確認
commit
"""
from django.db import transaction
try:
with transaction.atomic():
# with中寫的所有orm都屬於一個事務
except Exception as e:
print(e)
8 ORM中常用欄位和參數
//www.cnblogs.com/Dominic-Ji/p/9203990.html
9 資料庫查詢優化
# 1 only與defer