django 基礎進階ORM 2
1.多表操作
新增記錄: 針對一對多
book_obj=Book.objects.create(title="python葵花寶典",price=100,publishDate="2012-12-12",publish_id=1)
pub_obj=Publish.objects.get(pk=1)
book_obj=Book.objects.create(title="python葵花寶典",price=100,publishDate="2012-12-12",publish=pub_obj)
1.是新增表的物件 2 是在poblish_id 新增關聯欄位
針對多對多:
book_authors
id book_id author_id
4 2 3
5 1 4
book=Book.objects.get(pk=1)
book.authors.add(1,2,3)
book=Book.objects.get(pk=2)
book.authors.add(3)
book=Book.objects.get(pk=1)
book.authors.remove(2,3)
book=Book.objects.get(pk=1)
book.authors.clear()
book=Book.objects.get(pk=1)
book.authors.set([4,5]) # 列表不打散
再多對多,1是由於多對多關係是自動生成第3張表,需要通過找到pk來新增,其中remove(),set()找到pk
###########中間模型補充
2 補充中介模型
場景:
student
id name
1 A
1 B
course
id name
1 python
2 linux
score
id student_id course_id score
1 1 1 78
2 1 2 67
class Score(models.Model):
student=ForeignKey("Student")
course=ForeignKey("Course")
score=models.IntegerField()
# 中介模型方式:目的,由於是多對多關係,需要add()新增,要是知道新增加的表就好了
若是沒有中間模型的話,需要一步一步找,無法使用跨表查詢,中介模型很好解決了問題
class Student(models.Model):
name = models.CharField( max_length=32)
courses=models.ManyToManyField("Courses",through="Score")#通過指向through = score 來指定關聯的那張多對多新表
class Course(models.Model):
name = models.CharField( max_length=32)
class Score(models.Model):
student=models.ForeignKey("Student")
course=models.ForeignKey("Course")
score=models.IntegerField()
########跨表__查詢
3 跨表查詢
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField( max_length=32)
# 與Publish建立一對多的關係,外來鍵欄位建立在多的一方
publish=models.ForeignKey(to="Publish",to_field="nid",relate_name="xxx",on_delete=models.CASCADE)
# 與Author表建立多對多的關係,ManyToManyField可以建在兩個模型中的任意一個,自動建立第三張表
#################### 基於物件(子查詢)
正向查詢按欄位,反向查詢relate_name,如果沒有設定,按表名小寫_set
book=Book.objects.get(pk=1)
book.publish
book.authors.all()
pub=Publish.objects.get(pk=1)
pub.xxx.all()
author=Author.objects.get(pk=1)
author.book_set.all()
author.authordetail
authordetail.author
#################### 基於雙下劃線(join查詢)
id title pub_id
1 A 1
2 B 1
Publish
id name
1 人民
2 北京
innerjoin
1 A 1 1 人民
2 B 1 1 人民
rightjoin
1 人民 1 A 1
1 人民 2 B 1
2 北京 null null null
book_authors
id book_id author_id
1 1 1
2 2 1
2 3 1
3 3 2
正向查詢安欄位,反向查詢按表名小寫
# 查詢python出版社的名字
Book.objects.filter(title="python").values("publish__name")
Publish.objects.filter(book__title="python").values("name")
# 查詢alex出版過的書籍的名稱
Author.objects.filter(name__startswith="a").values("book__title")
Book.objects.filter(authors__name__startswith="a")
4 分組查詢(基於雙下劃線(join查詢))
聚合
# 計算所有圖書的平均價格
Book.objects.all().aggregate(AVG("price"))
Book.objects.all().aggregate(MAX("price"))
分組:
id name age salary dep
1 alex 12 2000 銷售部
2 egon 22 3000 人事部
3 wen 22 5000 人事部
sql:select dep,AVG(salary) from emp group by dep
orm:Emp.objects.values("dep").annotate(avg=AVG("salary")) # [{"dep":"銷售","avg":5000},{}]
跨表分組查詢
book
id title pub_id
1 python 1
2 linux 1
3 go 2
publish
id name
1 沙河
2 北京
查詢每一個出版社的名稱以及出版書籍的個數
id title pub_id id name
1 python 1 1 沙河
2 linux 1 1 沙河
3 go 2 2 北京
Publish.objects.values(pk).annotate(c=Count("book")) # [{pk:1,c:2},{pk:2,c:1}]
Publish.objects.all.annotate(c=Count("book")).values("c","name") # [publish_obj,publish_obj]
# 查詢每一個作者的名字以及出版書籍的最高價格
Author.objects.annotate(max_price=Max("book__price")).values("name","max_price")
# 查詢96年以後出生的每一個作者的名字以及出版書籍的最高價格
Author.objects.filter(birthday__year__gt=1996).annotate(max_price=Max("book__price")).values("name","max_price")
# 查詢不止一個作者的書籍名稱以及關聯的作者個數
Book.objects.all().annotate(c=Count("authors"))# [book1,book2,.....]
Book.objects.all().annotate(c=Count("authors")).filter(c__gt=1).values("title","c")
# 查詢每一個銷售的名字以及今天對應的成單量
userinfo
id name
1 sanjiang
2 jinjin
3 bingbing
customer
id name deal_date consultant
1 A 2018-11-23 1
1 B 2018-11-22 1
1 C 2018-11-23 2
1 D 2018-11-18 1
1 E 2018-11-23 1
1 F 2018-11-23 1
1 Q 2018-11-23 1
customer
id name deal_date consultant id name
1 A 2018-11-23 1 1 sanjiang
1 C 2018-11-23 2 2 jinjin
1 E 2018-11-23 3 3 bingbing
1 F 2018-11-23 3 3 bingbing
1 Q 2018-11-23 1 1 sanjiang
# Userinfo.objects.filter(depart_id=1).filter(customer__deal_date=now).annotate(c=Count("customers")).values("name","c")
F與Q
Book.objects.filter(commnetNum__lt=F('keepNum'))
Book.objects.filter(commnetNum__lt=F('keepNum')*2)
Book.objects.all().update(price=F("price")+30)
Book.objects.filter(Q(title__startswith="py")|Q(price__gt=100))
q=Q()
q.conector="or"
q.children.append(("title__startswith","py"))
q.children.append(("price__gt",100))
Django元件:
1 檔案上傳
form表單
<form action="/file_put/" method="post" enctype="multipart/form-data">
姓名<input type="text" name="user">
檔案<input type="file" name="file_obj">
<input type="submit">
</form>
ajax形式
<div>
姓名<input type="text" id="user">
檔案<input type="file" name="file_obj" id="file">
<input type="button" class="filebtn" value="提交">
<p class="msg"></p>
</div>
// 傳送檔案
$(".filebtn").click(function () {
var formdata=new FormData();
formdata.append("file_obj",$("#file")[0].files[0]);
formdata.append("user",$("#user").val());
$.ajax({
url:"/file_put/",
type:"post",
// Ajax上傳檔案必備引數
processData: false , // 不處理資料
contentType: false, // 不設定內容型別
data:formdata,
success:function (response) {
console.log(response);
if (response=="OK"){
$(".msg").html("提交成功!")
}
}
})
})
檢視:
def file_put(request):
print(request.POST)
print(request.FILES)
file_obj=request.FILES.get("file_obj")
# 檔案物件有一個name屬性,獲取檔名稱字串
print(file_obj.name)
path=file_obj.name
path=os.path.join(settings.BASE_DIR,"media","img",path)
with open(path,"wb") as f:
for line in file_obj:
f.write(line)
return HttpResponse("OK")