Django-ORM
Posted 123why
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django-ORM相关的知识,希望对你有一定的参考价值。
# 在Django中默认使用自带的sqlite数据库 # 如果想使用mysql,在settings.py文件中添加下面语句,把之前的sqlite配置注掉 DATABASES = { ‘default‘: { ‘ENGINE‘: ‘django.db.backends.mysql‘, ‘NAME‘: ‘books‘, #你的数据库名称 ‘USER‘: ‘root‘, #你的数据库用户名 ‘PASSWORD‘: ‘‘, #你的数据库密码 ‘HOST‘: ‘‘, #你的数据库主机,留空默认为localhost ‘PORT‘: ‘3306‘, #你的数据库端口 } } TIME_ZONE = ‘Asia/Shanghai‘ # 使用上海时间 # 这时候创建数据库会报错,因为Django默认使用MySQLdb,这是python2的模块,在python3中使用pymysql # 要解决这个问题,在项目的__init__.py文件中添加 import pymysql pymysql.install_as_MySQLdb() # 创建表========================================= # models.py from django.db import models from django.contrib.auth.models import User # django自带的用户登录验证 #使用时在用户表中添加user字段Foreignkey(User) #创建一张表,可以不写主键id ,创建表时会自动创建 class Book(models.Model): # 必须继承这个库 name = models.CharField( null=True # 字段可以为空 max_length=25, # 必填 db_column = ‘user‘, # 数据库列名name->user db_index = True, # 创建索引 unique = True, # 加速查找,限制列值唯一 primary = True, # 加速查找,限制列值唯一且非空 #admin属性 verbose_name=‘user‘, blank=True, # 在admin中字段是否可以为空 editable=True , # 在admin中是否可编辑 help_text= ‘帮助信息‘, choices # 下拉框选项 # gf = models.IntegerField(choices=[(0,"v1"),(1,"v2"),],default=1) error_messages validators #自定义错误验证 ) price = models.IntegerField() pub_date = models.DateField() class Meta: uninque_together("字段一","字段二") # 联合唯一 abstract = True # abstract:抽象的 使定义的这个modle不生成表,只用来供其他model类继承 想要创建表就在命令行输入下面两条命令 python manage.py makemigrations python manage.py migrate #添加表记录 #方法一--------------------------------------------------- #一个实例对象就是一条表记录,先创建一个对象,再保存 b = Book(name = "python",price=45,........) b.save() #方法二--------------------------------------------- Book.objects.create(name = "python",price=45,........) #修改表记录 # 方式一------------------------------------------ Book.objects.filter().update() # <class ‘django.db.models.query.QuerySet‘> # 方式二------------------------------------------- b.Book.objects.get() # <class ‘app01.models.Book‘> b.prince = 80 b.save() # 删除表记录 Book.objects.filter().delete() # 查询表记录 1. all() # 取出全部,支持切片 2. first() # 取出第一个 3. last() # 取出最后一个 4. get() #一定会取出那一条记录的对象,其他的是取出一组对象,哪怕只有一个 5. values values_list #通过filter筛选出来的多条记录,可以通过调用这两个方法,获取其中的某个字段,前者是字典,后者是元组 6. exclude() # 取出除筛选条件之外的记录 7. distinct() # values取字段的时候可能会取到重复字段,用该方法可以去重 # 万能的双下划线------------------------------- __gt: #字段名下的数据小于,prince__gt = 10,prince大于10的记录 ,__gte大于等于 __contains # 字段中包含, name__contains = "p" ,包含"p", __icontains不区分大小写 # 多表操作(一对多) #添加外键,比如把书绑定到出版社 /* class ForeignKey(to,on_delete,**options) 。 第一个参数是引用的是哪个模型,第二个参数是在使用外键引用的模型数据被删除了,这个字段该如何处理, 比如有 CASCADE 、 SET_NULL 等 */ - 一对一 - 一张表其实就是一对一 -两张表的一对一要添加约束唯一性 -一对多 # class Userinfo(models.Model): # username = models.CharField( # max_length=32, # ) # p_k = models.ForeignKey( # to="Part", # 关联的表 # to_field="id", # 关联的字段,默认关联ID # 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(可执行对象) # ) # class Part(models.Model): # name = models.CharField( # max_length=32, # ) -多对多 -多对多的第三张表有两种创建方式 a. 添加ManyToMany字段 mk = models.ManyToManyField( to="Tag", related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all() related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values(‘表名__字段名‘) limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件: db_table=None, # 创建第三张表时的表名 db_constraint=True, through=None, # 指定关系表,即不自动创建,而使用手动创建的第三张表,但有些方法无法使用如add through_fields=None, ) b.手动创建第三张表 class Utotag(models.Model): u = models.ForeignKey(to="User",on_delete=models.CASCADE) t = models.ForeignKey(to="Tag",on_delete=models.CASCADE) class Meta: # 约束多对多关系,使对应的多不能重复 verbose_name = u‘图片‘ verbose_name_plural = u‘图片‘ unique_together = [ ("u","t"), #Please correct the error below. ] - 自关联 # 自关联 """ 一个网站的用户在一张表中 用户之间的互相关注,是一种自关联 """ class User_list(models.Model): user = models.CharField(max_length=32) uTOu = models.ManyToManyField(to="User_list",related_name="sss") # 建议所有的多表关系都使用related_name - 会自动创建另一张表 其中的字段名 : id from_user_list_id to_user_list_id -select_related("外键字段") from app01 import models b_obj_list = models.B.objects.all().select_related("fk") for row in b_obj_list: print(row.name) print(row.fk.name) # for循环进行跨表查询时每次查询都会到数据库中执行查询,效率低 #models.B.objects.all().select_related("fk"),这样关联表也会被一次取出,提升了性能 # 在Book类中添加这样一个字段,public = models.ForeignKey("被关联的出版社表",on_delete=models.CASCADE) #django会自动在字段名后添加 _id ,默认关联到 id 上 # 添加记录 #方式一------------------------------------------ Book.objects.create(name = "GO",prince=70,pub_date=‘2019-08-07‘,public_id=1) #方式二------------------------------------------- # 先获取要绑定的对象 public_object=Public.objects.filter(name=‘人民出版社‘)[0] # 这是一个对象集合所以取索引0 # 之后把对象赋给外键(不加_id) Book.objects.create(name=‘python‘,prince=50,pub_date=‘2017-02-1‘,public=public_object) # 查询记录 # 方式一 正向查询:根据外键找关联,先取到model,然后model.外键就取到了这个model关联的对象 book_model = Book.objects.get(name="python") print(book_model.public.name) print(book_model.public.city) # 方式二 反向查询:从被关联的表反向找关联表,格式:被关联表model.关联表_set.all().values() || _set.all().values_list() OneToOne无法反向查询 pub_set = Public.objects.get(id=1) book_msg = pub_set.book_set.all().values("name","price") print(book_msg) #-- 小写类名_set是一种默认形式,可以修改在外键参数添加related_name="" cs = models.ForeignKey(Classes,on_delete=models.CASCADE,related_name="sss") # 正向查找和反向查找 # ---找到学员对应班级,正向查找 date = models.Students.objects.all().values("student_name","cs__class_name") # values是一个queryset字典,而values_list是元组,并且values在get和filter中不能使用 for i in date: print(i["student_name"],i["cs__class_name"]) # ---找到班级对应的学员,反向查找 reverse_date = models.Classes.objects.get(id=2).students_set.all().values("student_name") print(reverse_date) return HttpResponse("成功") # 以上两种方式都是通过对象 # 方式三:伟大的双下划线__ (可以在values中和filter中使用) # 多表操作(多对多) #两张表之间的多对多需要第三张表做桥梁 # 第一种方法是手动添加第三张表,两个外键分别关联两张表 # 在其中一张表中添加字段 字段名 = models.ManyToManyField("另一张表名") # 之后Django会自动创建第三张表 # 向第三张表中添加记录 # 取到要关联的两个对象,使用add方法添加 author_obj = Author.objects.get(name="alex") book_obj = Book.objects.get(id=2) book_obj.author.add(author_obj) # .remove(),可以解除关联,也就是删除第三张表中book_obj对应的数据 # 还可以直接传参数id号 book_obj.author.add(ID号([1,2,3]或者 2)) # 删除数据 book_obj.author.remove(book_obj) #可以解除关联,也就是删除第三张表中book_obj对应的数据 book_obj.author.clear() #清空该对象的关联 # 重置关联 book_obj.author.set([1,2,3]) # 相当于清空关联,重新设置 # 查询数据 # 查找alex出过的书 ret = Book.objects.filter(author__name="alex").values("name","price") # 查找GO这本书的作者 ret1 = Book.objects.filter(name = "GO").values("author__name") print(ret1) # 查询一班的老师 obj4=models.Classes.objects.filter(class_name="一班").first() obj5=models.Classes.objects.get(class_name="一班") print(obj4.ct.all().values("teacher_name")) # obj=models.Classes.objects.all().values("class_name","ct__teacher_name") # for i in obj: # print(i) # 聚合和分组 # 聚合 # 首先导入模块 from django.db.models import Avg Sum Min Max Count # 求所有书的价格 # ret = Book.objects.aggregate(Sum("price")) # print(ret) # 分组 # 求每个出版社出的书的价格 ret = Public.objects.values("name").annotate(Sum("book__price")) print(ret) # 求每个作者出的书的价格 ret2=Author.objects.values("name").annotate(Sum("book__price")) print(ret2) #F查询和Q查询 # filter中的筛选条件可以用逗号隔开写多条,但是这些条件之间是且的关系,怎么表示或和非呢? # 修改一条记录,SQL语句可以直接使用算术运算符,但ORM中不行,怎么办呢 # F查询和Q查询 # 给每本书的价格加10 Book.objects.all().update(price=F("price")+10) # 查询除了python以外的所有书 ret = Book.objects.filter(~Q(name="python")) for i in ret: print(i.name) # 查询价格是50或者60的书 ret = Book.objects.filter(Q(price=50)|Q(price=60)) for i in ret: print(i.name) ###########注意在筛选条件中F、Q和键值对可以并存,但F、Q要在键值对前面 """ from django.db.models import Q query_obj=Q() query_obj.connector=‘or‘ query_obj.children.append((‘qq__contains‘,query)) query_obj.children.append((‘name__contains‘,query)) """ # QuerySet :查询集合的一些特点 1.查询语句不会被立即执行,只有使用查询结果时才被执行 2.查询的结果会放在缓存中,中间无论怎么修改,再次使用查询结果都是缓存中的,除非再次调用查询语句 3.查询集合会全部放在内存中,当如果这个数据特别大,那么内存就会有极大的负担,所以可以吧查询集合做成一个生成器 用的时候一条一条的取 ,给集合调用.iterator()方法
以上是关于Django-ORM的主要内容,如果未能解决你的问题,请参考以下文章