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")