GVKun编程网logo

Django ORM操作(django orm的操作)

9

本文将带您了解关于DjangoORM操作的新内容,同时我们还将为您解释djangoorm的操作的相关知识,另外,我们还将为您提供关于Django-Model操作和ORM操作、Django-ORM操作、

本文将带您了解关于Django ORM操作的新内容,同时我们还将为您解释django orm的操作的相关知识,另外,我们还将为您提供关于Django - Model操作 和 ORM操作、Django - ORM操作、Django - 表与ORM操作、django -orm操作总结的实用信息。

本文目录一览:

Django ORM操作(django orm的操作)

Django ORM操作(django orm的操作)

Django中集成了ORM框架,可以直接使用orm对数据库进行增删查改等操作,相对sql语句来说,orm语句更加简洁易懂,方便开发者进行开发

1.增加数据

数据库中的表有一对一关系,一对多关系和多对多关系,对于这几种关系我们有不同的方法去实现增加数据操作。

一对一关系

对于一对一关系比较简单,我们假设有一张表student,里面有student_id(学号)和name(两个属性),代码如下:

# 使用如下方法时,需要先引入数据库
from .models import Student

# 第一种方法
Student.obects.create(student_id='123456',name='lcs')

# 第二种方法
stu = Student(student_id='123456',name='lcs')
stu.save()

一对多关系

我们在student表中添加一个属性counselor,表示他的辅导员是谁,辅导员对于学生是一对多的关系

# 使用如下方法时,需要先引入数据库
from .models import Student

# 第一种方法
Student.obects.create(student_id='123456',name='lcs',counselor_id=2)

# 第二种方法
stu = Student(student_id='123456',counselor_id=2)
stu.save()

多对多关系

比如说我们在表中添加一个字段teacher,他表示这个学生的老师。显然,一个学生对应多个老师,一个老师对应多个学生,所以这个是多对多关系。

我们新建一个Teacher表,表示这个学校所有的老师

# 同样,我们需要先引入这连个表
from .models import Teacher,Student

# 获得学生和老师
stu = Student.objects.get(name='lcs')
teacher_1 = Teacher.objects.get(name='hch')
teacher_2 = Teacher.objects.get(name='hyh')

# 将两个teacher对象添加到这个学生teacher字段中
stu.teacher.add(teacher_1,teacher_2)

2.删减数据

删除操作比较简单,但是要注意级联删除操作的存在,否则会造成不可预估的后果

# 引入数据表
from .models import student

student.objects.filter(student_id='1213131').delete()

3.查找数据

关于查找数据有比较多的方法,如果只看sql语句的话,有大于,小于,大于等于,小于等于,in操作等,下面介绍一下比较基本的操作

# 引入数据库
from .models import student

# 查找所有数据
student.objects.all()

# 按条件筛选数据,没有返回为空
student.objects.filter(name='lcs')
# 返回符合条件的第一条数据
student.objects.filter(name='lcs').first()
# 返回符合条件的最后一条数据
student.objects.filter(name='lcs').last()

# 按条件返回数据,没有符合条件的数据则报错
student.objects.get(name='lcs')

# 对所有的名字去重后返回
student.objects.values('name').distinct()

下面介绍sql语句中in,>,>=,<,<=等操作

# 引入数据库
from .models import student

# 获取个数
student.objects.filter(name='seven').count()

# 大于,小于
student.objects.filter(age__gt=21)              	# 获取age大于21的值
student.objects.filter(age__gte=21)              	# 获取age大于等于21的值
student.objects.filter(age__lt=21)             		# 获取age小于21的值
student.objects.filter(age__lte=21)             	# 获取age小于21的值
student.objects.filter(age__lt=20,age__gt=18)   	# 获取age大于18 且 小于21的值

# in操作
student.objects.filter(age__in=[18,19,20])   			# 获取id等于18,20的数据
student.objects.exclude(age__in=[18,20])  			# not in

# isnull操作
student.filter(teacher__isnull=True)

# contains操作
student.objects.filter(name__contains="ven")
student.objects.filter(name__icontains="ven") 
student.objects.exclude(name__icontains="ven")		# icontains大小写不敏感

# range操作
student.objects.filter(age__range=[18,21])   		# 年龄在18和21之间的学生

# 其他类似操作
# startswith,istartswith,endswith,iendswith,# order by
student.objects.filter(age=21).order_by('student_id')    # asc
student.objects.filter(age=21).order_by('-student_id')   # desc

# group by
student.objects.filter(age=20).values('name').annotate(name=Count('name'))

# limit 、offset
student.objects.all()[10:20]

4.更新数据

# 引入数据库
from .models import student

# 第一种方法
obj = student.objects.get(student_id='121212')
obj.age = '20'
obj.save()

# 第二种方法
student.objects.filter(student_id='121212').update(age=20)

Django - Model操作 和 ORM操作

Django - Model操作 和 ORM操作

一、字段

字段列表

  1 AutoField(Field)
  2         - int自增列,必须填入参数 primary_key=True
  3 
  4     BigAutoField(AutoField)
  5         - bigint自增列,必须填入参数 primary_key=True
  6 
  7         注:当model中如果没有自增列,则自动会创建一个列名为id的列
  8         from django.db import models
  9 
 10         class UserInfo(models.Model):
 11             # 自动创建一个列名为id的且为自增的整数列
 12             username = models.CharField(max_length=32)
 13 
 14         class Group(models.Model):
 15             # 自定义自增列
 16             nid = models.AutoField(primary_key=True)
 17             name = models.CharField(max_length=32)
 18 
 19     SmallIntegerField(IntegerField):
 20         - 小整数 -3276832767
 21 
 22     PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
 23         - 正小整数 032767
 24     IntegerField(Field)
 25         - 整数列(有符号的) -21474836482147483647
 26 
 27     PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
 28         - 正整数 02147483647
 29 
 30     BigIntegerField(IntegerField):
 31         - 长整型(有符号的) -92233720368547758089223372036854775807
 32 
 33     BooleanField(Field)
 34         - 布尔值类型
 35 
 36     NullBooleanField(Field):
 37         - 可以为空的布尔值
 38 
 39     CharField(Field)
 40         - 字符类型
 41         - 必须提供max_length参数, max_length表示字符长度
 42 
 43     TextField(Field)
 44         - 文本类型
 45 
 46     EmailField(CharField):
 47         - 字符串类型,Django Admin以及ModelForm中提供验证机制
 48 
 49     IPAddressField(Field)
 50         - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
 51 
 52     GenericIPAddressField(Field)
 53         - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
 54         - 参数:
 55             protocol,用于指定Ipv4或Ipv6, ''both'',"ipv4","ipv6"
 56             unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
 57 
 58     URLField(CharField)
 59         - 字符串类型,Django Admin以及ModelForm中提供验证 URL
 60 
 61     SlugField(CharField)
 62         - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
 63 
 64     CommaSeparatedIntegerField(CharField)
 65         - 字符串类型,格式必须为逗号分割的数字
 66 
 67     UUIDField(Field)
 68         - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
 69 
 70     FilePathField(Field)
 71         - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
 72         - 参数:
 73                 path,                      文件夹路径
 74                 match=None,                正则匹配
 75                 recursive=False,           递归下面的文件夹
 76                 allow_files=True,          允许文件
 77                 allow_folders=False,       允许文件夹
 78 
 79     FileField(Field)
 80         - 字符串,路径保存在数据库,文件上传到指定目录
 81         - 参数:
 82             upload_to = ""      上传文件的保存路径
 83             storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
 84 
 85     ImageField(FileField)
 86         - 字符串,路径保存在数据库,文件上传到指定目录
 87         - 参数:
 88             upload_to = ""      上传文件的保存路径
 89             storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
 90             width_field=None,   上传图片的高度保存的数据库字段名(字符串)
 91             height_field=None   上传图片的宽度保存的数据库字段名(字符串)
 92 
 93     DateTimeField(DateField)
 94         - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
 95 
 96     DateField(DateTimeCheckMixin, Field)
 97         - 日期格式      YYYY-MM-DD
 98 
 99     TimeField(DateTimeCheckMixin, Field)
100         - 时间格式      HH:MM[:ss[.uuuuuu]]
101 
102     DurationField(Field)
103         - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
104 
105     FloatField(Field)
106         - 浮点型
107 
108     DecimalField(Field)
109         - 10进制小数
110         - 参数:
111             max_digits,小数总长度
112             decimal_places,小数位长度
113 
114     BinaryField(Field)
115         - 二进制类型
116 
117 字段列表
字段列表

 

自定义无符号整数字段

 1 class UnsignedIntegerField(models.IntegerField):
 2     def db_type(self, connection):
 3         return ''integer UNSIGNED''
 4 
 5 PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
 6     ''AutoField'': ''integer AUTO_INCREMENT'',
 7     ''BigAutoField'': ''bigint AUTO_INCREMENT'',
 8     ''BinaryField'': ''longblob'',
 9     ''BooleanField'': ''bool'',
10     ''CharField'': ''varchar(%(max_length)s)'',
11     ''CommaSeparatedIntegerField'': ''varchar(%(max_length)s)'',
12     ''DateField'': ''date'',
13     ''DateTimeField'': ''datetime'',
14     ''DecimalField'': ''numeric(%(max_digits)s, %(decimal_places)s)'',
15     ''DurationField'': ''bigint'',
16     ''FileField'': ''varchar(%(max_length)s)'',
17     ''FilePathField'': ''varchar(%(max_length)s)'',
18     ''FloatField'': ''double precision'',
19     ''IntegerField'': ''integer'',
20     ''BigIntegerField'': ''bigint'',
21     ''IPAddressField'': ''char(15)'',
22     ''GenericIPAddressField'': ''char(39)'',
23     ''NullBooleanField'': ''bool'',
24     ''OneToOneField'': ''integer'',
25     ''PositiveIntegerField'': ''integer UNSIGNED'',
26     ''PositiveSmallIntegerField'': ''smallint UNSIGNED'',
27     ''SlugField'': ''varchar(%(max_length)s)'',
28     ''SmallIntegerField'': ''smallint'',
29     ''TextField'': ''longtext'',
30     ''TimeField'': ''time'',
31     ''UUIDField'': ''char(32)'',
32 
33 自定义无符号整数字段
自定义无符号整数字段

 

注意事项

 1 1.触发Model中的验证和错误提示有两种方式:
 2         a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息
 3         b. 使用ModelForm
 4         c. 调用Model对象的 clean_fields 方法,如:
 5             # models.py
 6             class UserInfo(models.Model):
 7                 nid = models.AutoField(primary_key=True)
 8                 username = models.CharField(max_length=32)
 9 
10                 email = models.EmailField(error_messages={''invalid'': ''格式错了.''})
11 
12             # views.py
13             def index(request):
14                 obj = models.UserInfo(username=''11234'', email=''uu'')
15                 try:
16                     print(obj.clean_fields())
17                 except Exception as e:
18                     print(e)
19                 return HttpResponse(''ok'')
20 
21            # Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。
22 
23     2.Admin中修改错误提示
24         # admin.py
25         from django.contrib import admin
26         from model_club import models
27         from django import forms
28 
29 
30         class UserInfoForm(forms.ModelForm):
31             age = forms.IntegerField(initial=1, error_messages={''required'': ''请输入数值.'', ''invalid'': ''年龄必须为数值.''})
32 
33             class Meta:
34                 model = models.UserInfo
35                 # fields = (''username'',)
36                 fields = "__all__"
37                 exclude = [''title'']
38                 labels = { ''name'':''Writer'', }
39                 help_texts = {''name'':''some useful help text.'',}
40                 error_messages={ ''name'':{''max_length'':"this writer name is too long"} }
41                 widgets={''name'':Textarea(attrs={''cols'':80,''rows'':20})}
42 
43         class UserInfoAdmin(admin.ModelAdmin):
44             form = UserInfoForm
45 
46         admin.site.register(models.UserInfo, UserInfoAdmin)
47 
48 注意事项
注意事项

 

二、字段参数

null                数据库中字段是否可以为空
    db_column           数据库中字段的列名
    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''), ]
                            )

 

三、元信息

class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "table_name"

            # 联合索引
            index_together = [
                ("pub_date", "deadline"),
            ]

            # 联合唯一索引
            unique_together = (("driver", "restaurant"),)

            # admin中显示的表名称
            verbose_name

            # verbose_name加s
            verbose_name_plural

 

更多:https://docs.djangoproject.com/en/1.10/ref/models/options/

 

四、多表关系以及参数

ForeignKey(ForeignObject) # ForeignObject(RelatedField)
        to,                         # 要进行关联的表名
        to_field=None,              # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
                                        - 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(可执行对象)

                                                        def func():
                                                            return 10

                                                        class MyModel(models.Model):
                                                            user = models.ForeignKey(
                                                                to="User",
                                                                to_field="id"
                                                                on_delete=models.SET(func),)
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values(''表名__字段名'')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={''nid__gt'': 5}
                                            - limit_choices_to=lambda : {''nid__gt'': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=''root'')
        db_constraint=True          # 是否在数据库中创建外键约束
        parent_link=False           # 在Admin中是否显示关联数据


    OneToOneField(ForeignKey)
        to,                         # 要进行关联的表名
        to_field=None               # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为

                                    ###### 对于一对一 ######
                                    # 1. 一对一其实就是 一对多 + 唯一索引
                                    # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
                                    # 如下会在A表中额外增加一个c_ptr_id列且唯一:
                                            class C(models.Model):
                                                nid = models.AutoField(primary_key=True)
                                                part = models.CharField(max_length=12)

                                            class A(C):
                                                id = models.AutoField(primary_key=True)
                                                code = models.CharField(max_length=1)

    ManyToManyField(RelatedField)
        to,                         # 要进行关联的表名
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values(''表名__字段名'')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={''nid__gt'': 5}
                                            - limit_choices_to=lambda : {''nid__gt'': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=''root'')
        symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
                                    # 做如下操作时,不同的symmetrical会有不同的可选字段
                                        models.BB.objects.filter(...)

                                        # 可选字段有:code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField(''self'',symmetrical=True)

                                        # 可选字段有: bb, code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField(''self'',symmetrical=False)

        through=None,               # 自定义第三张表时,使用字段用于指定关系表
        through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
                                        from django.db import models

                                        class Person(models.Model):
                                            name = models.CharField(max_length=50)

                                        class Group(models.Model):
                                            name = models.CharField(max_length=128)
                                            members = models.ManyToManyField(
                                                Person,
                                                through=''Membership'',
                                                through_fields=(''group'', ''person''),
                                            )

                                        class Membership(models.Model):
                                            group = models.ForeignKey(Group, on_delete=models.CASCADE)
                                            person = models.ForeignKey(Person, on_delete=models.CASCADE)
                                            inviter = models.ForeignKey(
                                                Person,
                                                on_delete=models.CASCADE,
                                                related_name="membership_invites",
                                            )
                                            invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # 是否在数据库中创建外键约束
        db_table=None,              # 默认创建第三张表时,数据库中表的名称

 

五、ORM操作

基本操作

 1 # 增
 2         #
 3         # models.Tb1.objects.create(c1=''xx'', c2=''oo'')  增加一条数据,可以接受字典类型数据 **kwargs
 4 
 5         # obj = models.Tb1(c1=''xx'', c2=''oo'')
 6         # obj.save()
 7 
 8         # 查
 9         #
10         # models.Tb1.objects.get(id=123)         # 获取单条数据,不存在则报错(不建议)
11         # models.Tb1.objects.all()               # 获取全部
12         # models.Tb1.objects.filter(name=''seven'') # 获取指定条件的数据
13         # models.Tb1.objects.exclude(name=''seven'') # 获取指定条件的数据
14 
15         # 删
16         #
17         # models.Tb1.objects.filter(name=''seven'').delete() # 删除指定条件的数据
18 
19         # 改
20         # models.Tb1.objects.filter(name=''seven'').update(gender=''0'')  # 将指定条件的数据更新,均支持 **kwargs
21         # obj = models.Tb1.objects.get(id=1)
22         # obj.c1 = ''111''
23         # obj.save()                                                 # 修改单条数据
24 
25 基本操作
基本操作

 

进阶操作

 1 # 获取个数
 2         #
 3         # models.Tb1.objects.filter(name=''seven'').count()
 4 
 5         # 大于,小于
 6         #
 7         # models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值
 8         # models.Tb1.objects.filter(id__gte=1)              # 获取id大于等于1的值
 9         # models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值
10         # models.Tb1.objects.filter(id__lte=10)             # 获取id小于10的值
11         # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
12 
13         # in
14         #
15         # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
16         # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
17 
18         # isnull
19         # Entry.objects.filter(pub_date__isnull=True)
20 
21         # contains
22         #
23         # models.Tb1.objects.filter(name__contains="ven")
24         # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
25         # models.Tb1.objects.exclude(name__icontains="ven")
26 
27         # range
28         #
29         # models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
30 
31         # 其他类似
32         #
33         # startswith,istartswith, endswith, iendswith,
34 
35         # order by
36         #
37         # models.Tb1.objects.filter(name=''seven'').order_by(''id'')    # asc
38         # models.Tb1.objects.filter(name=''seven'').order_by(''-id'')   # desc
39 
40         # group by
41         #
42         # from django.db.models import Count, Min, Max, Sum
43         # models.Tb1.objects.filter(c1=1).values(''id'').annotate(c=Count(''num''))
44         # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
45 
46         # limit 、offset
47         #
48         # models.Tb1.objects.all()[10:20]
49 
50         # regex正则匹配,iregex 不区分大小写
51         #
52         # Entry.objects.get(title__regex=r''^(An?|The) +'')
53         # Entry.objects.get(title__iregex=r''^(an?|the) +'')
54 
55         # date
56         #
57         # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
58         # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))
59 
60         # year
61         #
62         # Entry.objects.filter(pub_date__year=2005)
63         # Entry.objects.filter(pub_date__year__gte=2005)
64 
65         # month
66         #
67         # Entry.objects.filter(pub_date__month=12)
68         # Entry.objects.filter(pub_date__month__gte=6)
69 
70         # day
71         #
72         # Entry.objects.filter(pub_date__day=3)
73         # Entry.objects.filter(pub_date__day__gte=3)
74 
75         # week_day
76         #
77         # Entry.objects.filter(pub_date__week_day=2)
78         # Entry.objects.filter(pub_date__week_day__gte=2)
79 
80         # hour
81         #
82         # Event.objects.filter(timestamp__hour=23)
83         # Event.objects.filter(time__hour=5)
84         # Event.objects.filter(timestamp__hour__gte=12)
85 
86         # minute
87         #
88         # Event.objects.filter(timestamp__minute=29)
89         # Event.objects.filter(time__minute=46)
90         # Event.objects.filter(timestamp__minute__gte=29)
91 
92         # second
93         #
94         # Event.objects.filter(timestamp__second=31)
95         # Event.objects.filter(time__second=2)
96         # Event.objects.filter(timestamp__second__gte=31)
97 
98 进阶操作
进阶操作

 

高级操作

 1 # extra
 2         #
 3         # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
 4         #    Entry.objects.extra(select={''new_id'': "select col from sometable where othercol > %s"}, select_params=(1,))
 5         #    Entry.objects.extra(where=[''headline=%s''], params=[''Lennon''])
 6         #    Entry.objects.extra(where=["foo=''a'' OR bar = ''a''", "baz = ''a''"])
 7         #    Entry.objects.extra(select={''new_id'': "select id from tb where id > %s"}, select_params=(1,), order_by=[''-nid''])
 8 
 9         # F
10         #
11         # from django.db.models import F
12         # models.Tb1.objects.update(num=F(''num'')+1)
13 
14 
15         # Q
16         #
17         # 方式一:
18         # Q(nid__gt=10)
19         # Q(nid=8) | Q(nid__gt=10)
20         # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=''root'')
21 
22         # 方式二:
23         # con = Q()
24         # q1 = Q()
25         # q1.connector = ''OR''
26         # q1.children.append((''id'', 1))
27         # q1.children.append((''id'', 10))
28         # q1.children.append((''id'', 9))
29         # q2 = Q()
30         # q2.connector = ''OR''
31         # q2.children.append((''c1'', 1))
32         # q2.children.append((''c1'', 10))
33         # q2.children.append((''c1'', 9))
34         # con.add(q1, ''AND'')
35         # con.add(q2, ''AND'')
36         #
37         # models.Tb1.objects.filter(con)
38 
39 
40         # 执行原生SQL
41         #
42         # from django.db import connection, connections
43         # cursor = connection.cursor()  # cursor = connections[''default''].cursor()
44         # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
45         # row = cursor.fetchone()
46 
47 高级操作
高级操作

 

其他操作

  1 ##################################################################
  2 # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
  3 ##################################################################
  4 
  5 def all(self)
  6     # 获取所有的数据对象
  7 
  8 def filter(self, *args, **kwargs)
  9     # 条件查询
 10     # 条件可以是:参数,字典,Q
 11 
 12 def exclude(self, *args, **kwargs)
 13     # 条件查询
 14     # 条件可以是:参数,字典,Q
 15 
 16 def select_related(self, *fields)
 17      性能相关:表之间进行join连表操作,一次性获取关联的数据。
 18      model.tb.objects.all().select_related()
 19      model.tb.objects.all().select_related(''外键字段'')
 20      model.tb.objects.all().select_related(''外键字段__外键字段'')
 21 
 22 def prefetch_related(self, *lookups)
 23     性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。
 24             # 获取所有用户表
 25             # 获取用户类型表where id in (用户表中的查到的所有用户ID)
 26             models.UserInfo.objects.prefetch_related(''外键字段'')
 27 
 28 
 29 
 30             from django.db.models import Count, Case, When, IntegerField
 31             Article.objects.annotate(
 32                 numviews=Count(Case(
 33                     When(readership__what_time__lt=treshold, then=1),
 34                     output_field=CharField(),
 35                 ))
 36             )
 37 
 38             students = Student.objects.all().annotate(num_excused_absences=models.Sum(
 39                 models.Case(
 40                     models.When(absence__type=''Excused'', then=1),
 41                 default=0,
 42                 output_field=models.IntegerField()
 43             )))
 44 
 45 def annotate(self, *args, **kwargs)
 46     # 用于实现聚合group by查询
 47 
 48     from django.db.models import Count, Avg, Max, Min, Sum
 49 
 50     v = models.UserInfo.objects.values(''u_id'').annotate(uid=Count(''u_id''))
 51     # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id
 52 
 53     v = models.UserInfo.objects.values(''u_id'').annotate(uid=Count(''u_id'')).filter(uid__gt=1)
 54     # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
 55 
 56     v = models.UserInfo.objects.values(''u_id'').annotate(uid=Count(''u_id'',distinct=True)).filter(uid__gt=1)
 57     # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
 58 
 59 def distinct(self, *field_names)
 60     # 用于distinct去重
 61     models.UserInfo.objects.values(''nid'').distinct()
 62     # select distinct nid from userinfo
 63 
 64     注:只有在PostgreSQL中才能使用distinct进行去重
 65 
 66 def order_by(self, *field_names)
 67     # 用于排序
 68     models.UserInfo.objects.all().order_by(''-id'',''age'')
 69 
 70 def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
 71     # 构造额外的查询条件或者映射,如:子查询
 72 
 73     Entry.objects.extra(select={''new_id'': "select col from sometable where othercol > %s"}, select_params=(1,))
 74     Entry.objects.extra(where=[''headline=%s''], params=[''Lennon''])
 75     Entry.objects.extra(where=["foo=''a'' OR bar = ''a''", "baz = ''a''"])
 76     Entry.objects.extra(select={''new_id'': "select id from tb where id > %s"}, select_params=(1,), order_by=[''-nid''])
 77 
 78  def reverse(self):
 79     # 倒序
 80     models.UserInfo.objects.all().order_by(''-nid'').reverse()
 81     # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序
 82 
 83 
 84  def defer(self, *fields):
 85     models.UserInfo.objects.defer(''username'',''id'')
 86  87     models.UserInfo.objects.filter(...).defer(''username'',''id'')
 88     #映射中排除某列数据
 89 
 90  def only(self, *fields):
 91     #仅取某个表中的数据
 92      models.UserInfo.objects.only(''username'',''id'')
 93  94      models.UserInfo.objects.filter(...).only(''username'',''id'')
 95 
 96  def using(self, alias):
 97      指定使用的数据库,参数为别名(setting中的设置)
 98 
 99 
100 ##################################################
101 # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
102 ##################################################
103 
104 def raw(self, raw_query, params=None, translations=None, using=None):
105     # 执行原生SQL
106     models.UserInfo.objects.raw(''select * from userinfo'')
107 
108     # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名
109     models.UserInfo.objects.raw(''select id as nid from 其他表'')
110 
111     # 为原生SQL设置参数
112     models.UserInfo.objects.raw(''select id as nid from userinfo where nid>%s'', params=[12,])
113 
114     # 将获取的到列名转换为指定列名
115     name_map = {''first'': ''first_name'', ''last'': ''last_name'', ''bd'': ''birth_date'', ''pk'': ''id''}
116     Person.objects.raw(''SELECT * FROM some_other_table'', translations=name_map)
117 
118     # 指定数据库
119     models.UserInfo.objects.raw(''select * from userinfo'', using="default")
120 
121     ################### 原生SQL ###################
122     from django.db import connection, connections
123     cursor = connection.cursor()  # cursor = connections[''default''].cursor()
124     cursor.execute("""SELECT * from auth_user where id = %s""", [1])
125     row = cursor.fetchone() # fetchall()/fetchmany(..)
126 
127 
128 def values(self, *fields):
129     # 获取每行数据为字典格式
130 
131 def values_list(self, *fields, **kwargs):
132     # 获取每行数据为元祖
133 
134 def dates(self, field_name, kind, order=''ASC''):
135     # 根据时间进行某一部分进行去重查找并截取指定内容
136     # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
137     # order只能是:"ASC"  "DESC"
138     # 并获取转换后的时间
139         - year : 年-01-01
140         - month: 年-月-01
141         - day  : 年-月-142 
143     models.DatePlus.objects.dates(''ctime'',''day'',''DESC'')
144 
145 def datetimes(self, field_name, kind, order=''ASC'', tzinfo=None):
146     # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
147     # kind只能是 "year", "month", "day", "hour", "minute", "second"
148     # order只能是:"ASC"  "DESC"
149     # tzinfo时区对象
150     models.DDD.objects.datetimes(''ctime'',''hour'',tzinfo=pytz.UTC)
151     models.DDD.objects.datetimes(''ctime'',''hour'',tzinfo=pytz.timezone(''Asia/Shanghai''))
152 
153     """
154     pip3 install pytz
155     import pytz
156     pytz.all_timezones
157     pytz.timezone(‘Asia/Shanghai’)
158     """
159 
160 def none(self):
161     # 空QuerySet对象
162 
163 
164 ####################################
165 # METHODS THAT DO DATABASE QUERIES #
166 ####################################
167 
168 def aggregate(self, *args, **kwargs):
169    # 聚合函数,获取字典类型聚合结果
170    from django.db.models import Count, Avg, Max, Min, Sum
171    result = models.UserInfo.objects.aggregate(k=Count(''u_id'', distinct=True), n=Count(''nid''))
172    ===> {''k'': 3, ''n'': 4}
173 
174 def count(self):
175    # 获取个数
176 
177 def get(self, *args, **kwargs):
178    # 获取单个对象
179 
180 def create(self, **kwargs):
181    # 创建对象
182 
183 def bulk_create(self, objs, batch_size=None):
184     # 批量插入
185     # batch_size表示一次插入的个数
186     objs = [
187         models.DDD(name=''r11''),
188         models.DDD(name=''r22'')
189     ]
190     models.DDD.objects.bulk_create(objs, 10)
191 
192 def get_or_create(self, defaults=None, **kwargs):
193     # 如果存在,则获取,否则,创建
194     # defaults 指定创建时,其他字段的值
195     obj, created = models.UserInfo.objects.get_or_create(username=''root1'', defaults={''email'': ''1111111'',''u_id'': 2, ''t_id'': 2})
196 
197 def update_or_create(self, defaults=None, **kwargs):
198     # 如果存在,则更新,否则,创建
199     # defaults 指定创建时或更新时的其他字段
200     obj, created = models.UserInfo.objects.update_or_create(username=''root1'', defaults={''email'': ''1111111'',''u_id'': 2, ''t_id'': 1})
201 
202 def first(self):
203    # 获取第一个
204 
205 def last(self):
206    # 获取最后一个
207 
208 def in_bulk(self, id_list=None):
209    # 根据主键ID进行查找
210    id_list = [11,21,31]
211    models.DDD.objects.in_bulk(id_list)
212 
213 def delete(self):
214    # 删除
215 
216 def update(self, **kwargs):
217     # 更新
218 
219 def exists(self):
220    # 是否有结果
221 
222 其他操作
其他操作

 

六、其他

Django原生SQL获取cursor字典

 1 import pymysql
 2     from django.db import connection, connections
 3  
 4     connection.connect()
 5     conn = connection.connection
 6     cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
 7     cursor.execute("""SELECT * from app01_userinfo""")
 8     row = cursor.fetchone()
 9     connection.close()
10 
11 Django原生SQL获取cursor字典
Django原生SQL获取cursor字典

 

数字自增、字符串更新

 1 # 数字自增
 2     from django.db.models import F
 3     models.UserInfo.objects.update(num=F(''num'') + 1)
 4 
 5     # 字符串更新
 6     from django.db.models.functions import Concat
 7     from django.db.models import Value
 8 
 9     models.UserInfo.objects.update(name=Concat(''name'', ''pwd''))
10     models.UserInfo.objects.update(name=Concat(''name'', Value(''666'')))
11 
12 数字自增、字符串更新
数字自增、字符串更新

 

ORM函数相关

 1 # ########### 基础函数 ###########
 2 
 3     # 1. Concat,用于做类型转换
 4     # v = models.UserInfo.objects.annotate(c=Cast(''pwd'', FloatField()))
 5 
 6     # 2. Coalesce,从前向后,查询第一个不为空的值
 7     # v = models.UserInfo.objects.annotate(c=Coalesce(''name'', ''pwd''))
 8     # v = models.UserInfo.objects.annotate(c=Coalesce(Value(''666''),''name'', ''pwd''))
 9 
10     # 3. Concat,拼接
11     # models.UserInfo.objects.update(name=Concat(''name'', ''pwd''))
12     # models.UserInfo.objects.update(name=Concat(''name'', Value(''666'')))
13     # models.UserInfo.objects.update(name=Concat(''name'', Value(''666''),Value(''999'')))
14 
15     # 4.ConcatPair,拼接(仅两个参数)
16     # v = models.UserInfo.objects.annotate(c=ConcatPair(''name'', ''pwd''))
17     # v = models.UserInfo.objects.annotate(c=ConcatPair(''name'', Value(''666'')))
18 
19     # 5.Greatest,获取比较大的值;least 获取比较小的值;
20     # v = models.UserInfo.objects.annotate(c=Greatest(''id'', ''pwd'',output_field=FloatField()))
21 
22     # 6.Length,获取长度
23     # v = models.UserInfo.objects.annotate(c=Length(''name''))
24 
25     # 7. Lower,Upper,变大小写
26     # v = models.UserInfo.objects.annotate(c=Lower(''name''))
27     # v = models.UserInfo.objects.annotate(c=Upper(''name''))
28 
29     # 8. Now,获取当前时间
30     # v = models.UserInfo.objects.annotate(c=Now())
31 
32     # 9. substr,子序列
33     # v = models.UserInfo.objects.annotate(c=Substr(''name'',1,2))
34 
35     # ########### 时间类函数 ###########
36     # 1. 时间截取,不保留其他:Extract, ExtractDay, ExtractHour, ExtractMinute, ExtractMonth,ExtractSecond, ExtractWeekDay, ExtractYear,
37     # v = models.UserInfo.objects.annotate(c=functions.ExtractYear(''ctime''))
38     # v = models.UserInfo.objects.annotate(c=functions.ExtractMonth(''ctime''))
39     # v = models.UserInfo.objects.annotate(c=functions.ExtractDay(''ctime''))
40     #
41     # v = models.UserInfo.objects.annotate(c=functions.Extract(''ctime'', ''year''))
42     # v = models.UserInfo.objects.annotate(c=functions.Extract(''ctime'', ''month''))
43     # v = models.UserInfo.objects.annotate(c=functions.Extract(''ctime'', ''year_month''))
44     """
45     MICROSECOND
46     SECOND
47     MINUTE
48     HOUR
49     DAY
50     WEEK
51     MONTH
52     QUARTER
53     YEAR
54     SECOND_MICROSECOND
55     MINUTE_MICROSECOND
56     MINUTE_SECOND
57     HOUR_MICROSECOND
58     HOUR_SECOND
59     HOUR_MINUTE
60     DAY_MICROSECOND
61     DAY_SECOND
62     DAY_MINUTE
63     DAY_HOUR
64     YEAR_MONTH
65     """
66 
67     # 2. 时间截图,保留其他:Trunc, TruncDate, TruncDay,TruncHour, TruncMinute, TruncMonth, TruncSecond, TruncYear
68     # v = models.UserInfo.objects.annotate(c=functions.TruncHour(''ctime''))
69     # v = models.UserInfo.objects.annotate(c=functions.TruncDate(''ctime''))
70     # v = models.UserInfo.objects.annotate(c=functions.Trunc(''ctime'',''year''))
71 
72 ORM函数相关
ORM函数相关

 

ORM自定义函数

 1 from django.db.models.functions.base import Func
 2     class CustomeFunc(Func):
 3         function = ''DATE_FORMAT''
 4         template = ''%(function)s(%(expressions)s,%(format)s)''
 5 
 6         def __init__(self, expression, **extra):
 7             expressions = [expression]
 8             super(CustomeFunc, self).__init__(*expressions, **extra)
 9 
10     v = models.UserInfo.objects.annotate(c=CustomeFunc(''ctime'',format="''%%Y-%%m''"))
11 
12 ORM自定义函数
ORM自定义函数

Django - ORM操作

Django - ORM操作

[TOC]

Django - ORM操作

一. 必知必会13条

<1> all():                 查询所有结果
 
<2> filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
 
<3> get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
 
<4> exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象
 
<5> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
 
<6> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
 
<7> order_by(*field):      对查询结果排序
 
<8> reverse():             对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。
 
<9> distinct():            从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)
 
<10> count():              返回数据库中匹配查询(QuerySet)的对象数量。
 
<11> first():              返回第一条记录
 
<12> last():               返回最后一条记录
 
<13> exists():             如果QuerySet包含数据,就返回True,否则返回False

返回QuerySet对象的方法有

  • all()

  • filter()

  • exclude()

  • order_by()

  • reverse()

  • distinct()

特殊的QuerySet

  • values() 返回一个可迭代的字典序列

  • values_list() 返回一个可迭代的元祖序列

返回具体对象的

  • get()

  • first()

  • last()

返回布尔值的方法有:

  • exists()

返回数字的方法有

  • count()

单表查询之神奇的双下划线

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")  # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
 
models.Tb1.objects.filter(id__range=[1, 3])      # id范围是1到3的,等价于SQL的bettwen and
 
类似的还有:startswith,istartswith, endswith, iendswith 

date字段还可以:
models.Class.objects.filter(first_day__year=2017)

二. ForeignKey操作

正向查找

对象查找(跨表) 语法:

对象.关联字段.字段

示例:

book_obj = models.Book.objects.first()  # 第一本书对象
print(book_obj.publisher)  # 得到这本书关联的出版社对象
print(book_obj.publisher.name)  # 得到出版社对象的名称

字段查找(跨表) 语法:

关联字段__字段

示例:

print(models.Book.objects.values_list("publisher__name"))

反向操作

对象查找 语法:

obj.表名_set

示例:

publisher_obj = models.Publisher.objects.first()  # 找到第一个出版社对象
books = publisher_obj.book_set.all()  # 找到第一个出版社出版的所有书
titles = books.values_list("title")  # 找到第一个出版社出版的所有书的书名

字段查找 语法:

表名__字段

示例:

titles = models.Publisher.objects.values_list("book__title")

三. ManyToManyField

create()

创建一个新的对象,保存对象,并将它添加到关联对象集之中,返回新创建的对象。

>>> import datetime
>>> models.Author.objects.first().book_set.create(title="番茄物语", publish_date=datetime.date.today())

add()

把指定的model对象添加到关联对象集中。

添加对象

>>> author_objs = models.Author.objects.filter(id__lt=3)
>>> models.Book.objects.first().authors.add(*author_objs)

添加id

>>> models.Book.objects.first().authors.add(*[1, 2])

set()

更新model对象的关联对象。

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.set([2, 3])

remove()

从关联对象集中移除执行的model对象

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.remove(3)

clear()

从关联对象集中移除一切对象。

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.clear()

注意:

对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。

举个例子:

ForeignKey字段没设置null=True时,

class Book(models.Model):
title = models.CharField(max_length=32)
publisher = models.ForeignKey(to=Publisher)

没有clear()和remove()方法:

>>> models.Publisher.objects.first().book_set.clear()
Traceback (most recent call last):
	File "<input>", line 1, in <module>
AttributeError: ''RelatedManager'' object has no attribute ''clear''

当ForeignKey字段设置null=True时,

class Book(models.Model):
    name = models.CharField(max_length=32)
    publisher = models.ForeignKey(to=Class, null=True)

此时就有clear()和remove()方法:

>>> models.Publisher.objects.first().book_set.clear()

注意:

对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。

四. 聚合查询和分组查询

聚合

aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。

键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。

示例:

>>> from django.db.models import Avg, Sum, Max, Min, Count
>>> models.Book.objects.all().aggregate(Avg("price"))
{''price__avg'': 13.233333}

如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

>> models.Book.objects.aggregate(average_price=Avg(''price''))
{''average_price'': 13.233333}

如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

>> models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price"))
{''price__avg'': 13.233333, ''price__max'': Decimal(''19.90''), ''price__min'': Decimal(''9.90'')}

分组

我们在这里先复习一下SQL语句的分组。

假设现在有一张公司职员表:

我们使用原生SQL语句,按照部分分组求平均工资:

select dept,AVG(salary) from employee group by dept;

ORM查询:

from django.db.models import Avg
Employee.objects.values("dept").annotate(avg=Avg("salary").values(dept, "avg")

连表查询的分组:

SQL查询:

select dept.name,AVG(salary) from employee inner join dept on (employee.dept_id=dept.id) group by dept_id;

ORM查询:

from django.db.models import Avg
models.Dept.objects.annotate(avg=Avg("employee__salary")).values("name", "avg")

五. F查询和Q查询

F查询

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

示例1:

查询评论数大于收藏数的书籍

from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F(''keep_num''))

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

models.Book.objects.filter(commnet_num__lt=F(''keep_num'')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元

models.Book.objects.all().update(price=F("price")+30)

引申:

如果要修改char字段咋办?

如:把所有书名后面加上(第一版)

>>> from django.db.models.functions import Concat
>>> from django.db.models import Value
>>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版"), Value(")")))

Q查询

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象。

示例1:

查询作者名是小仙女或小魔女的

models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))

你可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。

示例:查询作者名字是小仙女并且不是2018年出版的书的书名。

>>> models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title")
<QuerySet [(''番茄物语'',)]>

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。

例如:查询出版年份是2017或2018,书名中带物语的所有书。

>>> models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物语")
<QuerySet [<Book: 番茄物语>, <Book: 香蕉物语>, <Book: 橘子物语>]>

六. 锁和事务

select_for_update(nowait=False, skip_locked=False)

返回一个锁住行直到事务结束的查询集,如果数据库支持,它将生成一个 SELECT ... FOR UPDATE 语句。

举个例子:

entries = Entry.objects.select_for_update().filter(author=request.user)

所有匹配的行将被锁定,直到事务结束。这意味着可以通过锁防止数据被其它事务修改。

一般情况下如果其他事务锁定了相关行,那么本查询将被阻塞,直到锁被释放。 如果这不想要使查询阻塞的话,使用select_for_update(nowait=True)。 如果其它事务持有冲突的锁, 那么查询将引发 DatabaseError 异常。你也可以使用select_for_update(skip_locked=True)忽略锁定的行。 nowait和skip_locked是互斥的,同时设置会导致ValueError。

目前,postgresql,oracle和mysql数据库后端支持select_for_update()。 但是,MySQL不支持nowait和skip_locked参数。

使用不支持这些选项的数据库后端(如MySQL)将nowait=True或skip_locked=True转换为select_for_update()将导致抛出DatabaseError异常,这可以防止代码意外终止。

事务

import os

if __name__ == ''__main__'':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings")
    import django
    django.setup()

    import datetime
    from app01 import models

    try:
        from django.db import transaction
        with transaction.atomic():
            new_publisher = models.Publisher.objects.create(name="火星出版社")
            models.Book.objects.create(title="橘子物语", publish_date=datetime.date.today(), publisher_id=10)  # 指定一个不存在的出版社id
    except Exception as e:
        print(str(e))

七. Django ORM执行原生SQL

Django 提供两种方法使用原始SQL进行查询:一种是使用raw()方法,进行原始SQL查询并返回模型实例;另一种是完全避开模型层,直接执行自定义的SQL语句。

执行原生查询

raw()管理器方法用于原始的SQL查询,并返回模型的实例:

注意:raw()语法查询必须包含主键。

这个方法执行原始的SQL查询,并返回一个django.db.models.query.RawQuerySet 实例。 这个RawQuerySet 实例可以像一般的QuerySet那样,通过迭代来提供对象实例。

举个例子:

class Person(models.Model):
    first_name = models.CharField(...)
    last_name = models.CharField(...)
    birth_date = models.DateField(...)
可以像下面这样执行原生SQL语句

>>> for p in Person.objects.raw(''SELECT * FROM myapp_person''):
...     print(p)
raw()查询可以查询其他表的数据。

举个例子:

ret = models.Student.objects.raw(''select id, tname as hehe from app02_teacher'')
    for i in ret:
        print(i.id, i.hehe)
raw()方法自动将查询字段映射到模型字段。还可以通过translations参数指定一个把查询的字段名和ORM对象实例的字段名互相对应的字典

d = {''tname'': ''haha''}
    ret = models.Student.objects.raw(''select * from app02_teacher'', translations=d)
    for i in ret:
        print(i.id, i.sname, i.haha)
原生SQL还可以使用参数,注意不要自己使用字符串格式化拼接SQL语句,防止SQL注入!

d = {''tname'': ''haha''}
    ret = models.Student.objects.raw(''select * from app02_teacher where id > %s'', translations=d, params=[1,])
    for i in ret:
        print(i.id, i.sname, i.haha)

直接执行自定义SQL

有时候raw()方法并不十分好用,很多情况下我们不需要将查询结果映射成模型,或者我们需要执行DELETE、 INSERT以及UPDATE操作。在这些情况下,我们可以直接访问数据库,完全避开模型层。

我们可以直接从django提供的接口中获取数据库连接,然后像使用pymysql模块一样操作数据库。

from django.db import connection, connections
cursor = connection.cursor()  # cursor = connections[''default''].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
ret = cursor.fetchone()

Django - 表与ORM操作

Django - 表与ORM操作

Django - 表与ORM操作

一. 模板语言

  模板中也有自己的语言, 该语言可以实现数据展示

- {{  变量 }}
- 循环   
      {%  for i in  all_publisher %}
          {{ forloop.counter }}   #  当前循环的测试 
      {%  endfor %}

 

•{{ item }}
•{% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}
  forloop.counter
  forloop.first
  forloop.last 
•{% if ordered_warranty %}  {% else %} {% endif %}
•母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
   {% block title %}{% endblock %}
•帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.css">
    <link rel="stylesheet" href="/static/css/dsb.css">
</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container-fluid">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                    aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">图书管理系统</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">Dashboard</a></li>
                <li><a href="#">Settings</a></li>
                <li><a href="#">Profile</a></li>
                <li><a href="#">Help</a></li>
            </ul>
            <form class="navbar-form navbar-right">
                <input type="text" class="form-control" placeholder="Search...">
            </form>
        </div>
    </div>
</nav>

    <div class="container-fluid">
    <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
            <ul class="nav nav-sidebar">
                <li ><a href="/index/">作家列表 <span class="sr-only">(current)</span></a></li>
                <li><a href="/book_list/">书籍列表</a></li>
                <li class="active"><a href="/auth_list/">作家列表</a></li>
                <li><a href="#">Export</a></li>
            </ul>
        </div>
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">

            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">作家展示</h3>
                </div>
                <div class="panel-body">
                    <a class="btn btn-primary " href="/add_auth/">添加</a>
                    <div class="table-responsive">
                        <table class="table table-striped table-hover">
                            <thead>
                            <tr>
                                <th>序号</th>
                                <th>ID</th>
                                <th>姓名</th>
                                <th>代表作</th>
                                <th>操作</th>
                            </tr>
                            </thead>
                            <tbody>
                            {% for i in all_auth %}
                                <tr>
                                    <td>{{ forloop.counter }}</td>
                                    <td>{{ i.pk }}</td>
                                    <td>{{ i.name }}</td>
                                    <td>
                                        {% for book in i.books.all %}
                                            {{ book.title }}
                                         {% endfor %}
                                    </td>
                                    <td>
                                        <a class="btn btn-success btn-sm" href="/edit_auth/?pk={{ i.pk }}">编辑</a>
                                        <a class="btn btn-danger btn-sm" href="/del_auth/?pk={{ i.pk }}">删除</a>
                                    </td>
                                </tr>
                            {% endfor %}
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>


        </div>
    </div>
</div>

</body>
</html>
实例

 

二. 表结构

  1. 基本表结构

from django.db import models

class userinfo(models.Model):
    name = models.CharField(max_length=30)
    email = models.EmailField()
    memo = models.TextField()
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''), ]
                            )
参数
class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "table_name"

            # 联合索引
            index_together = [
                ("pub_date", "deadline"),
            ]

            # 联合唯一索引
            unique_together = (("driver", "restaurant"),)

            # admin中显示的表名称
            verbose_name

            # verbose_name加s
            verbose_name_plural
        
    更多:https://docs.djangoproject.com/en/1.10/ref/models/options/
元信息
1.触发Model中的验证和错误提示有两种方式:
        a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息
        b. 调用Model对象的 clean_fields 方法,如:
            # models.py
            class UserInfo(models.Model):
                nid = models.AutoField(primary_key=True)
                username = models.CharField(max_length=32)

                email = models.EmailField(error_messages={''invalid'': ''格式错了.''})

            # views.py
            def index(request):
                obj = models.UserInfo(username=''11234'', email=''uu'')
                try:
                    print(obj.clean_fields())
                except Exception as e:
                    print(e)
                return HttpResponse(''ok'')

           # Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。

    2.Admin中修改错误提示
        # admin.py
        from django.contrib import admin
        from model_club import models
        from django import forms


        class UserInfoForm(forms.ModelForm):
            username = forms.CharField(error_messages={''required'': ''用户名不能为空.''})
            email = forms.EmailField(error_messages={''invalid'': ''邮箱格式错误.''})
            age = forms.IntegerField(initial=1, error_messages={''required'': ''请输入数值.'', ''invalid'': ''年龄必须为数值.''})

            class Meta:
                model = models.UserInfo
                # fields = (''username'',)
                fields = "__all__"


        class UserInfoAdmin(admin.ModelAdmin):
            form = UserInfoForm


        admin.site.register(models.UserInfo, UserInfoAdmin)
拓展知识

  2. 连表结构

    一对多: models.ForeignKey(其他表)

    多对多: models.ManyToManyField(其他表)

    一对一:models.OneToOneFileld(其他表)

  应用场景:   

  • 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择) 例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。
  • 多对多:在某表中创建一行数据是,有一个可以多选的下拉框 例如:创建用户信息,需要为用户指定多个爱好
  • 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了 例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据
ForeignKey(ForeignObject) # ForeignObject(RelatedField)
        to,                         # 要进行关联的表名
        to_field=None,              # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为
                                        - 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(可执行对象)

                                                        def func():
                                                            return 10

                                                        class MyModel(models.Model):
                                                            user = models.ForeignKey(
                                                                to="User",
                                                                to_field="id"
                                                                on_delete=models.SET(func),)
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values(''表名__字段名'')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={''nid__gt'': 5}
                                            - limit_choices_to=lambda : {''nid__gt'': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=''root'')
        db_constraint=True          # 是否在数据库中创建外键约束
        parent_link=False           # 在Admin中是否显示关联数据


    OneToOneField(ForeignKey)
        to,                         # 要进行关联的表名
        to_field=None               # 要关联的表中的字段名称
        on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为

                                    ###### 对于一对一 ######
                                    # 1. 一对一其实就是 一对多 + 唯一索引
                                    # 2.当两个类之间有继承关系时,默认会创建一个一对一字段
                                    # 如下会在A表中额外增加一个c_ptr_id列且唯一:
                                            class C(models.Model):
                                                nid = models.AutoField(primary_key=True)
                                                part = models.CharField(max_length=12)

                                            class A(C):
                                                id = models.AutoField(primary_key=True)
                                                code = models.CharField(max_length=1)

    ManyToManyField(RelatedField)
        to,                         # 要进行关联的表名
        related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values(''表名__字段名'')
        limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:
                                    # 如:
                                            - limit_choices_to={''nid__gt'': 5}
                                            - limit_choices_to=lambda : {''nid__gt'': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=''root'')
        symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
                                    # 做如下操作时,不同的symmetrical会有不同的可选字段
                                        models.BB.objects.filter(...)

                                        # 可选字段有:code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField(''self'',symmetrical=True)

                                        # 可选字段有: bb, code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField(''self'',symmetrical=False)

        through=None,               # 自定义第三张表时,使用字段用于指定关系表
        through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
                                        from django.db import models

                                        class Person(models.Model):
                                            name = models.CharField(max_length=50)

                                        class Group(models.Model):
                                            name = models.CharField(max_length=128)
                                            members = models.ManyToManyField(
                                                Person,
                                                through=''Membership'',
                                                through_fields=(''group'', ''person''),
                                            )

                                        class Membership(models.Model):
                                            group = models.ForeignKey(Group, on_delete=models.CASCADE)
                                            person = models.ForeignKey(Person, on_delete=models.CASCADE)
                                            inviter = models.ForeignKey(
                                                Person,
                                                on_delete=models.CASCADE,
                                                related_name="membership_invites",
                                            )
                                            invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # 是否在数据库中创建外键约束
        db_table=None,              # 默认创建第三张表时,数据库中表的名称
字段以及参数


三.  表操作

  1. 基本操作

#
    #
    # models.Tb1.objects.create(c1=''xx'', c2=''oo'')  增加一条数据,可以接受字典类型数据 **kwargs

    # obj = models.Tb1(c1=''xx'', c2=''oo'')
    # obj.save()

    #
    #
    # models.Tb1.objects.get(id=123)         # 获取单条数据,不存在则报错(不建议)
    # models.Tb1.objects.all()               # 获取全部
    # models.Tb1.objects.filter(name=''seven'') # 获取指定条件的数据

    #
    #
    # models.Tb1.objects.filter(name=''seven'').delete() # 删除指定条件的数据

    #
    # models.Tb1.objects.filter(name=''seven'').update(gender=''0'')  # 将指定条件的数据更新,均支持 **kwargs
    # obj = models.Tb1.objects.get(id=1)
    # obj.c1 = ''111''
    # obj.save()                                                 # 修改单条数据
View Code

 

  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)
View Code

 

  3. 其他操作

# extra
    #
    # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    #    Entry.objects.extra(select={''new_id'': "select col from sometable where othercol > %s"}, select_params=(1,))
    #    Entry.objects.extra(where=[''headline=%s''], params=[''Lennon''])
    #    Entry.objects.extra(where=["foo=''a'' OR bar = ''a''", "baz = ''a''"])
    #    Entry.objects.extra(select={''new_id'': "select id from tb where id > %s"}, select_params=(1,), order_by=[''-nid''])

    # F
    #
    # from django.db.models import F
    # models.Tb1.objects.update(num=F(''num'')+1)


    # Q
    #
    # 方式一:
    # Q(nid__gt=10)
    # Q(nid=8) | Q(nid__gt=10)
    # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=''root'')
    # 方式二:
    # con = Q()
    # q1 = Q()
    # q1.connector = ''OR''
    # q1.children.append((''id'', 1))
    # q1.children.append((''id'', 10))
    # q1.children.append((''id'', 9))
    # q2 = Q()
    # q2.connector = ''OR''
    # q2.children.append((''c1'', 1))
    # q2.children.append((''c1'', 10))
    # q2.children.append((''c1'', 9))
    # con.add(q1, ''AND'')
    # con.add(q2, ''AND'')
    #
    # models.Tb1.objects.filter(con)


    # 执行原生SQL
    #
    # from django.db import connection, connections
    # cursor = connection.cursor()  # cursor = connections[''default''].cursor()
    # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    # row = cursor.fetchone()
View Code

 

  4. 连表操作

    利用下划线和_set将表之间的操作连接起来

class UserProfile(models.Model):
    user_info = models.OneToOneField(''UserInfo'')
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)

    def __unicode__(self):
        return self.username


class UserInfo(models.Model):
    user_type_choice = (
        (0, u''普通用户''),
        (1, u''高级用户''),
    )
    user_type = models.IntegerField(choices=user_type_choice)
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    address = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name


class UserGroup(models.Model):

    caption = models.CharField(max_length=64)

    user_info = models.ManyToManyField(''UserInfo'')

    def __unicode__(self):
        return self.caption


class Host(models.Model):
    hostname = models.CharField(max_length=64)
    ip = models.GenericIPAddressField()
    user_group = models.ForeignKey(''UserGroup'')

    def __unicode__(self):
        return self.hostname
表结构实例
user_info_obj = models.UserInfo.objects.filter(id=1).first()
print user_info_obj.user_type
print user_info_obj.get_user_type_display()
print user_info_obj.userprofile.password
 
user_info_obj = models.UserInfo.objects.filter(id=1).values(''email'', ''userprofile__username'').first()
print user_info_obj.keys()
print user_info_obj.values()
一对一操作
类似一对一
1、搜索条件使用 __ 连接
2、获取值时使用 .    连接
一对多
user_info_obj = models.UserInfo.objects.get(name=u''武沛齐'')
user_info_objs = models.UserInfo.objects.all()
 
group_obj = models.UserGroup.objects.get(caption=''CEO'')
group_objs = models.UserGroup.objects.all()
 
# 添加数据
#group_obj.user_info.add(user_info_obj)
#group_obj.user_info.add(*user_info_objs)
 
# 删除数据
#group_obj.user_info.remove(user_info_obj)
#group_obj.user_info.remove(*user_info_objs)
 
# 添加数据
#user_info_obj.usergroup_set.add(group_obj)
#user_info_obj.usergroup_set.add(*group_objs)
 
# 删除数据
#user_info_obj.usergroup_set.remove(group_obj)
#user_info_obj.usergroup_set.remove(*group_objs)
 
# 获取数据
#print group_obj.user_info.all()
#print group_obj.user_info.all().filter(id=1)
 
# 获取数据
#print user_info_obj.usergroup_set.all()
#print user_info_obj.usergroup_set.all().filter(caption=''CEO'')
#print user_info_obj.usergroup_set.all().filter(caption=''DBA'')
多对多

 

  扩展:

    a.自定义上传

def upload_file(request):
    if request.method == "POST":
        obj = request.FILES.get(''fafafa'')
        f = open(obj.name, ''wb'')
        for chunk in obj.chunks():
            f.write(chunk)
        f.close()
    return render(request, ''file.html'')
View Code

 

    b.Form上传文件实例

class FileForm(forms.Form):
    ExcelFile = forms.FileField()
from
from django.db import models

class UploadFile(models.Model):
    userid = models.CharField(max_length = 30)
    file = models.FileField(upload_to = ''./upload/'')
    date = models.DateTimeField(auto_now_add=True)
Model
def UploadFile(request):
    uf = AssetForm.FileForm(request.POST,request.FILES)
    if uf.is_valid():
            upload = models.UploadFile()
            upload.userid = 1
            upload.file = uf.cleaned_data[''ExcelFile'']
            upload.save()
            
            print upload.file
View Code

 四. ORM

  1. ORM的对应关系

    类 -> 表

    对象 -> 记录(数据行)

    属性 -> 字段

  2. ORM操作

    a. 查询

1. models.Publisher(既类名).objects.all()    #查询所有的数据 -> 对象列表
2. models.(类名).objects.get(条件)    #获取满足条件的一个对象 -> 单独的对象
3. models.(类名).objects.filter()    #获取满足条件的所有对象 -> 对象列表
4. models.(类名).objects.all().order_by(''id'')    排序 ->对象列表
5. pub_obj(既主键对象的类名).pk    ->主键
6. pub_obj.name
7. 外键
    book_obj(既设置了外键被的表的获取的对象).publisher    -> 关联的对象
    book_obj.publisher_id    -> 从book表中获取关联对象的ID
    book_obj.publisher.name    -> 关联的对象的属性
8. 多对多
    author_obj.books    -> 管理对象
    author_obj.books.all()    -> 关联的所有的对象 对象列表
    book_obj.author_set    -> 管理对象

      b.增加

1. models.Publisher.objects.create(name=''xx'')    -> 对象
2. 外键
    models.Book.objects.create(name=''xxx'', publisher=pub_obj)
    models.Book.objexts.create)name=''xxx'', publisher_id=pub_obj.id)
3. 多对多
    models.Author.object.create(name=''xxxx'')    ->author_obj
    author_obj.book.set([多个要关联的对象])
    author_obj.book.set([多个要关联的对象的id])

      c.删除

1. models.Author.objects.get(id=1).delete()
2. models.Author.objects.filter(id=1).delect()

      d.修改

1. pub_obj.name=''new_xxx''
2. pub_obj.save()
3. 外键
    book_obj.title = ''xxx''
    book_obj.publisher = pub_obj 或者book_obj.publisher_id=pub_obj.id
    book_obj.save()
4. 多对多
    author_obj.name=''new_name''
    author_obj.save()
    author_obj.book.set([多个要关联对象]) 或 author_obj.book.set([多个要关联对象的id]) 
from django.shortcuts import render,redirect,HttpResponse
from cou_sele import models
# Create your views here.

def classes(request):
    all_class = models.Classes.objects.all().order_by(''cid'')
    return render(request, ''class_list.html'', {''all_class'':all_class})
def add_classes(request):
    err_msg, obj = '''', ''''
    if request.method == ''POST'':
        new_name = request.POST.get(''classes_name'')
        if not new_name:
            err_msg = ''兄弟,空的啊''
        obj = models.Classes.objects.filter(name=''new_name'')
        if obj:
            err_msg = ''兄弟,重复了''
        if new_name and not obj:
            models.Classes.objects.create(name=new_name)
            return redirect(''/class_list'')
    return render(request, ''add_classes.html'', {''err_msg'':err_msg})
def del_classes(request):
    pk = request.GET.get(''pk'')
    if not models.Classes.objects.filter(pk=pk):
        return HttpResponse(''数据不存在'')
    models.Classes.objects.get(pk=pk).delete()
    return redirect(''/class_list/'')
def edit_classes(request):
    err_msg = ''''
    pk = request.GET.get(''pk'')
    obj_list = models.Classes.objects.filter(pk=pk)
    if not obj_list:
        return HttpResponse("数据不存在")

    obj = obj_list[0]
    if request.method == ''POST'':
        new_name = request.POST.get(''classes_name'')
        if not new_name:
            err_msg = ''不能为空''
        exist = models.Classes.objects.filter(name=new_name)
        if exist:
            err_msg = ''已存在''
        if new_name and not exist:
            # 修改出版社的名称
            obj.name = new_name
            obj.save()  # 向数据库提交
            return redirect(''/class_list/'')
    return render(request, ''edit_classes.html'', {''obj'': obj, ''err_msg'': err_msg})

def studet_list(request):
    all_student = models.Student.objects.all()
    return render(request, ''studet_list.html'', {''all_student'': all_student})
def add_student(request):
    err_msg, obj = '''', ''''
    if request.method == ''POST'':
        new_name = request.POST.get(''student_name'')
        if not new_name:
            err_msg = ''兄弟,空的啊''
        obj = models.Classes.objects.filter(name=''new_name'')
        if obj:
            err_msg = ''兄弟,重复了''
        if new_name and not obj:
            models.Classes.objects.create(name=new_name)
            return redirect(''/class_list'')
    all_class = models.Classes.objects.all()
    return render(request, ''add_student.html'', {''all_class'': all_class, ''err_msg'': err_msg})
def del_student(request):
    pk = request.GET.get(''pk'')
    if not models.Classes.objects.filter(pk=pk):
        return HttpResponse(''数据不存在'')
    models.Classes.objects.get(pk=pk).delete()
    return redirect(''/student_list/'')
def edit_student(request):
    err_msg = ''''
    pk = request.GET.get(''pk'')
    student_obj = models.Student.objects.get(pk=pk)
    if not student_obj:
        return HttpResponse(''数据不存在'')
    if request.method == ''POST'':
        new_name = request.POST.get(''new_name'')

        classes_id = request.POST.get(''classes_id'')
        if not new_name:
            err_msg = ''不能为空''
        exist = models.Student.objects.filter(name=new_name)
        if exist:
            err_msg = ''你瞎啊, 已经有了''

        if new_name and not exist:
            student_obj.name = new_name
            student_obj.classes_id = classes_id
            student_obj.save()
            return redirect(''/studet_list/'')

    all_classes = models.Classes.objects.all()
    return render(request, ''edit_student.html'', {''err_msg'': err_msg, ''student_obj'': student_obj, ''all_classes'':all_classes})

def teacher_list(request):
    all_teacher = models.Teacher.objects.all()
    all_student = models.Student.objects.all()
    return render(request, ''teacher_list.html'', {''all_teacher'': all_teacher,''all_student'':all_student})
def add_teacher(request):
    err_msg = ''''
    if request.method == ''POST'':
        new_name = request.POST.get(''new_name'')
        student_ids = request.POST.getlist(''stu'')
        if not new_name:
            err_msg = ''瞎啊,空的''
        obj_new_name = models.Teacher.objects.filter(name=new_name)
        if obj_new_name:
            err_msg = ''瞎啊,重复了''
        if new_name and not obj_new_name:
            author_obj = models.Teacher.objects.create(name=new_name)
            author_obj.Student.set(student_ids)
            return redirect(''/teacher_list/'')

    all_student = models.Student.objects.all()
    return render(request, ''add_teacher.html'', {''all_student'': all_student, ''err_msg'': err_msg})
def del_teacher(request):
    del_id = request.GET.get(''pk'')
    models.Teacher.objects.get(pk = del_id).delete()
    return redirect(''/teacher_list/'')
def edit_teacher(request):
        err_msg = ''''
        pk = request.GET.get(''pk'')
        teacher_obj = models.Teacher.objects.get(pk=pk)
        if request.method == ''POST'':
            name = request.POST.get(''new_name'')
            student_ids = request.POST.getlist(''student_id'')
            if not name:
                err_msg = ''空的''
            else:
                teacher_obj.name = name
                teacher_obj.save()
                teacher_obj.Student.set(student_ids)
                return redirect(''/teacher_list/'')


        all_student = models.Student.objects.all()

        return render(request, ''edit_teacher.html'', {''err_msg'':err_msg,''author_obj'': teacher_obj, ''all_student'': all_student})
实例

五. request
  1. request.method  ->请求方式一共有8种 主要的有 GET/POST

  2. request.GET  -> url的参数 xxx/?id=1&name=konghui

   request.GET.get(''id'')

</thead>
                            <tbody>
                            {% for i in all_teacher %}
                                <tr>
                                    <td>{{ forloop.counter }}</td>
                                    <td>{{ i.pk }}</td>
                                    <td>{{ i.name }}</td>
                                    <td>
                                        {% for book in i.Student.all %}
                                            {{ book.name }}
                                        {% endfor %}
                                    </td>
                                    <td>
                                        <a class="btn btn-success btn-sm" href="/edit_teacher/?pk={{ i.pk }}">编辑</a>
                                        <a class="btn btn-danger btn-sm" href="/del_teacher/?pk={{ i.pk }}">删除</a>
                                    </td>
                                </tr>
                            {% endfor %}
实例

  3.request.POST  -> form表单提交的POST的数据{}

六.函数的返回值

  1. HttpRequest(''字符串'')  -> 返回字符串  

  2. render(request, ''模板的文件名'', {k1:v1})  -> 返回一个完整的页面

  3. request.POST(/''跳转的地址''/)  -> 重定向 响应头 location: ''跳转的地址''

    

    

  

django -orm操作总结

django -orm操作总结

前言

Django框架功能齐全自带数据库操作功能,本文主要介绍Django的ORM框架

 

到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:

  • 创建数据库,设计表结构和字段
  • 使用 MySQLdb 来连接数据库,并编写数据访问层代码
  • 业务逻辑层去调用数据访问层执行数据库操作

 

ORM是什么?:(在django中,根据代码中的类自动生成数据库的表也叫--code first)

ORM:Object Relational Mapping(关系对象映射)

类名对应------》数据库中的表名

类属性对应---------》数据库里的字段

类实例对应---------》数据库表里的一行数据

obj.id  obj.name.....类实例对象的属性

 

Django orm的优势:

Django的orm操作本质上会根据对接的数据库引擎,翻译成对应的sql语句;所有使用Django开发的项目无需关心程序底层使用的是MySQL、Oracle、sqlite....,如果数据库迁移,只需要更换Django的数据库引擎即可;

 

一、Django连接MySQL

 

1、创建数据库 (注意设置 数据的字符编码)

由于Django自带的orm是data_first类型的ORM,使用前必须先创建数据库

create database day70 default character set utf8 collate utf8_general_ci;


2、修改project中的settings.py文件中设置  连接 MySQL数据库(Django默认使用的是sqllite数据库)

复制代码
DATABASES = {
    ''default'': {
    ''ENGINE'': ''django.db.backends.mysql'',
    ''NAME'':''day70'',
    ''USER'': ''eric'',
    ''PASSWORD'': ''123123'',
    ''HOST'': ''192.168.182.128'',
    ''PORT'': ''3306'',
    }
}
复制代码

 

扩展:查看orm操作执行的原生SQL语句

在project中的settings.py文件增加

复制代码
LOGGING = {
    ''version'': 1,
    ''disable_existing_loggers'': False,
    ''handlers'': {
        ''console'':{
            ''level'':''DEBUG'',
            ''class'':''logging.StreamHandler'',
        },
    },
    ''loggers'': {
        ''django.db.backends'': {
            ''handlers'': [''console''],
            ''propagate'': True,
            ''level'':''DEBUG'',
        },
    }
}
复制代码

 

3、修改project 中的__init__py 文件设置 Django默认连接MySQL的方式

import pymysql
pymysql.install_as_MySQLdb()

 

4、setings文件注册APP

复制代码
INSTALLED_APPS = [
    ''django.contrib.admin'',
    ''django.contrib.auth'',
    ''django.contrib.contenttypes'',
    ''django.contrib.sessions'',
    ''django.contrib.messages'',
    ''django.contrib.staticfiles'',
    ''app01.apps.App01Config'',
   
]
复制代码

 5、models.py创建表

 

6、进行数据迁移

6.1、在winds cmd或者Linux shell的项目的manage.py目录下执行

python manage.py makemigrations  #根据app下的migrations目录中的记录,检测当前model层代码是否发生变化?

python manage.py migrate         #把orm代码转换成sql语句去数据库执行
python manage.py migrate --fake    #只记录变化,不提交数据库操作


 

扩展:修改表结构之后常见报错

 

这个报错:因为表创建之时,新增字段既没有设置默认值,也没有设置新增字段可为空,去对应原有数据导致;

2中解决方法:

 

1.设置新增字段可以为空

    startdate = models.CharField(max_length=255, verbose_name="任务开始时间",null=True, blank=True)
    Handledate = models.CharField(max_length=255, verbose_name="开始处理时间",null=True, blank=True)
    Handledone = models.CharField(max_length=255, verbose_name="处理完毕时间", null=True, blank=True)
    enddate = models.CharField(max_length=255, verbose_name="任务结束时间",null=True, blank=True)
    WorkTime_cost=models.CharField(max_length=255,verbose_name=''工作耗时'',null=True, blank=True)

 

2.设置新增字段默认值为 当前时间

Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type ''exit'' to exit this prompt
>>> timezone.now()

3.更多问题

python manage.py makemigrations :把你写在models中的代码翻译成增、删、改的 SQL 语句;

python manage.py migrate;讲python manage.py makemigrations翻译的SQL语句去数据库执行; 

python manage.py migrate --fake;假设 migrate 把所有SQL语句执行成功了;

我在使用Django构建表结构的时候很长一段时间都是没有了解以上3条语句的执行意义,所有经常在修改表结构之后出现报错;

出现报错的原因:

无非就是   makemigrations翻译的 SQL,跟数据库里面真实的表结构 相互冲突,增加、删除不了表、外键关系;

所以遇到报错 你应该先把model中的代码注释掉-----》python manage.py migrate --fake------》python manage.py makemigrations

去数据库把已经存在的表、外键删掉(确保数据库目前的状态,可以让makemigrations翻译出来的SQL语句在数据库里执行成功;然后migrate)--------》 python manage.py migrate;

 

 

7.设置pycharm可视化MySQL

 

 

 

 

 

 

 

二、modles.py创建表

 

ORM字段介绍

Djan提供了很多字段类型,比如URL/Email/IP/ 但是mysql数据没有这些类型,这类型存储到数据库上本质是字符串数据类型,其主要目的是为了封装底层SQL语句;

 

1、字符串类(以下都是在数据库中本质都是字符串数据类型,此类字段只是在Django自带的admin中生效)

name=models.CharField(max_length=32)
复制代码
EmailField(CharField):
IPAddressField(Field)
URLField(CharField)
SlugField(CharField)
UUIDField(Field)
FilePathField(Field)
FileField(Field)
ImageField(FileField)
CommaSeparatedIntegerField(CharField)
复制代码

 扩展

models.CharField  对应的是MySQL的varchar数据类型

char 和 varchar的区别 :

char和varchar的共同点是存储数据的长度,不能 超过max_length限制,

不同点是varchar根据数据实际长度存储,char按指定max_length()存储数据;所有前者更节省硬盘空间;

 

2、时间字段

models.DateTimeField(null=True)

date=models.DateField()

 

3、数字字段

(max_digits=30,decimal_places=10)总长度30小数位 10位)

数字:
num = models.IntegerField()
num = models.FloatField() 浮点
price=models.DecimalField(max_digits=8,decimal_places=3) 精确浮点

 

4、枚举字段

 choice=(
        (1,''男人''),
        (2,''女人''),
        (3,''其他'')
    )
lover=models.IntegerField(choices=choice) #枚举类型

 

扩展

在数据库存储枚举类型,比外键有什么优势?

1、无需连表查询性能低,省硬盘空间(选项不固定时用外键)
2、在modle文件里不能动态增加(选项一成不变用Django的choice)

    

其他字段

复制代码
db_index = True 表示设置索引
unique(唯一的意思) = True 设置唯一索引

联合唯一索引
class Meta:
unique_together = (
 (''email'',''ctime''),
)
联合索引(不做限制)
index_together = (
(''email'',''ctime''),
)
ManyToManyField(RelatedField)  #多对多操作


复制代码

 

字段参数介绍

1.数据库级别生效

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)
        - 二进制类型

字段

2、Django admin级别生效

针对 dango_admin生效的参数(正则匹配)(使用Django admin就需要关心以下参数!!))
blanke (是否为空)
editable=False 是否允许编辑

help_text="提示信息"提示信息
choices=choice 提供下拉框
error_messages="错误信息" 错误信息

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''), ]

三、ORM单表操作

0、orm操作前戏

orm使用方式:

orm操作可以使用类实例化,obj.save的方式,也可以使用create()的形式

 

QuerySet数据类型介绍

QuerySet与惰性机制

所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。

QuerySet特点:

       <1>  可迭代的 

       <2>  可切片

    <3>惰性计算和缓存机制

 

def queryset(request):
    books=models.Book.objects.all()[:10]  #切片 应用分页
    books = models.Book.objects.all()[::2]
    book= models.Book.objects.all()[6]    #索引
    print(book.title)
    for obj in books:                     #可迭代
        print(obj.title)
    books=models.Book.objects.all()          #惰性计算--->等于一个生成器,不应用books不会执行任何SQL操作
    # query_set缓存机制1次数据库查询结果query_set都会对应一块缓存,再次使用该query_set时,不会发生新的SQL操作;
    #这样减小了频繁操作数据库给数据库带来的压力;
    authors=models.Author.objects.all()
    for author in  authors:
        print(author.name)
    print(''-------------------------------------'')
    models.Author.objects.filter(id=1).update(name=''张某'')
    for author in  authors:
        print(author.name)
    #但是有时候取出来的数据量太大会撑爆缓存,可以使用迭代器优雅得解决这个问题;
    models.Publish.objects.all().iterator()
    return HttpResponse(''OK'')

增加和查询操作

def orm(request):
    orm2添加一条记录的方法
    单表
    1、表.objects.create()
    models.Publish.objects.create(name=''浙江出版社'',addr="浙江.杭州")
    models.Classify.objects.create(category=''武侠'')
    models.Author.objects.create(name=''金庸'',sex=''男'',age=89,university=''东吴大学'')
    2、类实例化:obj=类(属性=XX) obj.save()
    obj=models.Author(name=''吴承恩'',age=518,sex=''男'',university=''龙溪学院'')
    obj.save()
    
    1对多
    1、表.objects.create()
    models.Book.objects.create(title=''笑傲江湖'',price=200,date=1968,classify_id=6, publish_id=6)
    2、类实例化:obj=类(属性=X,外键=obj)obj.save()
    classify_obj=models.Classify.objects.get(category=''武侠'')
    publish_obj=models.Publish.objects.get(name=''河北出版社'')
    注意以上获取得是和 book对象 向关联的(外键)的对象
    book_obj=models.Book(title=''西游记'',price=234,date=1556,classify=classify_obj,publish=publish_obj)
    book_obj.save()
    
    多对多
    如果两表之间存在双向1对N关系,就无法使用外键来描述其关系了;
    只能使用多对多的方式,新增第三张表关系描述表;
    book=models.Book.objects.get(title=''笑傲江湖'')
    author1=models.Author.objects.get(name=''金庸'')
    author2=models.Author.objects.get(name=''张根'')
    book.author.add(author1,author2)

    书籍和作者是多对多关系,
    切记:如果两表之间存在多对多关系,例如书籍相关的所有作者对象集合,作者也关联的所有书籍对象集合
    book=models.Book.objects.get(title=''西游记'')
    author=models.Author.objects.get(name=''吴承恩'')
    author2 = models.Author.objects.get(name=''张根'')
    book.author.add(author,author2)
    #add()   添加
    #clear() 清空
    #remove() 删除某个对象
    return HttpResponse(''OK'')

根据条件判断,增加?更新?

# 根据user=user去查找,如果找到更新 如果没有找到创建defaults={} 中的数据
            tk = gen_tcoken(username)
            models.Token.objects.update_or_create(user=user, defaults={''token'': tk})

级联删除
为防止读者跑路,不再赘述!

# 修改方式1 update()
    models.Book.objects.filter(id=1).update(price=3)

    #修改方式2 obj.save() 
    book_obj=models.Book.objects.get(id=1)
    book_obj.price=5
    book_obj.save()

def ormquery(request):
    books=models.Book.objects.all()                               #------query_set对象集合 [对象1、对象2、.... ]
    books=models.Book.objects.filter(id__gt=2,price__lt=100) 
    book=models.Book.objects.get(title__endswith=''金'')            #---------单个对象,没有找到会报错
    book1 = models.Book.objects.filter(title__endswith=''金'').first()
    book2 = models.Book.objects.filter(title__icontains=''瓶'').last()
    books=models.Book.objects.values(''title'',''price'',             #-------query_set字典集合 [{一条记录},{一条记录} ]
                                    ''publish__name'',
                                    ''date'',
                                    ''classify__category'',         #切记 正向连表:外键字段___对应表字段
                                    ''author__name'',               #反向连表: 小写表名__对应表字段
                                    ''author__sex'',                #区别:正向 外键字段__,反向 小写表名__
                                    ''author__age'',
                                    ''author__university'')

    books=models.Book.objects.values(''title'',''publish__name'').distinct()  
                                                                  #exclude 按条件排除。。。
                                                                  #distinct()去重, exits()查看数据是否存在? 返回 true 和false
    a=models.Book.objects.filter(title__icontains=''金'').  
    return HttpResponse(''OK'')

连表查询

反向连表查询:
    1、通过object的形式反向连表, obj.小写表名_set.all()
    publish=models.Publish.objects.filter(name__contains=''湖南'').first()
    books=publish.book_set.all()
    for book in  books:
        print(book.title)
    通过object的形式反向绑定外键关系
    authorobj = models.Author.objects.filter(id=1).first()
    objects = models.Book.objects.all()
    authorobj.book_set.add(*objects)
    authorobj.save()
    
    2、通过values双下滑线的形式,objs.values("小写表名__字段")
    注意对象集合调用values(),正向查询是外键字段__XX,而反向是小写表名__YY看起来比较容易混淆;
    books=models.Publish.objects.filter(name__contains=''湖南'').values(''name'',''book__title'')
    authors=models.Book.objects.filter(title__icontains=''我的'').values(''author__name'')
    print(authors)
    fifter()也支持__小写表名语法进行连表查询:在publish标查询 出版过《笑傲江湖》的出版社
    publishs=models.Publish.objects.filter(book__title=''笑傲江湖'').values(''name'')
    print(publishs)
    查询谁(哪位作者)出版过的书价格大于200元
    authors=models.Author.objects.filter(book__price__gt=200).values(''name'')
    print(authors)
    通过外键字段正向连表查询,出版自保定的书籍;
    city=models.Book.objects.filter(publish__addr__icontains=''保定'').values(''title'')
    print(city)

1、基本操作

# 增
    #
    # models.Tb1.objects.create(c1=''xx'', c2=''oo'')  增加一条数据,可以接受字典类型数据 **kwargs

    # obj = models.Tb1(c1=''xx'', c2=''oo'')
    # obj.save()

    # 查
    #
    # models.Tb1.objects.get(id=123)         # 获取单条数据,不存在则报错(不建议)
    # models.Tb1.objects.all()               # 获取全部
    # models.Tb1.objects.filter(name=''seven'') # 获取指定条件的数据

    # 删
    #
    # models.Tb1.objects.filter(name=''seven'').delete() # 删除指定条件的数据

    # 改
    # models.Tb1.objects.filter(name=''seven'').update(gender=''0'')  # 将指定条件的数据更新,均支持 **kwargs
    # obj = models.Tb1.objects.get(id=1)
    # obj.c1 = ''111''
    # obj.save()                                                 # 修改单条数据

基本操作

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)

进阶操作

3、其他操作(执行原生SQL)

# 执行原生SQL

   1.执行自定义SQL
    # from django.db import connection, connections
    # cursor = connection.cursor()  # cursor = connections[''default''].cursor()
    # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    # row = cursor.fetchone()

  2.使用extra方法 
    #
    # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    #    Entry.objects.extra(select={''new_id'': "select col from sometable where othercol > %s"}, select_params=(1,))
    #    Entry.objects.extra(where=[''headline=%s''], params=[''Lennon''])
    #    Entry.objects.extra(where=["foo=''a'' OR bar = ''a''", "baz = ''a''"])
    #    Entry.objects.extra(select={''new_id'': "select id from tb where id > %s"}, select_params=(1,), order_by=[''-nid''])

   3.使用raw方法
  解释:执行原始sql并返回模型
  说明:依赖model多用于查询
  用法:
    book = Book.objects.raw("select * from hello_book")
    for item in book:
      print(item.title)
https://www.cnblogs.com/413xiaol/p/6504856.html

    # F
    #
    # from django.db.models import F
    # models.Tb1.objects.update(num=F(''num'')+1)


    # Q
    #
    # 方式一:
    # Q(nid__gt=10)
    # Q(nid=8) | Q(nid__gt=10)
    # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption=''root'')
    # 方式二:
    # con = Q()
    # q1 = Q()
    # q1.connector = ''OR''
    # q1.children.append((''id'', 1))
    # q1.children.append((''id'', 10))
    # q1.children.append((''id'', 9))
    # q2 = Q()
    # q2.connector = ''OR''
    # q2.children.append((''c1'', 1))
    # q2.children.append((''c1'', 10))
    # q2.children.append((''c1'', 9))
    # con.add(q1, ''AND'')
    # con.add(q2, ''AND'')
    #
    # models.Tb1.objects.filter(con)

四、ORM连表操作

我们在学习django中的orm的时候,我们可以把一对多,多对多,分为正向和反向查找两种方式。

正向查找:ForeignKey在 UserInfo表中,如果从UserInfo表开始向其他的表进行查询,这个就是正向操作,反之如果从UserType表去查询其他的表这个就是反向操作。

  • 一对多:models.ForeignKey(其他表)
  • 多对多:models.ManyToManyField(其他表)
  • 一对一:models.OneToOneField(其他表)

正向连表操作总结:

所谓正、反向连表操作的认定无非是Foreign_Key字段在哪张表决定的,

Foreign_Key字段在哪张表就可以哪张表使用Foreign_Key字段连表,反之没有Foreign_Key字段就使用与其关联的 小写表名;

1对多:对象.外键.关联表字段,values(外键字段__关联表字段)

多对多:外键字段.all()

反向连表操作总结:

 通过value、value_list、fifter 方式反向跨表:小写表名__关联表字段

通过对象的形式反向跨表:小写表面_set().all()

 

data: JSON.stringify({
                "table": "Functions",
                "action": "select_hosts",
                "db_type": data_type
            }),
# 添加权限时 select标签 联动 选择数据
permit_option_dict = {
    "DB_info": {"actions": {
        "select_db_type": {"args": [''select_db_type''], "filter": ["database_type"],
                           "values": [''id'', ''host'', ''port'', ''instance_nikename'']},
        "unique_alias": {"args": [''database_type'', "unique_alias"],
                         "filter": ["database_type", "instance_nikename__icontains"],
                         "values": [''id'', ''host'', ''port'', ''instance_nikename'']},
    }},
    "Functions": {"actions": {
        "select_hosts": {"args": ["db_type"], "filter": ["sql_type"], "values": [''id'', ''sql'']},
        "uniquefunction": {"args": [''select_db_type'', "uniquefunction"], "filter": ["sql_type", "sql__icontains"],
                           "values": [''id'', ''sql'']}
    }
    }

}


class Linkage(object):  # 根据配置返回数据库数据
    def __init__(self, request, model):
        self.data = json.loads(request.body)
        self.model = model
        self.action = self.data.get("action")
        self.table = self.data.get(''table'')

    def get_data(self):
        self.current_option_table = permit_option_dict.get(self.table).get("actions").get(self.action)  # 当前操作的表
        self.current_args_list = self.current_option_table.get(''args'')  # request传来的参数有哪些
        self.current_sql_value = self.current_option_table.get(''values'')  # query_set.value(值)
        self.current_args_filter_args = self.current_option_table.get(''filter'')
        self.current_args_filter_value = [self.data.get(i) for i in self.current_args_list]
        self.filter = dict(zip(self.current_args_filter_args, self.current_args_filter_value))
        data = list(getattr(self.model, self.table).objects.filter(**self.filter).values(*self.current_sql_value))
        return json.dumps(data)

根据前端参数,返回不同数据库结果

应用场景:

一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)

例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。

多对多:在某表中创建一行数据是,有一个可以多选的下拉框

例如:创建用户信息,需要为用户指定多个爱好

 

 

一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了

例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据

 

 

1、1对多

如果A表的1条记录对应B表中N条记录成立,两表之间就是1对多关系;在1对多关系中 A表就是主表,B表为子表,ForeignKey字段就建在子表;

如果B表的1条记录也对应A表中N条记录,两表之间就是双向1对多关系,也称为多对多关系;

 

在orm中设置如果 A表设置了外键字段user=models.ForeignKey(''UserType'')到B表(注意外键表名加引号)

就意味着 写在写A表的B表主键, (一列),代表B表的多个(一行)称为1对多,

查询

总结:利用orm获取 数据库表中多个数据

获取到的数据类型本质上都是 queryset类型,
类似于列表,
内部有3种表现形式(对象,字典,列表)

modle.表名.objects.all()
modle.表名.objects.values()
modle.表名.objects.values()

 

跨表

 正操作

 

所以表间只要有外键关系就可以一直点下去。。。点到天荒地老

所以可以通过obj.外键.B表的列表跨表操作(注意!!orm连表操作必须选拿单个对象,不像SQL中直接表和表join就可以了)

print(obj.cls.title)

 

 

foreignkey字段在那个表里,那个表里一个"空格"代表那个表的多个(一行)

 

 

class UserGroup(models.Model):
            """
            部门 3
            """
            title = models.CharField(max_length=32)
        class UserInfo(models.Model):
            """
            员工4
            """
            nid = models.BigAutoField(primary_key=True)
            user = models.CharField(max_length=32)
            password = models.CharField(max_length=64)
            age = models.IntegerField(default=1)
            # ug_id 1
            ug = models.ForeignKey("UserGroup",null=True)

1. 在取得时候跨表
q = UserInfo.objects.all().first()
q.ug.title

2. 在查的时候就跨表了 
UserInfo.objects.values(''nid'',''ug_id'') 
UserInfo.objects.values(''nid'',''ug_id'',''ug__title'')    #注意正向连表是  外键__外键列 反向是小写的表名

3. UserInfo.objects.values_list(''nid'',''ug_id'',''ug__title'')

 

反向连表:

反向操作无非2种方式:

1、通过对象的形式反向跨表:小写表面_set().all()

2、通过value和value_list方式反向跨表:小写表名__字段


1. 小写的表名_set 得到有外键关系的对象

obj = UserGroup.objects.all().first()
result = obj.userinfo_set.all() [userinfo对象,userinfo对象,]

2. 小写的表名 得到有外键关系的列 #因为使用values取值取得是字典的不是对象,所以需要 小写表名(外键表)__

v = UserGroup.objects.values(''id'',''title'') 
v = UserGroup.objects.values(''id'',''title'',''小写的表名称'') 
v = UserGroup.objects.values(''id'',''title'',''小写的表名称__age'') 

3. 小写的表名 得到有外键关系的列

v = UserGroup.objects.values_list(''id'',''title'') 
v = UserGroup.objects.values_list(''id'',''title'',''小写的表名称'') 
v = UserGroup.objects.values_list(''id'',''title'',''小写的表名称__age'')

 

 1对多自关联( 由原来的2张表,变成一张表! )

 

 

 

 想象有第二张表,关联自己表中的 行

 

 

代码

复制代码
    class Comment(models.Model):
                """
                评论表
                """
                news_id = models.IntegerField()            # 新闻ID
                content = models.CharField(max_length=32)  # 评论内容
                user = models.CharField(max_length=32)     # 评论者
                reply = models.ForeignKey(''Comment'',null=True,blank=True,related_name=''xxxx'') #回复ID
复制代码

 

 

 

 

 

 

2、 多对多:

1、自己写第3张关系表

ORM多对多查询:

女士表:

男生表:

男女关系表

 

多对跨表操作

#获取方少伟有染的女孩
    obj=models.Boy.objects.filter(name=''方少伟'').first()
    obj_list=obj.love_set.all()
    for row in obj_list:
        print(row.g.nike)

    # 获取和苍井空有染的男孩
    obj=models.Girl.objects.filter(nike=''苍井空'').first()
    user_list=obj.love_set.all()
    for row in  user_list:
        print(row.b.name)

多对多关系表   数据查找思路

1、找到该对象
2.通过该对象 反向操作 找到第三张关系表
3.通过第三张关系表 正向操作 找到 和该对象有关系对象
总结(只要对象1和对象2 中间有关系表建立了关系; 对象1反向操作 到关系表 ,关系表正向操作到对象2,反之亦然

 

 

 

 

2、第3张关系表不用写(m=models.ManyToManyField('' 要关联的表'') 自动生成  )

 

由于 DjangoORM中一个类名对应一张表,要想操作表就modles.类直接操作那张表,但使用ManyToManyField字段生成 “第三张”关系表怎么操作它呢?

答案:通过单个objd对象 间接操作

class Boy(models.Model):
    name = models.CharField(max_length=32)
    m = models.ManyToManyField(''Girl'',through="Love",through_fields=(''b'',''g'',))


class Girl(models.Model):
    nick = models.CharField(max_length=32)
    m = models.ManyToManyField(''Boy'')

正向操作: obj.m.all()

 1 obj = models.Boy.objects.filter(name=''方少伟'').first()
 2     print(obj.id,obj.name)
 3     obj.m.add(2)
 4     obj.m.add(2,4)
 5     obj.m.add(*[1,])
 6 
 7     obj.m.remove(1)
 8     obj.m.remove(2,3)
 9     obj.m.remove(*[4,])
10 
11     obj.m.set([1,])
12 
13     q = obj.m.all()
14     # [Girl对象]
15     print(q)
16     obj = models.Boy.objects.filter(name=''方少伟'').first()
17     girl_list = obj.m.all()
18 
19     obj = models.Boy.objects.filter(name=''方少伟'').first()
20     girl_list = obj.m.all()
21     girl_list = obj.m.filter(nick=''小鱼'')
22     print(girl_list)
23 
24     obj = models.Boy.objects.filter(name=''方少伟'').first()
25     obj.m.clear()
View Code

反向操作 :obj.小写的表名_set

多对多和外键跨表一样都是 小写的表名_set

 

 

3、既自定义第三张关系表 也使用ManyToManyField(''Boy'')字段(杂交类型)

ManyToManyField()字段创建第3张关系表,可以使用字段跨表查询,但无法直接操作第3张表,

自建第3表关系表可以直接操作,但无法通过字段 查询,我们可以把他们结合起来使用;

作用:

1、既可以使用字段跨表查询,也可以直接操作第3张关系表

2、obj.m.all() 只有查询和清空 方法

 

class UserInfo(AbstractUser):
    """
    用户信息
    """
    nid = models.BigAutoField(primary_key=True)
    nickname = models.CharField(verbose_name=''昵称'', max_length=32)
    telephone = models.CharField(max_length=11, blank=True, null=True, unique=True, verbose_name=''手机号码'')
    avatar = models.FileField(verbose_name=''头像'', upload_to=''upload/avatar/'')
    create_time = models.DateTimeField(verbose_name=''创建时间'',auto_now_add=True)

    fans = models.ManyToManyField(verbose_name=''粉丝们'',
                                  to=''UserInfo'',
                                  through=''UserFans'',

                                  through_fields=(''user'', ''follower''))

    def __str__(self):
        return self.username


class UserFans(models.Model):
    """
    互粉关系表
    """
    nid = models.AutoField(primary_key=True)
    user = models.ForeignKey(verbose_name=''博主'', to=''UserInfo'', to_field=''nid'', related_name=''users'')
    follower = models.ForeignKey(verbose_name=''粉丝'', to=''UserInfo'', to_field=''nid'', related_name=''followers'')

    class Meta:
        unique_together = [
            (''user'', ''follower''),
        ]


through=''UserFans''指定第3张关系表的表名
through_fields    指定第3张关系表的字段
class Boy(models.Model):
                name = models.CharField(max_length=32)
                m = models.ManyToManyField(''Girl'',through="Love",through_fields=(''b'',''g'',))
                # 查询和清空

            class Girl(models.Model):
                nick = models.CharField(max_length=32)
                # m = models.ManyToManyField(''Boy'')

            class Love(models.Model):
                b = models.ForeignKey(''Boy'')
                g = models.ForeignKey(''Girl'')

                class Meta:
                    unique_together = [
                        (''b'',''g''),

 

外键反向查找别名(方便反向查找)

在写ForeignKey字段的时候,如果想要在反向查找时不使用默认的 小写的表名_set,就在定义这个字段的时间加related参数!

related_name、related_query_name 字段=什么别名 反向查找时就使用什么别名!

 

反向查找:

设置了related_query_name 反向查找时就是obj.别名_set.all()保留了_set

related_query_name

from django.db import models

class Userinfo(models.Model):
    nikename=models.CharField(max_length=32)
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=64)
    sex=((1,''男''),(2,''女''))
    gender=models.IntegerField(choices=sex)


''''''把男女表混合在一起,在代码层面控制第三张关系表的外键关系  ''''''
   #写到此处问题就来了,原来两个外键 对应2张表 2个主键 可以识别男女
   #现在两个外键对应1张表  反向查找 无法区分男女了了
   # object对象女.U2U.Userinfo.set  object对象男.U2U.Userinfo.set
   #所以要加related_query_name对 表中主键 加以区分
   #查找方法 
   # 男 obj.a._set.all()
   # 女:obj.b._set.all()
class U2U(models.Model):
    b=models.ForeignKey(Userinfo,related_query_name=''a'')
    g=models.ForeignKey(Userinfo,related_query_name=''b'')

related_name

反向查找:

设置了relatedname就是 反向查找时就说 obj.别名.all()  

from django.db import models

class Userinfo(models.Model):
    nikename=models.CharField(max_length=32)
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=64)
    sex=((1,''男''),(2,''女''))
    gender=models.IntegerField(choices=sex)


''''''把男女表混合在一起,在代码层面控制第三张关系表的外键关系  ''''''
   #写到此处问题就来了,原来两个外键 对应2张表 2个主键 可以识别男女
   #现在两个外键对应1张表  反向查找 无法区分男女了了
   # object对象女.U2U.Userinfo.set  object对象男.U2U.Userinfo.set
   #所以要加related_query_name设置反向查找命名对 表中主键 加以区分
   #查找方法
   # 男 obj.a.all()
   # 女:obj.b.all()
class U2U(models.Model):
    b=models.ForeignKey(Userinfo,related_name=''a'')
    g=models.ForeignKey(Userinfo,related_name=''b'')

操作

from django.shortcuts import render,HttpResponse
from app01 import models
# Create your views here.

def index(request):
   #查找 ID为1男孩 相关的女孩
   boy_obj=models.Userinfo.objects.filter(id=1).first()
   
   res= boy_obj.boy.all()#得到U2U的对象再 正向跨表
   #原来跨表 boy_obj.小写表名.all()
   # 现在设置了related_name(别名) 直接res= boy_obj.boy.all()跨表
   
   for obj in res:
       print(obj.g.nikename)
   return HttpResponse(''OK'')

from django.shortcuts import render,HttpResponse
from app01 import models
# Create your views here.

def index(request):
#查找 ID为1男孩 相关的女孩
boy_obj=models.Userinfo.objects.filter(id=1).first()

res= boy_obj.boy.all()#得到U2U的对象再 正向跨表
#原来跨表 boy_obj.小写表名.all()
# 现在设置了related_name(别名) 直接res= boy_obj.boy.all()跨表

for obj in res:
print(obj.g.nikename)
return HttpResponse(''OK'')

class Userinfo(models.Model):
    nikename=models.CharField(max_length=32)
    username=models.CharField(max_length=32)
    password=models.CharField(max_length=64)
    sex=((1,''男''),(2,''女''))
    gender=models.IntegerField(choices=sex)
    m=models.ManyToManyField(''Userinfo'')

 查找方法

def index(request):
   # 多对多自关联 之通过男士查询女生
   boy_obj=models.Userinfo.objects.filter(id=4).first()
   res=boy_obj.m.all()
   for row in  res:
      print(row.nikename)
   return HttpResponse(''OK'')
   #多对多自关联 之通过女士查询男生
   girl_obj=models.Userinfo.objects.filter(id=4).first()
   res=girl_obj.userinfo_set.all()
   for obj in res:
      print(obj.nikename)
   return HttpResponse(''OK'')

 

多对多自关联特性:

 

 

ManyToManyField生成的第三张表

 

 

 

 

五、浅谈ORM查询性能

普通查询

obj_list=models.Love.objects.all() 
    for row in obj_list:           #for循环10次发送10次数据库查询请求
        print(row.b.name)


这种查询方式第一次发送 查询请求每for循环一次也会发送查询请求



1、select_related:结果为对象  注意query_set类型的对象 都有该方法

原理: 查询时主动完成连表形成一张大表,for循环时不用额外发请求;

试用场景: 节省硬盘空间,数据量少时候适用相当于做了一次数据库查询;

obj_list=models.Love.objects.all().select_related(''b'')
    for row in obj_list:
        print(row.b.name)



2、prefetch_related:结果都对象是

原理:虽好,但是做连表操作依然会影响查询性能,所以出现prefetch_related
prefetch_related:不做连表,多次单表查询外键表 去重之后显示, 2次单表查询(有几个外键做几次1+N次单表查询, 

适用场景:效率高,数据量大的时候试用

obj_list=models.Love.objects.all().prefetch_related(''b'')
    for obj in obj_list:
        print(obj.b.name)

3、update()和对象.save()修改方式的性能PK
修改方式1
models.Book.objects.filter(id=1).update(price=3)
方式2
book_obj=models.Book.objects.get(id=1)
book_obj.price=5
book_obj.save()


执行结果:
(0.000) BEGIN; args=None
(0.000) UPDATE "app01_book" SET "price" = ''3.000'' WHERE "app01_book"."id" = 1; args=(''3.000'', 1)
(0.000) SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", "app01_book"."date", "app01_book"."publish_id", "app01_book"."classify_id" FROM "app01_book" WHERE "app01_book"."id" = 1; args=(1,)
(0.000) BEGIN; args=None
(0.000) UPDATE "app01_book" SET "title" = ''我的奋斗'', "price" = ''5.000'', "date" = ''1370-09-09'', "publish_id" = 4, "classify_id" = 3 WHERE "app01_book"."id" = 1; args=(''我的奋斗'', ''5.000'', ''1370-09-09'', 4, 3, 1)
[31/Aug/2017 17:07:20] "GET /fandq/ HTTP/1.1" 200 2

结论:

update() 方式1修改数据的方式,比obj.save()性能好;

六、分组和聚合查询

1、aggregate(*args,**kwargs)  聚合函数

通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。

from django.db.models import Avg,Sum,Max,Min
    #求书籍的平均价
    ret=models.Book.objects.all().aggregate(Avg(''price''))
    #{''price__avg'': 145.23076923076923}

    #参与西游记著作的作者中最老的一位作者
    ret=models.Book.objects.filter(title__icontains=''西游记'').values(''author__age'').aggregate(Max(''author__age''))
    #{''author__age__max'': 518}

    #查看根哥出过得书中价格最贵一本
    ret=models.Author.objects.filter(name__contains=''根'').values(''book__price'').aggregate(Max(''book__price''))
    #{''book__price__max'': Decimal(''234.000'')}

2、annotate(*args,**kwargs)  分组函数

#查看每一位作者出过的书中最贵的一本(按作者名分组 values() 然后annotate 分别取每人出过的书价格最高的)
    ret=models.Book.objects.values(''author__name'').annotate(Max(''price''))
    # < QuerySet[
    # {''author__name'': ''吴承恩'', ''price__max'': Decimal(''234.000'')},
    # {''author__name'': ''吕不韦'',''price__max'': Decimal(''234.000'')},
    # {''author__name'': ''姜子牙'', ''price__max'': Decimal(''123.000'')},
    # {''author__name'': ''亚微'',price__max'': Decimal(''123.000'')},
    # {''author__name'': ''伯夷 '', ''price__max'': Decimal(''2010.000'')},
    # {''author__name'': ''叔齐'',''price__max'': Decimal(''200.000'')},
    # {''author__name'': ''陈涛'', ''price__max'': Decimal(''234.000'')},
    # {''author__name'': ''高路川'', price__max'': Decimal(''234.000'')}
    # ] >

    #查看每本书的作者中最老的    按作者姓名分组 分别求出每组中年龄最大的
    ret=models.Book.objects.values(''author__name'').annotate(Max(''author__age''))
    # < QuerySet[
    #  {''author__name'': ''吴承恩'', ''author__age__max'': 518},
    #  {''author__name'': ''张X'', ''author__age__max'': 18},
    #  { ''author__name'': ''张X杰'', ''author__age__max'': 56},
    #  {''author__name'': ''方X伟'', ''author__age__max'': 26},
    #  {''author__name'': ''游X兵'', ''author__age__max'': 35},
    #  {''author__name'': ''金庸'', ''author__age__max'': 89},
    #  { ''author__name'': ''X涛'', ''author__age__max'': 27},
    #  {''author__name'': ''高XX'', ''author__age__max'': 26}
    # ] >

    #查看 每个出版社 出版的最便宜的一本书
    ret=models.Book.objects.values(''publish__name'').annotate(Min(''price''))
    # < QuerySet[
    # {''publish__name'': ''北大出版社'',''price__min'': Decimal(''67.000'')},
    # {''publish__name'': ''山西出版社'',''price__min'': Decimal(''34.000'')},
    # {''publish__name'': ''河北出版社'', ''price__min'': Decimal(''123.000'')},
    # {''publish__name'': ''浙江出版社'', ''price__min'': Decimal(''2.000'')},
    # {''publish__name'': ''湖北出版社'', ''price__min'': Decimal(''124.000'')},
    # {''publish__name'': ''湖南出版社'',price__min'': Decimal(''15.000'')}
    # ] >

七、F查询与Q查询

仅仅靠单一的关键字参数查询已经很难满足查询要求。此时Django为我们提供了F和Q查询:

1、F 可以获取对象中的字段的属性(列),并对其进行操作;

    from django.db.models import F,Q
    #F 可以获取对象中的字段的属性(列),并且对其进行操作;
    models.Book.objects.all().update(price=F(''price'')+1)   #对图书馆里的每一本书的价格 上调1块钱

 

2、Q多条件组合查询

 Q()可以使orm的fifter()方法支持, 多个查询条件,使用逻辑关系(&、|、~)包含、组合到一起进行多条件查询;

 

语法:

fifter(Q(查询条件1)| Q(查询条件2))

fifter(Q(查询条件2)& Q(查询条件3))

fifter(Q(查询条件4)& ~Q(查询条件5))

fifter(Q(查询条件6)| Q(Q(查询条件4)& ~ Q(Q(查询条件5)& Q(查询条件3)))包含

from django.db.models import F,Q
    1、F 可以获取对象中的字段的属性(列),并且对其进行操作;
    # models.Book.objects.all().update(price=F(''price'')+1)
    2、Q多条件组合查询
    #如果 多个查询条件 涉及到逻辑使用 fifter(,隔开)可以表示与,但没法表示或非得关系
    #查询 书名包含作者名的书
    book=models.Book.objects.filter(title__icontains=''伟'',author__name__contains=''伟'').values(''title'')
    #如何让orm 中得 fifter 支持逻辑判断+多条件查询? Q()登场
    book=models.Book.objects.filter(Q(title__icontains=''伟'') & Q(author__name__contains=''伟'')).values(''title'')
    book=models.Book.objects.filter(Q(author__name__contains=''伟'') & ~Q(title__icontains=''伟'')).values(''title'')

   #多条件包含组合查询
   #查询作者姓名中包含 方/少/伟/书名包含伟3字 并且出版社地址以山西开头的书
    book=models.Book.objects.filter(
                                    Q(
                                    Q(author__name__contains=''方'') |
                                    Q(author__name__contains=''少'') |
                                    Q(title__icontains=''伟'')|
                                    Q(author__name__contains=''伟'')
                                    )
                                    &
                                    Q(publish__addr__contains=''山西'')
                                    ).values(''title'')
    print(book)
    return HttpResponse(''OK'')

注意:Q查询条件和非Q查询条件混合使用注意,不包Q()的查询条件一点要放在Q(查询条件)后面

 

 

八、Django自带ContentType表

首先声明本文介绍的ContentType不是http协议中请求头里Content Type,而是Django程序启动后自带的一张表;

INSTALLED_APPS = [
    ''django.contrib.admin'',
    ''django.contrib.auth'',
    ''django.contrib.contenttypes'',
    ''django.contrib.sessions'',
    ''django.contrib.messages'',
    ''django.contrib.staticfiles'',
    ''app01.apps.App01Config'',
]

setings.py配置文件

1、ContentType表内容介绍

ContentType表记录了Django程序的所有APP下model中的表名、和所在app的名称;

 

2、应用场景:

2.1 通过ContentType中的app名称和表名,查找到Django model中所有表;

from django.shortcuts import render,HttpResponse

from django.contrib.contenttypes.models import ContentType
#在Django默认设置app,contrib.contenttypes下中models 导入ContentType类(表)


def test(request):
    c=ContentType.objects.get(app_label=''app01'',model=''boy'')
    print(c)
    #boy
    model_class=c.model_class()
    print(model_class)
    #app01.models.Boy
    return HttpResponse(''OK'')
;

2.2 解决 1张表 同时 其他N张表建立外键,并且多个外键中只能选择1个,关系的复杂问题

 

场景1:你是一家在线教育的DBA,现有N种优惠券,每1种优惠券怎么分别对应 N门课程中的一1门课程,怎么设计表结构呢?

from django.db import models
from django.contrib.contenttypes.models import ContentType

class DegreeCourse(models.Model):
    """学位课程
     ID    名称
   学位课1
   学位课2

    """
    name = models.CharField(max_length=128, unique=True)



class Course(models.Model):
    """普通课程
     ID    名称
   普通课1
   普通课2
    """
    name = models.CharField(max_length=128, unique=True)

class Coupon(models.Model):
    """优惠券生成规则

    ID     优惠券名称         content_type_id(表)         object_id(表中数据ID)
      通用                 null                    null
      满100-10               8                      1
      满200-30               8                      2
      满200-30               9                      1
    总结:
    """
    name = models.CharField(max_length=64, verbose_name="活动名称")
    brief = models.TextField(blank=True, null=True, verbose_name="优惠券介绍")
    #course_type 代指哪张表
    course_type = models.ForeignKey(ContentType,blank=True,null=True)
    #代指对象ID
    object_id=models.IntegerField(blank=True,null=True)

场景2 :学生 学习成绩如何要奖惩、 作业写得如何要奖惩、学习进度如何要奖惩、。。。。。。学生各种行为都要奖惩怎么设计表结构?

class Homework(models.Model):
    """
    ID  User     Name    score
 吴昊   第一模块    30
 吴昊   第二模块    80
 吴昊   第三模块    100

    """
    name = models.CharField(max_length=32)

    score_choices = (
        (100,''A''),
        (80,''B''),
        (60,''C''),
        (30,''D''),
    )
    score = models.IntegerField(choices=score_choices)

    user = models.ForeignKey(''User'')


class Record(models.Model):
    """
     ID  User     Name     score
 吴昊     第一模块    10        5
 吴昊     第二模块    8        10
    """
    name = models.CharField(max_length=32)
    score_choices = (
        (100, ''A''),
        (80, ''B'')
    )
    score = models.IntegerField(choices=score_choices)

class ScoreRecord(models.Model):
    """
    ID      Name           表       对象
    作业太差         1
    作业太好         1
    看的太快         null               1
    """
    name = models.CharField(max_length=32)
    content_type = models.ForeignKey(ContentType, blank=True, null=True)
    # 对象ID
    object_id = models.PositiveIntegerField("绑定课程", blank=True, null=True, help_text="可以把优惠券跟课程绑定")

3、content type 操作

from django.db import models
from django.contrib.contenttypes.models import ContentType

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
class DegreeCourse(models.Model):
    """学位课程
     ID    名称
   学位课1
   学位课2

    """
    name = models.CharField(max_length=128, unique=True)
    #GenericRelation 自动连表查询
    xx= GenericRelation(''Coupon'')


class Course(models.Model):
    """普通课程
     ID    名称
   普通课1
   普通课2
    """
    name = models.CharField(max_length=128, unique=True)

class Coupon(models.Model):
    """优惠券生成规则

    ID     优惠券名称         content_type_id(表)         object_id(表中数据ID)
      通用                 null                    null
      满100-10               8                      1
      满200-30               8                      2
      满200-30               9                      1
    总结:
    """
    name = models.CharField(max_length=64, verbose_name="活动名称")
    brief = models.TextField(blank=True, null=True, verbose_name="优惠券介绍")
    #course_type 代指哪张表 注意该字段必须为 content_type=
    content_type = models.ForeignKey(ContentType,blank=True,null=True)
    #代指对象ID
    object_id = models.PositiveIntegerField("绑定课程", blank=True, null=True, help_text="可以把优惠券跟课程绑定")
    #通过 contenttype 直接 创建 外键关系,不会生成额外的列,注意 (''content_type'',''object_id'') 和上面2字段保持一致
    content_object=GenericForeignKey(''content_type'',''object_id'')

model
from django.shortcuts import render,HttpResponse
from django.contrib.contenttypes.models import ContentType

from app01 import models

def test(request):
    # c=ContentType.objects.get(app_label=''app01'',model=''boy'')
    # print(c)
    # #boy
    # model_class=c.model_class()
    # print(model_class)
    # #app01.models.Boy



    #给学位课1,创建优惠券100
    #方式1
    #1、在学位课表中 ,找到学位课1
    d1=models.DegreeCourse.objects.get(id=1)
    #2、在ContentType找到学位课表
    c1= ContentType.objects.get(app_label=''app01'',model=''degreecourse'')
    #3 给学位课1,创建优惠券100
    # models.Coupon.objects.create(name=''优惠券'',brief=''100'',content_type=c1,object_id=d1.id)
    # 方式2
    # d1 = models.DegreeCourse.objects.get(id=1)
    # models.Coupon.objects.create(name=''优惠券'',brief=''100'',content_object=d1)

    #当前课程都有哪些优惠券?
    d1 = models.DegreeCourse.objects.get(id=1)
    # 查询关联的所有优惠券
    print(d1.xx.all())
    v=models.DegreeCourse.objects.values(''name'',''xx__brief'',''xx__name'')
    print(v)

    return HttpResponse(''OK'')

视图

3.1 GenericForeignKey 创建

给学位课1,创建优惠券100

#给学位课1,创建优惠券100
    #方式1
    #1、在学位课表中 ,找到学位课1
    d1=models.DegreeCourse.objects.get(id=1)
    #2、在ContentType找到学位课表
    c1= ContentType.objects.get(app_label=''app01'',model=''degreecourse'')
    #3 给学位课1,创建优惠券100
    models.Coupon.objects.create(name=''优惠券'',brief=''100'',content_type=c1,object_id=d1.id)

方式1
#course_type 代指哪张表 注意该字段必须为 content_type=
    content_type = models.ForeignKey(ContentType,blank=True,null=True)
    #代指对象ID
    object_id = models.PositiveIntegerField("绑定课程", blank=True, null=True, help_text="可以把优惠券跟课程绑定")
    #直接和contenttype 创建 外键关系,不会生成额外的列
    content_object=GenericForeignKey(''content_type'',''object_id'')
d1 = models.DegreeCourse.objects.get(id=1)
    models.Coupon.objects.create(name=''优惠券'',brief=''100'',content_object=d1)
    return HttpResponse(''OK'')

3.2  GenericRelation  查询

当前课程都有哪些优惠券?

class DegreeCourse(models.Model):
    """学位课程
     ID    名称
   学位课1
   学位课2

    """
    name = models.CharField(max_length=128, unique=True)
    #GenericRelation 自动连表查询
    xx= GenericRelation(''Coupon'')

model
#当前课程都有哪些优惠券?
    d1 = models.DegreeCourse.objects.get(id=1)
    # 查询关联的所有优惠券
    print(d1.xx.all())
    v=models.DegreeCourse.objects.values(''name'',''xx__brief'',''xx__name'')
    print(v)

九、补充

1.oder_by(-id):按照某种规则排序

 2.exclude(字段):字段获取数据时排除

course_list = models.Course.objects.exclude(course_type=2)

3.按时间查询

Django的orm支持按时间查询数据,前提是你在models中设置了该字段为DateTimeField 以及该字段存储的数据类型为 python的datime时间类型。

 

提示:

如果在通过时间查询的时候出现 warning 在setings.py中设置如下:

USE_TZ = True

如果时间格式显示英文在setings.py中设置如下:

LANGUAGE_CODE = ''zh-Hans''

 

 

 

A.查询大于某个时间点产生的数据。(在某个时间点之后)

#gt:大于某个时间
now = datetime.datetime.now()
start = now-datetime.timedelta(hours=23,minutes=59,seconds=59)
#查询 前一天的数据
obj=models.TaskLog.objects.filter(date__gt=start)
print(obj)

 

B.大于等于某个时间点

复制代码
import datetime
start_date = datetime.date(2018, 9, 5)
#gte:大于等于某个时间点
now = datetime.datetime.now()
start = now-datetime.timedelta(hours=23,minutes=59,seconds=59)
#查询 前一天的数据
obj=models.TaskLog.objects.filter(date__gte=start)
print(obj)
复制代码

 

C.小于某个时间点(在某个时间点之前)

复制代码
import datetime
start_date = datetime.date(2018, 9, 5)
#lt:小于某个时间点
now = datetime.datetime.now()
start = now-datetime.timedelta(hours=23,minutes=59,seconds=59)
#查询 2018年9月4日,之前产生的日志。
obj=models.TaskLog.objects.filter(date__lt=start)
print(obj)
复制代码

 

D.小于等于某个时间点

复制代码
import datetime
start_date = datetime.date(2018, 9, 5)
#lte:小于等于某个时间点
now = datetime.datetime.now()
start = now-datetime.timedelta(hours=23,minutes=59,seconds=59)
#查询 2018年9月4日当日以及当天之前产生的日志。
obj=models.TaskLog.objects.filter(date__lte=start)
print(obj)
复制代码

 

 E.range:查询某个明确时间段数据 (某个时间段)

import datetime
start_date = datetime.date(2018, 9, 5)
end_date = datetime.date(2018, 9,8)
#查询 2018年9月5日 ------- 2018年9月8日 期间产生的日志
obj=models.TaskLog.objects.filter(date__range=(start_date,end_date))
print(obj)

 

F.__year查询某年产生数据(例如:2018)

#查询2018年产生的日志
obj=models.TaskLog.objects.filter(date__year=2018)
print(obj)

 

G.__month查询 某月产生的数据(例:2018年9月)

#查询9月产生的数据
obj=models.TaskLog.objects.filter(date__year=2018,date__month=9)
print(obj)

 

H.__week_day查询某年、某月、星期几产生的数据(例如:2018年9月份 每个星期5)

#查询 某年 某月  周几 产生的数据
#                                                              0-6表示:周1至周五
obj=models.TaskLog.objects.filter(date__year=2018,date__month=9,date__week_day=4).count()
print(obj)

 

 

 I.查询某年、某月、某天产生的数据 (例:2018年9月10日)

obj=models.TaskLog.objects.filter(date__year=2018,date__month=9,date__day=10).count()
print(obj)

 

原贴:https://www.cnblogs.com/sss4/p/7070942.html 

 

二龙湖浩哥:http://www.cnblogs.com/yuanchenqi/articles/6811632.html#3763280

 

银角大王:http://www.cnblogs.com/wupeiqi/articles/5246483.html

 

今天的关于Django ORM操作django orm的操作的分享已经结束,谢谢您的关注,如果想了解更多关于Django - Model操作 和 ORM操作、Django - ORM操作、Django - 表与ORM操作、django -orm操作总结的相关知识,请在本站进行查询。

本文标签: