一 models模型
models模型:与数据库打交道的,对数据库约束管理的模块
orm框架:orm在做映射关系,将class类转成对应的sql语句。
models.Model类:python于orm链接起来,提醒orm,哪个django需要进行数据库的迁移。
映射关系:
python的类名对应sql语句中的表名
python中的属性对应sql语句中的字段
python中的属性值对应sql语句中的字段类型
实例:
from django.db import models # Create your models here. # ------------------创建表------------------------- class Student(models.Model): nid=models.AutoField(primary_key=True) # 主键约束 name=models.CharField(max_length=32) # 字符串字段 birth=models.DateField() # 日期类型 class_id=models.IntegerField(default=0)
同过这个类实例化出来的对象就是对应的每一条记录。
save:保存数据到数据库
from django.shortcuts import render,HttpResponse # Create your views here. from app01.models import * def add(request): s=Student(name="yuan",birth="2012-12-12",class_id=3) s.save() # 保存到数据库 return HttpResponse("添加成功")
类型介绍:AutoField:自增,primary_key=True:设置为主键
charField:字符串类型,max_length=数组,字符的长度
dataField:日期对象
IntegerField:整数类型,default:默认值
nid=models.AutoField(primary_key=True) # 主键约束 name=models.CharField(max_length=32) # 字符串字段 birth=models.DateField() # 日期类型 class_id=models.IntegerField(default=0)
类型补充:
FileField:文件类型,上传文件的。Upload_to:上传到哪个目录下面。
ImageField:图片文件类型
avatar = models.FileField(upload_to = 'avatar/',default="/avatar/default.png")
TextField:文本字符串的类型。
参数:null=True:为空;unique=True:唯一
关联表的参数:to:关联到那一张表;to_field:关联哪个字段
class ArticleDetail(models.Model): """ 文章详细表 """ nid = models.AutoField(primary_key=True) content = models.TextField() article = models.OneToOneField(to='Article', to_field='nid')
unqueic_together:联合唯一,限制了某些字段不能为空。
class ArticleUpDown(models.Model): """ 点赞表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey('UserInfo', null=True) article = models.ForeignKey("Article", null=True) is_up=models.BooleanField(default=True) class Meta: unique_together = [ ('article', 'user'), ]
二 表操作
类名.objects:需要用objects来调用类的属性
增:
create:添加纪录
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def add(request): if request.method=="POST": name=request.POST.get("name") birth=request.POST.get("birth") class_id=request.POST.get("class_id") # 方式1: # s=Student(name=name,birth=birth,class_id=class_id) # s.save() # 方式2: stu_obj=Student.objects.create(name=name,birth=birth,class_id=class_id) return redirect("/index/") return render(request,"add.html")
删:
delete:删除记录
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def delStu(request,id): # 删除主键为ID值得学生记录 # 过滤查询 filter() #ret=Student.objects.filter(nid=id) # <QuerySet [<Student: Student object>]> Student.objects.filter(nid=id).delete() return redirect("/") # 重定向的是路径
改:
update:修改,更新记录
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def set_student(request,id): if request.method=='POST': name=request.POST.get('name') date=request.POST.get('date') class_id=request.POST.get('class_id') ret=models.Student.objects.filter(sid=id).update(name=name,date=date,cid=class_id) return redirect('/student_list/') student=models.Student.objects.filter(sid=id)[0] return render(request,'set_student.html',{'student':student})
三 表的查看操作
查看记录API:
all():是一个列表,里面放的是一条条的记录,返回的是一个QuerySet对象
filter(过滤条件):过滤查找,查找出来的是符合条件的对象,返回的是一个QuerySet对象
exclade():查找出来的都是不符合条件的,相当于sql语句中的not,返回的是一个QuerySet对象
first:第一条记录,主键先升序,在取第一条记录,返回的是一个models对象
last:最后的一条记录。主键先降序再取第一条记录,返回的是一个models对象
order_by:做排序,默认是升序,-是降序。
values:是一个列表里面放的是一个个字典,是一种显示方式,返回一个QuerySet对象
values_list:是一个列表里面放的是一个个的元组,也是一种显示方式,返回一个QuerySet对象
count:计数,返回的是一个数字。
reverse:对表的查询结果反向排序。
get:只查找拿到一个models对象,不过拿到的不是一个就会报错,返回的是一个models对象
distinck:去掉具体某些相同的记录,主要用在values和values_list里面的。
exists:限制取出的条数,优化查询结果
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
(1)Student.objects.all() #返回的QuerySet类型 查询所有记录 [obj1,obj2....] (2)Student.objects.filter() #返回的QuerySet类型 查询所有符合条件的记录 (3)Student.objects.exclude()#返回的QuerySet类型 查询所有不符合条件的记录 (4)Student.objects.get() #返回的models对象 查询结果必须有且只有一个,否则报错 (5)Student.objects.all().first() #返回的models对象 查询结果集合中的第一个 (6)Student.objects.filter().last() #返回的models对象 查询结果集合中的最后一个 (7)Student.objects.all().values("name","class_id") #返回的QuerySet类型 ,列表中存放的字典 (8)Student.objects.all().values_list("name","class_id") #返回的QuerySet类型 ,列表中存放的元组 (9)Student.objects.all().order_by("class_id") # 按指定字段排序,不指定,按主键排序 (10)Student.objects.all().count() # 返回的记录个数 (11)Student.objects.all().values("name").distinct() (12)Student.objects.all().exist()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 1 all() QuerySet类型 # Student.objects.all() # 2 filter QuerySet类型 #stu_list=Student.objects.filter(birth__year="2017",birth__month="12") #stu_list=Student.objects.filter(name="龙华",class_id=6) # for stu in stu_list: # print(stu.name) #3 exclude() QuerySet类型 # stu_list=Student.objects.exclude(name="alex") # for stu in stu_list: # print(stu.name) # 4 first() 5 last() models对象 #stu_obj=Student.objects.all().first() # stu_obj=Student.objects.filter(birth__year="2017").first() # print(stu_obj.name) # 6 order_by : QuerySet类型 # stu_list=Student.objects.all().order_by("-class_id") # # # for stu in stu_list: # print(stu.name) # ret=Student.objects.order_by("class_id") # print(ret) # for i in ret: # print(i.name) # 7 values values_list : QuerySet # ret1=Student.objects.filter(birth__year="2017").values("name","class_id") # ret2=Student.objects.filter(birth__year="2017").values_list("name","class_id") # 8 count # ret=Student.objects.all().count() # ret=Student.objects.filter(nid=15).count() # print(ret) # 9 get 必须有且只有一个记录,否则报错 # Student.objects.filter(nid=5).first() # ret=Student.objects.get(class_id="5") # print(ret.name) # Student object # 10 : distinct # [obj1,obj2,..........] #ret=Student.objects.all().values("class_id").distinct() # exist() #stu_list=Student.objects.all().exists() # if stu_list: # print("OK")
查询下面的__双下划线的方法:
__gt:大于号>
__endswith:以什么结尾
__iendswith:以什么结尾,不区分大小写
__shartswith:以什么开头
__ishartswith:以什么开头,不区分大小写
__contains:包含什么
__icontains:包含什么,并不区分大小写
__lt:小于<
__in:是否在这里面
__range:某个范围
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven") models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and startswith,istartswith, endswith, iendswith
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def select(request): # ret=models.Student.objects.filter(date__year='2017',cid=2) # for stu in ret: # print(stu.name,stu.date,stu.cid) # ret=models.Student.objects.filter(cid__gt=2) # for stu in ret: # print(stu.name,stu.cid) # ret=models.Student.objects.filter(name__endswith='g') # for stu in ret: # print(stu.name) # ret=models.Student.objects.filter(name__icontains='ng') # for stu in ret: # print(stu.name) # # # ret=models.Student.objects.filter(name__contains='e') # for stu in ret: # print(stu.name) # ret=models.Student.objects.filter(name__startswith='f') # for stu in ret: # print(stu.name) # ret=models.Student.objects.filter(cid__in=[2,5]) # for stu in ret: # print(stu.cid,stu.name) # ret=models.Student.objects.filter(cid__range=[3,7]) # for stu in ret: # print(stu.cid,stu.name) # ret=models.Student.objects.filter(cid__lt=4) # for stu in ret: # print(stu.cid,stu.name) return HttpResponse('OK')
查看转换的sql语句:将下面一段代码添加到setting.py文件中就可以了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
四 多表操作
数据类型补充:
DecimalField:浮点数,decimal_places:小数位的个数。
EmailField:邮箱数据类型
一对多表的创建:ForeignField("关联的表名"):设置外键,orm默认指定关联表的主键,是多表的某个字段的关联表的一个对象。
related_name='名字':反向查找的时候可以直接使用这个名字。
to_field:可以设置多表与关联表的那个字段相关联。
class Book(models.Model): title = models.CharField(max_length=32) publishDate = models.DateField() price = models.DecimalField(max_digits=5, decimal_places=2) # 999.99 # 创建一对多的关联字段 : 是与某个书籍对象关联的出版社对象(注意,只有一个对象) publish=models.ForeignKey("Publish")
操作方法:
增:1 外键关联表对象字段可以直接赋值一个单表的对象。
2 外键字段可以直接赋值一个单表关联的字段的值。
#pub_obj=Publish.objects.get(name="沙河出版社") ########################### 一对多添加################################## # 方式1: # Book.objects.create(title="金瓶",publishDate="2001-12-12",price=122,publish=pub_obj) # 方式2: #book_obj=Book.objects.create(title="金瓶3",publishDate="2011-08-12",price=112,publish_id=1)
查:1 可以使用单表查询将多表的外键的值取出来,然后在到单表里面将对象给过滤出来。
2 可以将多表的那条对象取出来,然后可以使用点方法给关联对象就可以操作取值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# #################一对多查询 # 金瓶的出版社名称 # book_obj=Book.objects.filter(title="金瓶2").first() # print(book_obj.title) # print(book_obj.price) # print(book_obj.publishDate) # print(book_obj.publish_id) # 1 ########## # pid=book_obj.publish_id # 1 # pub_obj=Publish.objects.filter(nid=pid).first() # 与这本书关联的出版社对象 # print(pub_obj.name) #----- # print(book_obj.publish.name)
多对多表创建:
ManyToManyFodel:不用手动创建第三张表,orm自动给你创建。创建的是绑定表某个对象的关联对象集合。
class Book(models.Model): title = models.CharField(max_length=32) publishDate = models.DateField() price = models.DecimalField(max_digits=5, decimal_places=2) # 创建的多对多的关系 authors=models.ManyToManyField("Author") def __str__(self): return self.title
多对多操作:需要借助单表的查询方法,返回的是一个QuerySet类型。
增:orm分别拿到的是两个表的对象,然后在添加到关系表里面去。
可以将没有ManyToManymodel约束条件的表的关联字段值拿到,然后在添加到关系表去。也可以直接写数字添加,
add:追加一条记录
*:直接加上一个QuerySet类型对象就可以添加
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
########################### 多对多添加################################## # book_obj = Book.objects.create(title="金瓶3", publishDate="2011-08-12", price=112, publish_id=1) # # alex=Author.objects.get(name="alex") # aler.id # egon=Author.objects.get(name="egon") # egon.id # # # 绑定关系 # book_obj.authors.add(alex,egon) ###################### # 追加一个作者 # book_obj=Book.objects.filter(title="金瓶3").first() # # wenzhou=Author.objects.get(name="文州") # book_obj.authors.add(wenzhou) # 绑定关系2: book_obj = Book.objects.create(title="金瓶5", publishDate="2011-08-12", price=112, publish_id=1) # authors=Author.objects.all() # book_obj.authors.add(*authors) #绑定关系3: book_obj.authors.add(1,2)
查:get():获取某一个对象
all():获取记录
################### 多对多查询 # 查询金瓶3所有作者的名字 # book_obj=Book.objects.get(title="金瓶3") ######### # book_obj.authors.all() # print(book_obj.authors.all()) # <QuerySet [<Author: alex>, <Author: egon>]> # # for author in book_obj.authors.all(): # print(author.name)
删:remove:删除相关记录
clear:清空相关记录
# 删除一个作者 # alex=Author.objects.get(name="alex") # book_obj = Book.objects.filter(title="金瓶3").first() # book_obj.authors.remove(alex) # 清空所有作者 # book_obj = Book.objects.filter(title="金瓶3").first() # book_obj.authors.clear()
一对一表创建:unique=True:唯一约束
OneToOneField:创建一对一的外键
class AuthorDetail(models.Model): addr=models.CharField(max_length=32) email=models.EmailField() author=models.OneToOneField("Author")
反向查询:__set:多表反向查询字段,返回的是一个集合。使用方法是:表名__ser.all():自己拼接。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
.publish ==== 一对多(Book----------------->Publish) <---------------- .book_set.all() 查询python这本书的出版社的名字 (正向查询,按字段) book_obj=Book.objects.get(title="python") print(book_obj.publish.name) 查询沙河出版社出版过的书籍名称 (反向查询按:表名_set) pub_obj=Publish.objects.get(name="人民出版社") print(pub_obj.book_set.all()) .authors.all() ==== 多对多(Book------------------->Author) <-------------------- .book_set.all() 查询python这本书的所有作者的名字 (正向查询,按字段) book_obj=Book.objects.get(title="python") print(book_obj.authors.all()) 查询alex出版过的所有书籍 (反向查询按:表名_set) author_obj=Author.objects.get(name="alex") print(author_obj.book_set.all()) # <QuerySet [<Book: 金瓶4>, <Book: 金瓶5>]>
一对一表反向查寻是不需要__set的,因为返回的结果只有一个。使用方法:表名.all():直接调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
.author ==== 一对一(AuthorDetail--------------->Author) <---------------- .authordetail 查询的地址在烟台并且email是789的作者的名字 (正向查询,按字段) authordetail=AuthorDetail.objects.get(addr="烟台",email=789) print(authordetail.author.name) 查询文州的email (反向查询按:表名) wenhzou=Author.objects.get(name="文州") print(wenhzou.authordetail.email) # 123@qq.com # 查询住在沙河的作者出版过的所有书籍的名称以及出版社名称 author_obj=Author.objects.get(name="alex") print(author_obj.book_set.all()) # <QuerySet [<Book: 金瓶4>, <Book: 金瓶5>]>
总结:反向查询靠的是表名,而正向查询靠的的是字段名。
基于__双下划线查询,join方法:
表名__字段名:反向查询,按照表名查询;字段对象__字段名:正向查询,按照字段查询
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
##########################基于双下划线的查询:正向查询,按字段;反向查询,按表名##################### # 查询沙河出版社出版过的书籍名称 # ret=Publish.objects.filter(name="人民出版社").values("book__title") # print(ret) # Book.objects.filter(publish__name="人民出版社").values("title") # email以456开头的作者出版过的所有书籍名称以及出版社名称 ret=Book.objects.filter(authors__authordetail__email__startswith="456").values("title","publish__name") print(ret) sql: SELECT "app01_book"."title", "app01_publish"."name" FROM "app01_book" INNER JOIN "app01_book_authors" ON ("app01_book"."id" = "app01_book_authors"."book_id") INNER JOIN "app01_author" ON ("app01_book_authors"."author_id" = "app01_author"."id") INNER JOIN "app01_authordetail" ON ("app01_author"."id" = "app01_authordetail"."author_id") INNER JOIN "app01_publish" ON ("app01_book"."publish_id" = "app01_publish"."nid") WHERE "app01_authordetail"."email" LIKE '456%' ESCAPE '\' LIMIT 21; args=('456%',)
分组和聚合:
aggregate:统计信息返回的是一个人对象,是QuerySet对象额终结者。
annotate:统计信息,返回的是一个QuerySet对象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def query3(request): from django.db.models import Avg,Sum,Count,Min #############################聚合函数:aggregate################### #查询所有书籍的平均价格 # ret=Book.objects.all().aggregate(avgPrice=Avg("price")) # print(ret) # {} #############################分组函数:annotate ################### # 查询每一个出版社出版过的书籍个数 # ret=Publish.objects.all().annotate(c=Count("book__title")) # for pub_obj in ret: # print(pub_obj.name,pub_obj.c) # 查询每一本书的作者个数 # ret=Book.objects.all().annotate(counts=Count("authors__id")).values("title","counts") # print(ret) # 查询每一个作者出版过的书籍的平均价格 # ret=Author.objects.all().annotate(avgprice=Avg("book__price")).values("name","avgprice") # print(ret) return HttpResponse("OK")
五 F与Q查询
F:主要用于数值的查询和修改,主要可以用在两个字段的比较个重新计算和赋值。
def update_book(request): # models.Book.objects.all().update(price=F('price')-100) print(models.Book.objects.filter(comment__gt=F('likeBook')).values_list('title')) return HttpResponse('OK')
Q:在Q里面包含了逻辑运算符,或| 与& 非~。可以使用与多个约束条件的查看
def Q_book(request): print(models.Book.objects.filter((Q(price__gt=2000)|Q(title__startswith='方合意'))&Q(pubdate__day='15')).values_list('title')) return HttpResponse('OK')
六 用户认证模块(auth)
导入方式:
from django.contrib.auth.models import User from django.contrib import auth
request.user:获取浏览中的字符串,如果登陆,显示的是当前用户登陆的那一个对象,如果没有登陆,显示的是一个匿名用户。
auth模块:django将多个用户表的信息全部封装到了user这个表的下面,由于表不是我们手动创建的,所以不能直接的操作用户表。
createsuperuser:创建超级用户
auth.authenticate:验证方法,将输入的密文加密,然后在到user表里面进行比较认证,返回的是一个对象。
auth.login(请求对象,登陆对象):创建session对象,并发送到浏览器。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def login(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") user=auth.authenticate(username=user,password=pwd) if user: auth.login(request,user) # request.session["user"]=user.username return redirect("/index/") return render(request, "login.html")
auth.logout:注销,将某个对象session对应的记录全部删除
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def log_out(request): auth.logout(request) # request.session.flush() return redirect("/login/")
user对象UPI:
is_authenticated:判断当前的用户是否登陆,放回的是布尔值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def index(request): user=request.user # 显示当前登录用户对象 if not user.is_authenticated(): return redirect("/login/") name=request.user.username return render(request,"index.html",{"name":name})
user.objects.create_user:将传入的password值转成密文,然后在保存到user表里面去。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def reg(request): if request.method == "POST": user = request.POST.get("user") pwd = request.POST.get("pwd") user=User.objects.create_user(username=user,password=pwd) return redirect("/login/") return render(request,"reg.html")
check_password:用户注册时使用,检测密码
set_password:删除原来的密码,将新的值存放到user表里面去。
save:提交
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def setpwd(request): if request.method == "POST": user = request.POST.get("user") pre_pwd = request.POST.get("pre_pwd") new_pwd = request.POST.get("new_pwd") repeat_pwd = request.POST.get("repeat_pwd") user=auth.authenticate(username=user,password=pre_pwd) if user: user.set_password(new_pwd) user.save() return redirect("/login/") return render(request,"setpwd.html")
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
用户认证 auth模块--------------auth.user表 auth模块API: user=request.user: if 用户登录状态: user就是登录对象,否则就是一个匿名对象 验证方法: auth.authenticate(username=user,password=pwd) 插入session记录:auth.login(request,user) # request.session["user"]=user.username 删除session记录:auth.logout(request) # request.session.flush() user对象的API: user.is_authenticated():返回布尔值,该用户登录则为True,否则为False 注册:user=User.objects.create_user(username=user,password=pwd) 修改密码: user.set_password(new_pwd) user.save()