十六、Django的ORM(二)
1.一、计算机初识2.二、数据概述3.六、ip地址与子网划分4.五、网络通信实现5.四、字符编码6.三、网络基础7.十四、MySQL与Django之Model基础8.十三、Django Admin9.十二、Django视图函数和模版相关10.十一、Django url控制系统11.十、Django静态文件12.九、Django环境搭建(基于anaconda环境)13.八、Python开发环境管理14.七、ip地址配置15.二十五、JSON跨域16.二十四、文件上传17.二十三、Django Serializes18.二十二、Django之Form组件19.二十一、分页20.JS笔记21.二十、基于Bootstrap和FontAwesome制作页面22.十九、Ajax和iFrame23.十八、Django之Http24.十七、Cookie和Session
25.十六、Django的ORM(二)
26.十五、Django的ORM27.实践中前端的一些笔记28.二十六、登录相关29.二十九、RBAC+动态菜单30.二十八、XSS31.JS第三方插件32.二十七、简单的验证码实现33.三十二、Django实践的笔记34.三十一、动态Form35.三十、Kingadmin1、DecimalField
DecimalField保存浮点型数据比FloatField精确,因为它是以字符串来保存,而FloatField,数据越长,保存得越不精确。
2、索引
(命中索引) 正确使用SQL语言,使查找数据时,用到索引
username=models.CharField(
...
# db_index=True 数据库中字段是否可以建立索引 在数据库中数据很大时,建立该索引,可以查找得更快(加速查找)
# unique= 数据库中字段是否可以建立唯一索引 加速查找 && 限制列值唯一
# primary_key= 加速查找 && 限制列值唯一 && 不能为空
# unique_for_date= 数据库中字段【日期】部分是否可以建立唯一索引
# unique_for_month= 数据库中字段【月】部分是否可以建立唯一索引
# unique_for_year= 数据库中字段【年】部分是否可以建立唯一索引
...
)
3、一对一
使foreignkey唯一 或使用oneToOneField
4、ForeignKey
a、关联删除
"""
on_delete = models.CASCADE, 删除关联数据,与之关联也删除
models.DO_NOTHING,删除关联数据,引发错误IntegrityError
models.PROTECT,删除关联数据,引发错误ProtectedError
models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
models.SET_DEFAULT, 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
models.SET ,删除关联数据,
a、与之关联的值设置为指定值,设置:models.SET(值)
b、与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
"""
b、related_name, related_query_name, limit_choices_to
related_name='b', # 反向查找时,用obj.b
related_query_name='b', # 反向查找时,用obj.b_set
limit_choices_to={'id__gt':1}, # Admin中关联的部门id要求大于1 (只在Admin中生效)
5、联合唯一
class UserToTag(models.Model):
u = models.ForeignKey(to='User')
t = models.ForeignKey(to='Tag')
ctime=models.DateField()
...
class Meta:
# 联合唯一 即两条记录中 u和t 不能重复
unique_together=[
('u','t'),
]
6、多对多的高级方式
通过through属性 指定第三张表 为自己创建的表
这样,第三张表就可以有不只三列数据
但这时候,.add .set .remove等方法不能使用了 .all .filter 还可以使用
因此,这种通过through属性关联起来的第三张表多对多方式 不推荐。
推荐:普通manyTomany 或 自创建第三张表但不through关联
class Tag(models.Model):
title = models.CharField(max_length=16)
# 使用ManyToManyField只能在第三张表中创建三列数据
m = models.ManyToManyField(
to='UserInfo',
through='UserToTag', # 通过through指定第三张表就可以有三列以上的数据
through_fields=['u','t']
)
7、自关联
(ManyToMany)自关联时,related_name必须设置,方便反向查询
8、extra
9、Using :指定使用的数据库
10、raw
# 执行原生SQL语句
models.UserInfo.objects.raw('select * from userinfo')
# 其它
...
11、dates查询
12、批量创建bulk_create
13、in_bulk
models.UserInfo.objects.in_bulk([1,2,3]) #查询主键为1,2,3的记录
一些实践中的笔记
1、
classifications = models.Classification.objects.filter(direction__id=d)
# 拿到id集合的方法
ids = list(zip(*classifications.values_list('id')))[0]
2、
class video(models.Model):
title = models.CharField(max_length=32)
href = models.CharField(max_length=256)
img = models.FileField(upload_to='statics/videos/img/') #指定admin中存放图片的位置
summary = models.CharField(max_length=256)
weight = models.IntegerField(verbose_name='权重(按从大到小排列)', default=0)
create_date = models.DateTimeField(auto_now_add=True)
status_choices = ((0, '下线'),(1, '上线'),)
status = models.SmallIntegerField(choices=status_choices, default=1, verbose_name='状态')
# SET_NULL外键为空时,这个字段设为空,需要设置blank=True,null=True
level = models.ForeignKey("Level", on_delete=models.SET_NULL, blank=True,null=True)
classification = models.ForeignKey('Classification', on_delete=models.CASCADE)
class Meta:
verbose_name_plural = '视频'
def __str__(self):
return self.title
def img_url(self): #外面.img时是statics/...的路径。但项目设置了别名static,所以这里需要转换。
return self.img.name.replace('statics', 'static')
3、
userInfo = models.UserInfo.objects.filter(name=name,password=pwd)
if userInfo.exists(): # 使用exists()优化,不需查询用户信息处理
# site = userInfo.first().blog.first().site # 这种方式查询site,会查询两次数据,1:查询用户信息;2:查询博客信息
site = models.Blog.objects.filter(user__name=name).values_list('site').first()[0] #这种正向查询,只需查询一次数据
request.session['UserInfo'] = {'name': name, 'blog_site': site}
4、多对多、反向查询:
class UserFans(models.Model):
user = models.ForeignKey(UserInfo, on_delete=models.CASCADE, related_name='star')
follower = models.ForeignKey(UserInfo, on_delete=models.CASCADE, related_name='follow')
class Meta:
unique_together = [('user', 'follower',),]
class UserInfo(models.Model):
name = models.CharField(max_length=16,unique=True)
...
fans = models.ManyToManyField('UserInfo',
through="UserFans",
through_fields=('user','follower'))
class Blog(models.Model):
site = models.CharField(max_length=16,unique=True)
...
user = models.ForeignKey(UserInfo, unique=True, on_delete=models.CASCADE, related_name="blog")
blog = models.Blog.objects.filter(site=site).first()
if blog:
fans_count = blog.user.fans.count() #普通:直接查询userinfo的fans字段
#多对多+反向:follow找到user在UserFans中作为folloer的所有数据
follow_count = blog.user.follow.all() #即查询user关注了的userinfo
5、raw()原生查询
for p in models.Article.objects.raw("SELECT * FROM repository_article"):
print(p)
for p in models.Article.objects\
.raw('SELECT id, strftime("%Y-%m",create_time) AS ctime FROM repository_article'):
print("----",p.ctime)
for p in models.Article.objects\
.raw('SELECT id, count(id) as nm, strftime("%Y-%m",create_time) AS ctime FROM repository_article GROUP BY strftime("%Y-%m",create_time)'):
print("----",p.ctime, p.nm, p.id)
dates = models.Article.objects\
.raw('SELECT repository_article.id, count(repository_article.id) as nm, strftime("%Y-%m",repository_article.create_time) AS ctime, site FROM repository_article,repository_blog WHERE blog_id=repository_blog.id GROUP BY strftime("%Y-%m",create_time)')
for i in dates:
print(i.site)
# s = models.Blog.objects.raw('SELECT * FROM repository_blog WHERE site="bruce"')
sql_raw = 'SELECT repository_article.id, count(repository_article.id) as nm, strftime("%Y-%m",repository_article.create_time) AS ctime, site FROM repository_article,repository_blog WHERE blog_id=repository_blog.id AND repository_blog.site = '\
+ '\'%s\''%site + ' GROUP BY strftime("%Y-%m",create_time)'
print(sql_raw)
dates = models.Article.objects.raw(sql_raw)
for i in dates:
print(i.site)
通过结果“dates”.访问article的id,nm,ctime查询sql语言中的这些SELECT过的字段,
不需要重新查询。而访问其它字段,例如:dates.title,dates.summary,就会另外查询。
另外,dates由于是通过models.Arcticle查询出来的,因此访问的是Article的字段。
6、where()查询
articles=models.Article.objects.filter(blog__site=site)
.extra(where=['strftime("%%Y-%%m",create_time)=%s'],params=[param,]).all()
7、Select_relate 链表查询只能连有foreign的,不可以反向连
反向查询:
tag = models.Tag.objects.filter(id=param, blog__site=site).first()
articles = tag.article_set.all()
8、跨表查询相关
做评论列表时,查询评论数据,然后序列化。由于评论者在评论中是外键关联。
模版通过 评论.user 只能拿到user的id,即外键字段的值。
那么,应该怎样拿到user name?
目前的解决方法:在视图函数提前点出来
comments = models.ArticleComment.objects.filter(article_id=article_id)\
.select_related("user","reply").all()\
.values("id","content","user","reply","create_time","user__name","reply__user__name")
9、
通过values指定查询的字段,可以减少文章列表对数据库查询次数。因为文章model里关联了在模版渲染时
articles = models.Article.objects.filter(blog__site=site)\
.values("title","id","summary","create_time","comment_count","up_count")
troubles = models.FR_table.objects.filter(user_id=user_id).values("id","title",'status','ctime','processor')
troubles = models.FR_table.objects.filter(user_id=user_id).only("id","title",'status','ctime','processor')
Values 与 only是不同的
values是将字段查询出来组成字典
only只是限定查询的字段
在模版中<td>{{ a.get_status_display }}</td> 用values时,这个模版语言是没有效果的。因为用了values,模版中只能使用values指定的那些键。而用only,在模版中可以通过指定字段继续查询
only是只查对应字段 与使用values 的SQL语句一样,不知道如何产生不同的效果
如果不使用only和values,会查询所有字段,只要查询一条记录,就查询所有字段。
manyTomany: 文章被删除,文章&Tag第三张表仍有被删除文章的id 好像文章是被自己直接从数据库中删除
10、查询关联model的方法
def display_all_related_objs(obj):
"""
显示要被删除对象的所有关联对象
:param obj:
:return:
"""
ele = "<ul>"
# ele += "<li><a href='/kingadmin/%s/%s/%s/change/'>%s</a></li>" %(obj._meta.app_label,
# obj._meta.model_name,
# obj.id,obj)
for reversed_fk_obj in obj._meta.related_objects: #._meta.related_objects可以拿到反向关联和多对多的表
related_table_name = reversed_fk_obj.name
related_lookup_key = "%s_set" % related_table_name
related_objs = getattr(obj,related_lookup_key).all() #反向查所有关联的数据
ele += "<li>%s<ul> "% related_table_name
if reversed_fk_obj.get_internal_type() == "ManyToManyField": # 不需要深入查找
for i in related_objs:
ele += "<li><a href='/kingadmin/%s/%s/%s/change/'>%s</a> 记录里与[%s]相关的的数据将被删除</li>" \
% (i._meta.app_label,i._meta.model_name,i.id,i,obj)
else:
for i in related_objs:
#ele += "<li>%s--</li>" %i
ele += "<li><a href='/kingadmin/%s/%s/%s/change/'>%s</a></li>" %(i._meta.app_label,
i._meta.model_name,
i.id,i)
ele += display_all_related_objs(i)
ele += "</ul></li>"
ele += "</ul>"
return ele
合集:
Python全栈(Django)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库