Day45 of learning python --Django的ORM操作(model操作)
一、ORM简介
ORM实现了数据模型和数据库的解耦,即数据模型的设计不需要依赖特定的数据库,通过简单的配置就可更换数据库。
ORM是‘对象-关系-映射’的简称

二、单表操作
1.创建表
1)django项目下,在model.py中创建数据库表(一个类代表一个表,类的对象相当于一列数据)
from django.db import models q class UserGroup(models.Model): # 类名就相当于表名,创建成功时,在数据上表名会显示成:app名字+类名,中间用下划线隔开:例如app01_UserGroup,当使用的是models的点数据库表时,直接使用类名,而当使用sql语句时,要使用:app名字+类名 # 部门 tittle = models.CharField(max_length=32) class Meta: # 这是把数据库中的表名直接设置成UserGroup db_table = 'UserGroup' class UserInfo(models.Model): # 创建一个表 # 员工 nid = models.BigAutoField(primary_key=True) # nid字段名,BigAutoFieleField是自增长类型。当model中如果没有自增列,则自动会创建一个列名为id的列 username = models.CharField(max_length=32) password = models.CharField(max_length=64) # age = models.IntegerField(null=True) age = models.IntegerField(default=1) # ug_id ug = models.ForeignKey('UserGroup',on_delete=models.CASCADE,null=True) # 一个对象代指一行数据 外键
2)字段和参数
AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key=True 注:当model中如果没有自增列,则自动会创建一个列名为id的列 from django.db import models class UserInfo(models.Model): # 自动创建一个列名为id的且为自增的整数列 username = models.CharField(max_length=32) class Group(models.Model): # 自定义自增列 nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) SmallIntegerField(IntegerField): - 小整数 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整数 0 ~ 32767 IntegerField(Field) - 整数列(有符号的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整数 0 ~ 2147483647 BigIntegerField(IntegerField): - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 自定义无符号整数字段 class UnsignedIntegerField(models.IntegerField): def db_type(self, connection): return 'integer UNSIGNED' PS: 返回值为字段在数据库中的属性,Django字段默认的值为: 'AutoField': 'integer AUTO_INCREMENT', 'BigAutoField': 'bigint AUTO_INCREMENT', 'BinaryField': 'longblob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DurationField': 'bigint', 'FileField': 'varchar(%(max_length)s)', 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', 'IntegerField': 'integer', 'BigIntegerField': 'bigint', 'IPAddressField': 'char(15)', 'GenericIPAddressField': 'char(39)', 'NullBooleanField': 'bool', 'OneToOneField': 'integer', 'PositiveIntegerField': 'integer UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED', 'SlugField': 'varchar(%(max_length)s)', 'SmallIntegerField': 'smallint', 'TextField': 'longtext', 'TimeField': 'time', 'UUIDField': 'char(32)', BooleanField(Field) - 布尔值类型 NullBooleanField(Field): - 可以为空的布尔值 CharField(Field) - 字符类型 - 必须提供max_length参数, max_length表示字符长度 TextField(Field) - 文本类型 EmailField(CharField): - 字符串类型,Django Admin以及ModelForm中提供验证机制 IPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 GenericIPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 - 参数: protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both" URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字 UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 - 参数: path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 允许文件 allow_folders=False, 允许文件夹 FileField(Field) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录 - 参数: upload_to = "" 上传文件的保存路径 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage width_field=None, 上传图片的高度保存的数据库字段名(字符串) height_field=None 上传图片的宽度保存的数据库字段名(字符串) DateTimeField(DateField) - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 时间格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 FloatField(Field) - 浮点型 DecimalField(Field) - 10进制小数 - 参数: max_digits,小数总长度 decimal_places,小数位长度 BinaryField(Field) - 二进制类型
null 数据库中字段是否可以为空 db_column 数据库中字段的列名 db_tablespace default 数据库中字段的默认值 primary_key 数据库中字段是否为主键 db_index 数据库中字段是否可以建立索引 unique 数据库中字段是否可以建立唯一索引 unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引 unique_for_month 数据库中字段【月】部分是否可以建立唯一索引 unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 verbose_name Admin中显示的字段名称 blank Admin中是否允许用户输入为空。 editable Admin中是否可以编辑 help_text Admin中该字段的提示信息 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 如:{'null': "不能为空.", 'invalid': '格式错误'} validators 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidator from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\ MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 如: test = models.CharField( max_length=32, error_messages={ 'c1': '优先错信息1', 'c2': '优先错信息2', 'c3': '优先错信息3', }, validators=[ RegexValidator(regex='root_\d+', message='错误了', code='c1'), RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'), EmailValidator(message='又错误了', code='c3'), ] )
(1)blank 如果为True,该字段允许不填。默认为False。 要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。 (2)default 字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。 (3)primary_key 如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True, Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为, 否则没必要设置任何一个字段的primary_key=True。 (4)unique 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的 (5)choices 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
3)Django下修改setting默认配置,用来连接pymysql数据库
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'d70django', #库名,这个要我们先在数据库里创建一个库 'USER':'root', #连接数据库的用户名 'PASSWORD':'baicells', #连接数据库的密码 'HOST':'127.0.0.1', #本机ip 'PORT':3306 #端口默认3306 } 先把settings里面的databases给删除了,再写上自己的数据库的信息。
4)配置app01下的__init__.py文件
因为Django默认你导入的驱动的是MySqldb,但是我们用的是pymysql,所以,我们把pymysql伪装成MySQLdb,让django识别
import pymysql pymysql.install_as_MySQLdb()
5)在pycharm下的terminal终端下输入指令来创建表结构
python manage.py makemigrations
等待跑完之后输入
python manage.py migrate
2.添加表结构
在视图函数输入创建表数据的代码,如果通过路由调用,进行创建数据
1)方式一
在视图函数下输入下面代码 UserType_obj = UserType(title='超级用户') # 实例化一个对象 UserType_obj.save() # 加上save()方法
2)方式二
book_obj=models.book.objects.create(name='python',price=20) #每一个定义的字段都要给值,自增长的不用,该create的返回值是新建的数据行
三、models的基本操作-增删改查
1)查
queryset对象就是有实例化对象组成的集合,这和JQuery对象与DOM对象关系差不多 <1> all(): 查询所有结果 得到queryset对象 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 queryset对象 <3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个, 实例化对象 如果符合筛选条件的对象超过一个或者没有都会抛出错误。 <4> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 queryset对象 <5> order_by(*field): 对查询结果排序 queryset对象 <6> reverse(): 对查询结果反向排序 queryset对象 只能和order_by搭配使用 <8> count(): 返回数据库中匹配查询(QuerySet)的对象数量。 <9> first(): 返回第一条记录 得到模型类对象 <10> last(): 返回最后一条记录 得到模型类对象 <11> exists(): 如果QuerySet包含数据,就返回True,否则返回False <12> values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列 <13> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 <14> distinct(): 从返回结果中剔除重复纪录
Book.objects.filter(price__in=[100,200,300]) 可以找出price=100,或price=200,或price=300 Book.objects.filter(price__gt=100) 可以找出price>100的 Book.objects.filter(price__lt=100) 可以找出price<100的 Book.objects.filter(price__range=[100,200]) 可以找出price在100到200之间的 Book.objects.filter(title__contains="python") 可以找出title里包含‘python’的 Book.objects.filter(title__icontains="python") 和上面一样,只是不区分大小写 Book.objects.filter(title__startswith="py") 可以找出title里以‘py’开头的 Book.objects.filter(pub_date__year=2012) 可以找出pub_date是2012年的
2)增
models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs
# 一次性增加多条数据
models.UserAdmin.objects.bulk_create([models.UserAdmin(user='egon',password='egon1'), models.UserAdmin(user='egon1',password='egon2') ])
3)删
models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 obj.delete() #obj可以使queryset对象,也可以是实例化对象
4)改
models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs obj = models.Tb1.objects.get(id=1) obj.c1 = '111' obj.save() # 修改单条数据
5)练习
1,查询人民出版社的价格大于200的书籍 models.book.objects.all().filter(publish='人民出版社',price__gt=200) 2,查询2017年8月出版的所有以py开头的书籍名称 models.book.objects.all().filter(pub_date__year=2017,pub_date__month=8,name__startswith='py').values('name') 3,查询价格为50,100或150的所有书籍名称和出版社名称 models.book.objects.all().filter(price__in=[50,100,150]).values('name','publish') 4,查询价格在100到200之间的所有书籍名称及其价格 models.book.objects.all().filter(price__range=[100,200]).values('name','price') 5,查询所有人民出版社出版的书籍的价格(从高到低排序,去重) models.book.objects.all().filter(publish="人民出版社").values("price").order_by('-price').distinct()
四、一对多关系的跨表查询
一本书只有一个出版社,一个出版社可以出版多本书,从而书与出版社之间就构成一对多关系,书是‘多’的一方,出版社是‘一’的一方,我们在建立模型的时候,把外键写在‘多’的一方,即我们要把外键写在book类。
from django.db import models # Create your models here. class Book(models.Model): name = models.CharField(max_length=16) price = models.IntegerField() publish = models.ForeignKey('Publish',on_delete=models.CASCADE) class Publish(models.Model): name = models.CharField(max_length=16) addr = models.CharField(max_length=16) phone = models.IntegerField() # 在创建模型时不用创建id字段,在makemigrations命令输入之后,它会在migrations文件夹下生产一个py文件记录models.py里面所有的改动,在记录的时候就会自动给你加上自增长的主键字段id。
# 基于对象跨表查询 # 一对多查询,正向查询(按外键字段:publish) book_obj = models.Book.objects.all().first() # 查询第一个book对象 # book_obj.publish 是book对象关联的出版社对象 print(book_obj.publish.name,book_obj.publish.addr,type(book_obj)) # 反向查询(按表名小写_set:book_set) publish_obj = models.Publish.objects.get(name='电子出版社') # publish_obj.book_set.all() 与电子出版社关联的所有书籍对象的集合 book_list = publish_obj.book_set.all() print(type(book_list)) for row in book_list: print(row.name) # 利用双下划线跨表--正向查询 按外键字段:publish # 查询书对应的出版社的名字 ret = models.Book.objects.filter(id=1).values('publish__name') print(ret) ret = models.Book.objects.filter(id=1).values_list('publish__name') print(ret) # 查询人民出版社出版过的所有书籍的名字和价格 ret = models.Book.objects.filter(publish__name='人民出版社').values('name','price') print(ret) # 利用双下划线跨表--反向查询 按表名:book ret = models.Publish.objects.filter(name='华南理工出版社').values('book__name','book__price') print(ret)
五、一对一关系的跨表查询
一个作者只能对应一个作者详细信息表,他们之间就是一对一关系,这和多对多一样的,关系写在哪张表都是可以的
class Author(models.Model): name = models.CharField(max_length=16) age = models.IntegerField() author_info = models.OneToOneField('Author_Info',on_delete=models.CASCADE) # 第二个参数是,自动跟随删除,当作者不在了,随作者的信息也会删除 class Meta: db_table = 'author' class Author_Info(models.Model): gf_name = models.CharField(max_length=10) phone = models.IntegerField() card = models.IntegerField()
# 一对一查询 # 基于对象跨表查询--正向查询 按外键字段查询:author_info obj = models.Author.objects.filter(name='天青色等烟雨').first() print(obj.author_info.gf_name,obj.author_info.card) # 基于对象跨表查询--反向查询 按表名小写:author obj = models.Author_Info.objects.filter(id=1).first() print(obj.author.name) # 基于双下划线的跨表查询,正向按外键字段,方向按表名小写 # 正向查询 obj = models.Author.objects.filter(id=1).values('author_info__card') print(obj) # 反向查询 obj = models.Author_Info.objects.filter(author__age=18).values('phone','card') print(obj) obj = models.Author_Info.objects.filter(id=1).values('author__age', 'author__name') print(obj)
六、多对多关系的跨表查询
一本书可以有多个作者,一个作者可以写多本书,从而书和作者就构成了多对多的关系,我们在创建模型的时候,把多对多关系写在其中的任何一张表都可以。
class Book1(models.Model): name = models.CharField(max_length=16) price = models.IntegerField() publish = models.CharField(max_length=16) author1 = models.ManyToManyField('Author1',db_table='book_author') # 多对多关系时,有第三张表的形成,第二个参数为把关系表的名字改为‘book_author’,如果不写,名字会是应用名_本模型名的小写_另一张模型名的小写。如‘app_book_author’ class Meta: db_table='book1' class Author1(models.Model): name= models.CharField(max_length=16) age = models.IntegerField() class Meta: db_table = 'author1'
# 多对多查询 # 基于对象跨表查询--正向查询 按外键字段查询:author # 查询<python基础教程>所有作者以年龄 obj = models.Book1.objects.filter(name='python基础教程').first() authors = obj.author1.all() for row in authors: print(row.name,row.age) # 基于对象跨表查询--反向查询 按表名小写_set:book1_set # 查询作者出过的所有书的名称 obj = models.Author1.objects.filter(name='林玮任').first() books = obj.book1_set.all() for row in books: print(row.name) # 基于双下划线的跨表查询 # 正向查询按外键字段 :author1__name # 查询作者出过的所有书的名称 obj = models.Book1.objects.filter(author1__name='林玮任').values('name') print(obj) # 反向查询按表名:book obj = models.Author1.objects.filter(name='林玮任').values('book1__name') print(obj)
补充:related_name设置
可以通过Foreignkey和MangToMangField的定义中设置related_name的值来复写foo_set的名称。 publish=ForeignKey('Publish',related_name='booklist') #这样之后,反向就不用表名_set,就用booklist # 查询 人民出版社出版过的所有书籍 publish=Publish.objects.get(name="人民出版社") book_list=publish.bookList.all() # 与人民出版社关联的所有书籍对象集合
七、聚合查询与分组查询
1)聚合,aggregate(*args,**kwargs)
aggregate(*args,**kwargs)是Queryset的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是按照字段和聚合函数的名称自动生成出来的 计算所有图书的平均价格 from django.db.models import Avg Book.objects.all().aggregate(Avg('price')) 结果:{'price__avg': 34.35} 如果你想要为聚合值指定一个名称,可以向聚合函数前面用一个变量名来接收,此时,键的名称就变为接收的变量名 Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35} 在终止子句里面可以放多个聚合函数,得到结果就是有多个键值对 from django.db.models import Avg, Max, Min Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} aggregate()只能对一个分组有用,对于按某字段分完组后的n个组,此时aggregate()就不能循环对每个分组作用,它只会得到第一组的结果
2)分组
单表分组查询
查询每一个部门名称以及对应的员工数 emp: id name age salary dep 1 alex 12 2000 销售部 2 egon 22 3000 人事部 3 wen 22 5000 人事部 emp.objects.values('dep').annotate(c=Count('*')) values(‘dep’)就是按‘dep’进行分组 annotate()对每个分组的进行操作
多表分组查询
每一个出版社的名称和出版过的书籍个数 Publish.objects.values('name').annotate(c=Count('book')) #首先读整个语句,当读到‘book’时,就会把两个表连起来,然后在按Publish.name分组 跨表分组查询本质就是将关联表join成一张表,然后再按单表的思路进行分组查询 还有一种写法: publishlist=Publish.objects.annotate(c=Count('book')) 这相当于给Publish表添加了一个‘c’字段。首先也是把两张表连起来,以Publish分组,计算每个Publish的书籍数量 publishlist是一个queryset对象集合,里面放的是publish模型类对象,只是现在的对象比之前多了一个‘c’字段 for publish in publishlist: print(publish.name,publish.c) 利用for循环就可以遍历出每个模型类对象,然后用句点符‘.’就可以取得任何字段的值 我们也可以不用for循环,直接用values_list()就可以实现,如上面的for循环可以写成:values_list('name','c') 统计每一本书的作者个数 Book.objects.annotate(c=Count('author')).values_list('name','c') filter()放在annotate()前面就是相当于where 统计每一本以py开头的书籍的作者的个数: Book.objects.filter(name__startswith='py').annotate(c=Count('author')).values_list('name','c') filter()放在annotate()后面就相当于having 统计作者个数大于1的书籍: Book.objects.annotate(c=Count('author')).filter(c__gt=1).value_list('name','c') 根据书籍的作者数来排序: Book.objects.annotate(c=Count('author')).orderby('c')
八、F查询与Q查询
F,更新时用于获取原来的值。Q,用于构造复杂的查询条件
1)F查询
from django.db.models import F
在之前,对象的字段只能放在比较符的前面,比如filter(id__gt=2),但现在,有一个表,有生物成绩ss字段和物理成绩ws字段,统计物理成绩高于生物成绩的学生: student.objects.filter(ws__gt=ss) 这样写肯定是报错的,因为字段写在了比较符后面,但此时我们借助F查询就可以不报错了,正确写法如下: student.objcts.filter(ws__gt=F('ss')) F('ss')此时就是把ss字段的值取出来,就相当于一个纯数字了,可以进行加减乘除操作 查询物理成绩大于生物成绩两倍的学生 student.objects.filter(ws__gt=F('ss')*2) 把每个学生的物理成绩加上10分: student.objects.all().update(ws=F('ws')+10)
2)Q查询
# q使用有两种方式:对象方式,方法方式 # 对象方式 from django.db.models import Q models.UserInfo.objects.filter(Q(id=1)) models.UserInfo.objects.filter(Q(id=1) | Q(id=2)) # 或 models.UserInfo.objects.filter(Q(id=1) & Q(id=2)) # 与 ''' # 方法方式,运维系统的多个条件的集合 condition_dict = { 'k1':[1,2,3,4], 'k2':[1,], } con = Q() for k,v in condition_dict.items(): q = Q() q.connector = 'OR' for i in v: q.children.append(('id',i)) con.add(q,'AND') h = models.UserInfo.objects.filter(con) print(h.query) #SELECT "app01_publish"."id", "app01_publish"."name", "app01_publish"."addr", "app01_publish"."phone" FROM "app01_publish" WHERE (("app01_publish"."id" = 1 OR "app01_publish"."id" = 2 OR "app01_publish"."id" = 3 OR "app01_publish"."id" = 4) AND "app01_publish"."id" = 1) for row in h: print(row.id,row.name,row.addr,row.phone) '''
九、Extra
额外查询条件及相关表,排序
extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) a.映射 #select #select_params=None #select 此处 from 表 b.条件 #where = None #params=None, #select * from 表 where 此处 c.表 #tables #select * from 表,此处 (笛卡尔积) d.排序 #order_by=None #select * from 表 order by 此处
运用:
models.UserInfo.objects.extra( select={'newid':'select count(1) from app01_usertype where id>%s'}, select_params=[1,], where=['age'>%s'], params=[18,], order_by=['-age'], tables=['app01_usertype'] ) """ select app01_userinfo.id, (select count(1) from app01_usertype where id>1) as newid from app01_userinfo,app01_usertype where app01_userinfo.age>18 order_by app01_userinfo.age desc """
v = models.UserInfo.objects.all().extra( select={ 'n':"select count(1) from app01_usertype where id=%s or id=%s", 'm': "select count(1) from app01_usertype where id=%s or id=%s", }, select_params=[1,2,3,4] ) for obj in v: print(obj.name,obj.id,obj.n) models.UserInfo.objects.extra( where=["id=1 or id=%s","name=%s"], params=[1,"alex"] ) models.UserInfo.objects.extra( tables=['app01_usertype'], )
十、原生SQL和raw
直接使用SQL语句进行查询
-原生SQL语句 from django.db import connection,connections cursor = connection.cursor() # connection=default数据 cursor = connections['db2'].cursor() cursor.execute("""select * from app01_userinfo where id = %s""",[1]) row = cursor.fetchone() row = cursor.fetchall()
raw: result = models.UserInfo.objects.raw('select * from userinfo') [obj(UserInfo),obj,]
十一、添加表的纪录
1.一对多关系
之前我们创建了Book表和Publish表,两者就是一对多的关系,Book表是‘多’的一方,所以外键字段在Book表,Book表添加和之前的不一样,而‘一’的Publish表就是一张单表,和之前的一样,所以我们只要学习‘多’的一张Book表的添加就行了。添加表记录有两种方式。
1.1 按models.py里面Book类的属性来添加
pub=Publish.objects.all().filter(id=1).first() #首先找到id为1的Publish对象 book=Book.objects.create(name=name,price=price,publish=pub,pub_date=pub_date) #然后把这一对象赋值给Book类的publish属性
1.2 按数据库里面Book表的字段来添加
book=Book.objects.create(name=name,price=price,publish_id=1,pub_date=pub_date) #直接把Publish的id赋值给book表的publish_id就行了
2.多对多关系
之前我们创建了Book表和Author表,两者就是多对多关系,我是把多对多关系写在book表中的,所以从book去添加关联关系是正向的。
# 当前生成的书籍对象 book_obj=Book.objects.create(title="追风筝的人",price=200,publishDate="2012-11-12",publish_id=1) # 为书籍绑定的作者对象 a1=Author.objects.filter(id=2).first() # 在Author表中主键为2的纪录 a2=Author.objects.filter(id=1).first() # 在Author表中主键为1的纪录 # 绑定多对多关系,即向关系表book_authors中添加纪录,正向用属性,反向用表名_set 第一种,以Book为基表,因为多对多关系是写在Book中的,所以现在属于正向关联,用属性 book_obj.author.add(author1,author2) #这是给book_obj对象绑定上author1和author2两个对象。这里的author不是Author小写,而是Book类的一个属性 第二种,以Author为基表,因为多对多关系不是写在Author表,所以属于反向关联,用表名小写_set author_obj.book_set.add(book1,book2) #这是给author_obj对象绑定上book1和book2两个对象,但是这里book可不是Author类的属性,而且也没有这个属性,它是Book表小写后得到的 关系表的方法: 1,add()方法 参数可以是可以是n个模型类对象,如上面的写法 也可以是一个queryset集合,如author_list=Author.objects.filter(id__gt=2),这是找出id大于2的作者集合 book_obj.author.add(*author_list) 还可以是一个主键列表,如下面的写法 book_obj.author.add(*[1,3,4]) 2,remove()方法,移出关系方法 现在book1关联着author1和author2两个作者 book1.author.remove(author1) #此时book1就关联author2一个作者 反向也行author2.book_set.remove(book2) #把author2的关联书籍book2给移出 3,clear()方法,清空关系方法 book1.author.clear() #把book1的所有关联关系给删除,现在book1就没有关联作者了 author1.book_set.clear() 一样的,把author1的所有关联书籍的关联关系删除 4,set()方法,先把关联关系清空,再添加关联关系 假如book1关联着author1 book1.author.set(author2) 先把与author1的关联关系删除,然后再建立与author2的关联关系 假如author3关联着book1 author3.book_set.set(book2) 先把关联关系清空,再建立与book2的关联关系 5,=方法,赋值一个可迭代对象,关联关系会被整体替换 假如book1关联author1 new_list=[author2,author3] book1.author=new
3.一对一关系
给Author1类的属性赋值 info=Author_Info.objects.create(gf_name=gf_name,telephone=telephone,ShenFenZheng=ShenFenZheng) #这是创建了一条Author_Info记录,info就是一个Author_info对象 Author1.objects.create(name=name,age=age,author_info=info) 把创建的info对象赋值给author_info属性 和一对多一样,也可以使用Author表的字段赋值 Author1.objects.create(name=name,age=age,author_info_id=2)
神奇的双下划线
# 获取个数 # # models.Tb1.objects.filter(name='seven').count() # 大于,小于 # # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 # models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 # models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # in # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # isnull # Entry.objects.filter(pub_date__isnull=True) # contains # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 # models.Tb1.objects.exclude(name__icontains="ven") # range # # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # 其他类似 # # startswith,istartswith, endswith, iendswith, # order by # # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc # group by # # from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" # limit 、offset # # models.Tb1.objects.all()[10:20] # regex正则匹配,iregex 不区分大小写 # # Entry.objects.get(title__regex=r'^(An?|The) +') # Entry.objects.get(title__iregex=r'^(an?|the) +') # date # # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) # year # # Entry.objects.filter(pub_date__year=2005) # Entry.objects.filter(pub_date__year__gte=2005) # month # # Entry.objects.filter(pub_date__month=12) # Entry.objects.filter(pub_date__month__gte=6) # day # # Entry.objects.filter(pub_date__day=3) # Entry.objects.filter(pub_date__day__gte=3) # week_day # # Entry.objects.filter(pub_date__week_day=2) # Entry.objects.filter(pub_date__week_day__gte=2) # hour # # Event.objects.filter(timestamp__hour=23) # Event.objects.filter(time__hour=5) # Event.objects.filter(timestamp__hour__gte=12) # minute # # Event.objects.filter(timestamp__minute=29) # Event.objects.filter(time__minute=46) # Event.objects.filter(timestamp__minute__gte=29) # second # # Event.objects.filter(timestamp__second=31) # Event.objects.filter(time__second=2) # Event.objects.filter(timestamp__second__gte=31)
浙公网安备 33010602011771号