zoukankan      html  css  js  c++  java
  • django框架<二>

    django框架:

      Models

    1、基本创建

    Django提供了一个抽象层("Model")的构建和管理Web应用程序的数据。

    Django使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。

    • 每个模型是一个Python类,子类django.db.models.model
    • 模型中的每个属性代表一个数据库字段。
    # DEMO
    
    class Student(models.Model):
        name = models.CharField(max_length=10)
        sex = models.CharField(max_length=10)
        age = models.IntegerField()
        grade = models.ForeignKey('Grade')
    
    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_112233d+', message='又错误了', code='c2'),
                                        EmailValidator(message='又错误了', code='c3'), ]
                                )
    Field参数

    2、连表结构例如在建表的时候应该了解到如何

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

    3、表操作

    a、基本操作

    #
        #
        # 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

    b、进阶操作(了不起的双下划线)

    # 获取个数
            #
            # 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)
    进阶之双下划线

    c、连表操作(了不起的双下划线)

    # DEMO
    # 班级和老师存在多对多关系、班级和学生存在一对多关系
    from django.db import models
    
    class Classes(models.Model):
        titile = models.CharField(max_length=32)
        m = models.ManyToManyField('Teachers')
    
    
    class Teachers(models.Model):
        name = models.CharField (max_length=32)
    
    
    class Student(models.Model):
        username = models.CharField(max_length=32)
        age = models.IntegerField()
        gender = models.BooleanField()
        cs = models.ForeignKey(Classes)
    表结构实例
    #
    # Teachers.objects.create(name='root')
    # obj = Teachers(name='root')
    # obj.save()
    #
    # Teachers.objects.all()
    # Teachers.objects.filter(id=1)
    # Teachers.objects.filter(id=1,name='root')
    # result = Teachers.objects.filter(id__gt=1)
    # [obj(id,name),]
    # result = Teachers.objects.filter(id__gt=1).first()
    #
    # Teachers.objects.filter(id=1).delete()
    #
    # Teachers.objects.all().update(name='alex')
    # Teachers.objects.filter(id=1).update(name='alex')
    单表
    # 增加
    # Student.objects.create(username='东北',age=18,gender='男',cs_id=1)
    # Student.objects.create(username='东北',age=18,gender='男',cs= Classes.objects.filter(id=1).first() )
    # 查看
    """
    ret = Student.objects.all()
    # []
    # [ obj(..),]
    # [ obj(1      东北       18     男         1),obj(2      东北1      118     男         2),obj(..),]
    for item in ret:
        print(item.id)
        print(item.username)
        print(item.age)
        print(item.gender)
        print(item.cs_id)
        print(item.cs.id)
        print(item.cs.name)
    """
    # 删除
    # Student.objects.filter(id=1).delete()
    # Student.objects.filter(cs_id=1).delete()
    
    # cid = input('请输入班级ID')
    # Student.objects.filter(cs_id=cid).delete()
    
    # cname = input('请输入班级名称')
    # Student.objects.filter(cs_id=cid).delete()
    # Student.objects.filter(cs__name=cname).delete()
    一对多
    """
    班级:
    id  title
       3班
       4班
       5班
    老师:
    id   title
       Alex
       老妖
       瞎驴
       Eric
     老师班级关系表(类):
    id   班级id   老师id
        1        2
        1        3
        2        2
        2        3
        2        4
        1        5
    
    
    # 增
    obj = Classes.objects.filter(id=1).first() #1    3班
    obj.m.add(2)
    obj.m.add([4,3])
    
    # obj = Classes.objects.filter(id=2).first() #1    3班
    # obj.m.add(2)
    # obj.m.add([4,3])
    
    obj = Classes.objects.filter(id=1).first() #1    3班
    # 删除
    # obj.m.remove([4,3])
    # 清空
    obj.m.clear()
    # 重置
    obj.m.set([2,3,5])
    
    # 查第三张表
    # 把3班的所有老师列举
    obj = Classes.objects.filter(id=1).frist()
    obj.id
    obj.titile
    ret = obj.m.all() # 第三张表
    # ret是一个 [ 老师1(id,name),obj(id,name)   ]
    
    """
    多对多

    d、其它操作

    # ============其他的关于moders的应用=========================
    #     排序
    #     user_list=models.Userinfo.objects.all().order_by("id","username")#从小到大排序,当出现id一样的话,则按照名字排序
    #     user_list2=models.Userinfo.objects.all().order_by("-id")#从大到小排序
    #     print(user_list)
    #     print(user_list2)
    #     分组
        from django.db.models import Count,Sum,Min,Max
        # res=models.Userinfo.objects.values("ut_id").annotate(a=Count("id"))
        # print(res.query)#==>相当于SELECT `app01_userinfo`.`ut_id`, COUNT(`app01_userinfo`.`id`) AS `a` FROM `app01_userinfo` GROUP BY `app01_userinfo`.`ut_id`
    
        # res=models.Userinfo.objects.values("ut_id").annotate(b=Count("id")).filter(id__lt=2)
        # print(res)#==><QuerySet [{'ut_id': 1, 'b': 1}]>
        # print(res.query)#=>SELECT `app01_userinfo`.`ut_id`, COUNT(`app01_userinfo`.`id`) AS `b` FROM `app01_userinfo` WHERE `app01_userinfo`.`id` < 2 GROUP BY `app01_userinfo`.`ut_id` ORDER BY NULL
        # 过滤
        # res =models.Userinfo.objects.filter(id__lt=5)#小于
        # res =models.Userinfo.objects.filter(id__gt=5)#大于
        # res =models.Userinfo.objects.filter(id__lte=5)#小于等于
        # res =models.Userinfo.objects.filter(id__gte=5)#大于等于
        # res =models.Userinfo.objects.filter(id__in=[1,2,3])#id在列表中
        # res =models.Userinfo.objects.filter(id__range=[1,3])#id的范围属于1-3(包含1和3)
        # res=models.Userinfo.objects.filter(username__startswith="ha")
        # res=models.Userinfo.objects.filter(username__endswith="ha")
        # res=models.Userinfo.objects.filter(username__contains="xu")#包含
        # res=models.Userinfo.objects.exclude(id=1)#排除id=1的
        # print(res)
    
    # ======关于F、Q、extra
    #     F:
        from django.db.models import F
        #将数据库中的年级那一列都自加一
        # models.Userinfo.objects.all().update(age=F("age")+1)
    
        # Q:
        # res=models.Userinfo.objects.filter(id=1,username="xuyuanyuan")#里面是and的关系
        # print(res)#==><QuerySet []>
        # dict={
        #     "id":1,
        #     "username":"xuyuanyuan"
        # }#里面是and的关系
        # ret=models.Userinfo.objects.filter(**dict)
        # print(ret)#===><QuerySet []>
    
        from django.db.models import Q
        # Q使用有两种方式:对象方式,方法方式 *
        # res=models.Userinfo.objects.filter(Q(id__lt=5))
        # res=models.Userinfo.objects.filter(Q(id__lt=5)|Q(id__gt=315))#或
        # res=models.Userinfo.objects.filter(Q(id__lt=5)&Q(id__gt=310))
        # print(res)
    
        # q1=Q()
        # q1.connector="OR"
        # q1.children.append(("id__gte",1))
        # q1.children.append(("id",3))
        # q1.children.append(("id",4))
        #
        # q2 = Q()
        # q2.connector = 'OR'
        # q2.children.append(('id', 11))
        # q2.children.append(('id', 1))
        # q2.children.append(('id', 10))
        #
        # q3 = Q()
        # q3.connector = 'AND'
        # q3.children.append(('id', 111))
        # q3.children.append(('id', 200))
        # q2.add(q3,'OR')
        #
        # con = Q()
        # con.add(q1, 'AND')
        # con.add(q2, 'AND')
        # res=models.Userinfo.objects.filter(con)
        # print(res)#===><QuerySet [<Userinfo: 1-hahaha-19>]>
        # print(res.query)#==>上面定义的就相当于下面的sql语句:
        # SELECT `app01_userinfo`.`id`,
        #  `app01_userinfo`.`username`,
        # `app01_userinfo`.`age`,
        # `app01_userinfo`.`ut_id`
        # FROM `app01_userinfo`
        # WHERE ((`app01_userinfo`.`id` >= 1 OR `app01_userinfo`.`id` = 3 OR `app01_userinfo`.`id` = 4)
        # AND (`app01_userinfo`.`id` = 11 OR `app01_userinfo`.`id` = 1 OR `app01_userinfo`.`id` = 10
        # OR (`app01_userinfo`.`id` = 111 AND `app01_userinfo`.`id` = 200)))
    
    
    
        # condition_dict = {
        #     'k1':[1,2,3,4],
        #     'k2':[1,2,10,11],
        #     "k3":[1,2,100,111,200],
        # }
        # con = Q()
        # for k,v in condition_dict.items():
        #     q = Q()
        #     q.connector = 'OR'
        #     for i in v:
        #         q.children.append(('id', i))
        #     con.add(q,'AND')
        # res=models.Userinfo.objects.filter(con)
        # print(res)
        # print(res.query)
    
    
        # 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'])
        
    #原生sql
        # name_map = {'title': 'titles'}
        # v1 = models.Userinfo.objects.raw('SELECT id,title FROM app01_usertype',translations=name_map)
        # print(v1.query)
        # print(v1)
        # for i in v1:
        #     print(i,type(i))
    其它

    e、补充

    # values             取到的是字典集合
        # values_list        取到的是没有键的元祖形式
    
        # get                只有在能取到一条数据的时候才不会报错(不推荐)
        # filter([筛选条件])
        # all()              俩者取到的都是Query set集合对象 是可迭代、可切片、索引取值
    
        # iterator()         ORM的惰性机制
                             # Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet
                             # 并不会马上执行sql,而是当调用QuerySet的时候才执行。
    View Code

     

    示例:

        # ==========多对多的练习
    # def test(request):
       # objs=[
        #     models.Boy(bname="小凳子"),
        #     models.Boy(bname="小座子"),
        #     models.Boy(bname="小李子"),
        #     models.Boy(bname="小面子"),
        #
        # ]
        # models.Boy.objects.bulk_create(objs,5)
    
        # objss=[
        #     models.Girl(gname="胖胖"),
        #     models.Girl(gname="矮矮"),
        #     models.Girl(gname="高高"),
        #     models.Girl(gname="凶凶"),
        # ]
        # models.Girl.objects.bulk_create(objss,5)
    
    
        # models.Love.objects.create(b_id=1,g_id=2)
        # models.Love.objects.create(b_id=1,g_id=3)
        # models.Love.objects.create(b_id=2,g_id=3)
        # models.Love.objects.create(b_id=2,g_id=4)
        # models.Love.objects.create(b_id=3,g_id=1)
        # models.Love.objects.create(b_id=4,g_id=4)
    
    #查找小凳子约会的女生名字
        # 方法一:(1)
        # objs=models.Boy.objects.filter(bname="小凳子").first()#直接取到的是obj,可以直接obj.出来
        # love_list_obj = objs.love_set.all()
        # for i in love_list_obj:
        #     print(i.g.gname)
        # (2)
        # list=models.Boy.objects.filter(bname="小凳子")#取到的是query的,需要for循环出来obj,再obj.出来
        # for i in list:
        #     print(i.bname)
        # print(list[0])
        # love_list_obj=list[0].love_set.all()
        # for i in love_list_obj:
        #     print(i.g.gname)
    
        # 方法二:
        # love_list=models.Love.objects.filter(b__bname="小凳子")
        # print(love_list)
        # for i in love_list:
        #     print(i.g.gname)
    
        # 方法三:
        # love_dict = models.Love.objects.filter(b__bname="小凳子").values("g__gname")
        # for i in love_dict:
        #     print(i["g__gname"])
    
        # 方法四:
        # love_list=models.Love.objects.filter(b__bname="小凳子").select_related("g")
        # for i in love_list:
        #     print(i.g.gname)
        #return HttpResponse("hello")

     

    django之model进阶的更多操作整理

    一、字段

    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
    
        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)
            - 二进制类型
    字段列表
    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)',
    自定义无符号整数字段

    二、字段参数

    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_112233d+', message='又错误了', code='c2'),
                                        EmailValidator(message='又错误了', code='c3'), ]
                                )
    View Code

    三、多表关系及参数

    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,              # 默认创建第三张表时,数据库中表的名称
    View Code

    四、更多ORM操作

    ##################################################################
    # PUBLIC METHODS THAT ALTER ATTRIBUTES AND RETURN A NEW QUERYSET #
    ##################################################################
    
    def all(self)
        # 获取所有的数据对象
    
    def filter(self, *args, **kwargs)
        # 条件查询
        # 条件可以是:参数,字典,Q
    
    def exclude(self, *args, **kwargs)
        # 条件查询
        # 条件可以是:参数,字典,Q
    
    def select_related(self, *fields)
         性能相关:表之间进行join连表操作,一次性获取关联的数据。
         model.tb.objects.all().select_related()
         model.tb.objects.all().select_related('外键字段')
         model.tb.objects.all().select_related('外键字段__外键字段')
    
    def prefetch_related(self, *lookups)
        性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。
                # 获取所有用户表
                # 获取用户类型表where id in (用户表中的查到的所有用户ID)
                models.UserInfo.objects.prefetch_related('外键字段')
    
    
    
                from django.db.models import Count, Case, When, IntegerField
                Article.objects.annotate(
                    numviews=Count(Case(
                        When(readership__what_time__lt=treshold, then=1),
                        output_field=CharField(),
                    ))
                )
    
                students = Student.objects.all().annotate(num_excused_absences=models.Sum(
                    models.Case(
                        models.When(absence__type='Excused', then=1),
                    default=0,
                    output_field=models.IntegerField()
                )))
    
    def annotate(self, *args, **kwargs)
        # 用于实现聚合group by查询
    
        from django.db.models import Count, Avg, Max, Min, Sum
    
        v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id'))
        # SELECT u_id, COUNT(ui) AS `uid` FROM UserInfo GROUP BY u_id
    
        v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id')).filter(uid__gt=1)
        # SELECT u_id, COUNT(ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
    
        v = models.UserInfo.objects.values('u_id').annotate(uid=Count('u_id',distinct=True)).filter(uid__gt=1)
        # SELECT u_id, COUNT( DISTINCT ui_id) AS `uid` FROM UserInfo GROUP BY u_id having count(u_id) > 1
    
    def distinct(self, *field_names)
        # 用于distinct去重
        models.UserInfo.objects.values('nid').distinct()
        # select distinct nid from userinfo
    
        注:只有在PostgreSQL中才能使用distinct进行去重
    
    def order_by(self, *field_names)
        # 用于排序
        models.UserInfo.objects.all().order_by('-id','age')
    
    def 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'])
    
     def reverse(self):
        # 倒序
        models.UserInfo.objects.all().order_by('-nid').reverse()
        # 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序
    
    
     def defer(self, *fields):
        models.UserInfo.objects.defer('username','id')
        或
        models.UserInfo.objects.filter(...).defer('username','id')
        #映射中排除某列数据
    
     def only(self, *fields):
        #仅取某个表中的数据
         models.UserInfo.objects.only('username','id')
         或
         models.UserInfo.objects.filter(...).only('username','id')
    
     def using(self, alias):
         指定使用的数据库,参数为别名(setting中的设置)
    
    
    ##################################################
    # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
    ##################################################
    
    def raw(self, raw_query, params=None, translations=None, using=None):
        # 执行原生SQL
        models.UserInfo.objects.raw('select * from userinfo')
    
        # 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名
        models.UserInfo.objects.raw('select id as nid from 其他表')
    
        # 为原生SQL设置参数
        models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])
    
        # 将获取的到列名转换为指定列名
        name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
        Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)
    
        # 指定数据库
        models.UserInfo.objects.raw('select * from userinfo', using="default")
    
        ################### 原生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() # fetchall()/fetchmany(..)
    
    
    def values(self, *fields):
        # 获取每行数据为字典格式
    
    def values_list(self, *fields, **kwargs):
        # 获取每行数据为元祖
    
    def dates(self, field_name, kind, order='ASC'):
        # 根据时间进行某一部分进行去重查找并截取指定内容
        # kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)
        # order只能是:"ASC"  "DESC"
        # 并获取转换后的时间
            - year : 年-01-01
            - month: 年-月-01
            - day  : 年-月-日
    
        models.DatePlus.objects.dates('ctime','day','DESC')
    
    def datetimes(self, field_name, kind, order='ASC', tzinfo=None):
        # 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间
        # kind只能是 "year", "month", "day", "hour", "minute", "second"
        # order只能是:"ASC"  "DESC"
        # tzinfo时区对象
        models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)
        models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))
    
        """
        pip3 install pytz
        import pytz
        pytz.all_timezones
        pytz.timezone(‘Asia/Shanghai’)
        """
    
    def none(self):
        # 空QuerySet对象
    
    
    ####################################
    # METHODS THAT DO DATABASE QUERIES #
    ####################################
    
    def aggregate(self, *args, **kwargs):
       # 聚合函数,获取字典类型聚合结果
       from django.db.models import Count, Avg, Max, Min, Sum
       result = models.UserInfo.objects.aggregate(k=Count('u_id', distinct=True), n=Count('nid'))
       ===> {'k': 3, 'n': 4}
    
    def count(self):
       # 获取个数
    
    def get(self, *args, **kwargs):
       # 获取单个对象
    
    def create(self, **kwargs):
       # 创建对象
    
    def bulk_create(self, objs, batch_size=None):
        # 批量插入
        # batch_size表示一次插入的个数
        objs = [
            models.DDD(name='r11'),
            models.DDD(name='r22')
        ]
        models.DDD.objects.bulk_create(objs, 10)
    
    def get_or_create(self, defaults=None, **kwargs):
        # 如果存在,则获取,否则,创建
        # defaults 指定创建时,其他字段的值
        obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2})
    
    def update_or_create(self, defaults=None, **kwargs):
        # 如果存在,则更新,否则,创建
        # defaults 指定创建时或更新时的其他字段
        obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})
    
    def first(self):
       # 获取第一个
    
    def last(self):
       # 获取最后一个
    
    def in_bulk(self, id_list=None):
       # 根据主键ID进行查找
       id_list = [11,21,31]
       models.DDD.objects.in_bulk(id_list)
    
    def delete(self):
       # 删除
    
    def update(self, **kwargs):
        # 更新
    
    def exists(self):
       # 是否有结果
    View Code

    五、小结

    # Model操作
        .related_name         # 设置反向查找的别名 例如 Book_set ==> xx
        .related_query_name   # 设置表的别名  例如 Book_set ==> xx_set
    
        .all
        .values
        .values_list
        .delete
        .filter
        .update
        .create
        
        # 多对多字段操作
        .m.add                 # 添加关系
        .m.set                 # 重置关系
        .m.clear               # 清空关系
        .m.remove              # 删除关系
    
        .only                  # 仅取某几列数据
        .defer                 # 排除某几列数据
        
        # 执行原生SQL语句的三种方式
    
    
        # from django.db import connection, connections
        # cursor = connection.cursor()  或 cursor = connections['default'].cursor()
        # cursor.execute("""SELECT * from auth_user where id = %s""", [1])  # 将1进行字符串拼接
        # row = cursor.fetchone()
    
        models.UserInfo.objects.raw('select id,name from userinfo')
    
        Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
        
    
        # 涉及到查表效率
        # 在使用all filter 查询表时,涉及到第三张表的查询时、
        # 会再次执行查询,数据量很庞大的时候,会影响执行效率、因此下方俩条可较为有效的解决此问题
    
        select_related('跨表字段')  # 一次连表查询获取所有数据
        prefetch_related           # 不连表、会进行俩次查询

     

     

    Admin

    Django Amdin是Django提供的一个后台管理页面,改管理页面提供完善的html和css,在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用Django Admin 则需要以下步骤:

    • 创建后台管理员
    • 配置url
    • 注册和配置Django Admin后台管理页面 

    1、创建后台管理员

    python manage.py createsuperuser
    

    2、配置后台管理url

    url(r'^admin/', include(admin.site.urls))
    

    3、注册和配置django admin 后台管理页面

    A、注册表

    from django.contrib import admin
      
    from app01 import  models
      
    admin.site.register(models.UserType)
    admin.site.register(models.UserInfo)
    admin.site.register(models.UserGroup)
    admin.site.register(models.Asset)
    View Code

    B、设置数据表显示名称

    class UserType(models.Model):
        name = models.CharField(max_length=50)
      
        class Meta:
            verbose_name = '用户类型'
            verbose_name_plural = '用户类型'
    View Code

    C、打开表之后想要看哪些字段作出如下配置

    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username', 'password', 'email')  # 放置对应表字段
      
    admin.site.register(models.UserInfo,UserInfoAdmin)
    View Code

    D、数据表添加过滤功能(模糊输入查询)

    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username', 'password', 'email')
        search_fields = ('username', 'email')     # 定义它
      
    admin.site.register(models.UserInfo,UserInfoAdmin)
    View Code

    E、快速过滤

    from django.contrib import admin
      
    from app01 import  models
      
    class UserInfoAdmin(admin.ModelAdmin):
        list_display = ('username', 'password', 'email')
        search_fields = ('username', 'email')
        list_filter = ('username', 'email')
          
      
    admin.site.register(models.UserInfo,UserInfoAdmin)
    View Code

    F、设置分页和只读字段

    from django.contrib import admin
    from repository import models
    
    
    class CustomerInfoAdmin(admin.ModelAdmin):
        list_display = ['name', 'source', 'contact_type', 'contact', 'consultant', 'status', 'date']
        list_filter = ['source', 'consultant', 'status', 'date']
        search_fields = ['contact', 'consultant__name']
        readonly_fields = ['status','contact']   # 只读字段
        filter_horizontal = ['consult_courses',]  # 出现炫酷的select切换
        list_per_page = 2    # 设置分页,每页显示多少条
    
    admin.site.register(models.UserProfile)
    admin.site.register(models.Role)
    admin.site.register(models.CustomerInfo, CustomerInfoAdmin)
    View Code
    
    

     

    分页

    一、Django内置分页

    示例:

    urls.py

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    
    urlpatterns = [
    
    # 查看django自带的上一页和下一页
        url(r'^index.html$', views.index),
    
    ] 

    views.py

    from django.shortcuts import render,HttpResponse
    from django.views import View
    from app01 import models
    from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage
    # django自带的分页
    def index(request):
        """
        分页
        :param request: 
        :return: 
        """
        # 往用户信息的数据表内插入300条用户信息
        # for i in range(301):
        #     name="xuyuanyuan"+str(i)
        #     models.Userinfo.objects.create(username=name,age=20,ut_id=2)
    
        choise_page=request.GET.get("page")
        user_list=models.Userinfo.objects.all()
        # paginator=Paginator(user_list,10)分页处理,每一页10条数据
        paginator=Paginator(user_list,10)
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
    
        try:
            result=paginator.page(choise_page)
            # print(result)#QuerySet [<Userinfo: Userinfo object>, <Userinfo: Userinfo object>,
            # 打印的result是一个个userinfo的对象
            # print(result.object_list)
        except PageNotAnInteger as e:
            result=paginator.page(1)
        except EmptyPage as e:
            result=paginator.page(1)
    
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    
        return render(request,"index.html",{"result":result})
    

     index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>用户列表</h1>
    <ul>
        {% for i in result.object_list %}
            <li>姓名:{{ i.username }}</li>
        {% endfor %}
    </ul>
    <div>
        {% if result.has_previous %}
            <a href="/index.html?page={{ result.previous_page_number }}">上一页</a>
        {% endif %}
    
        {% if result.has_next %}
            <a href="/index.html?page={{ result.next_page_number }}">下一页</a>
        {% endif %}
    </div>
    </body>
    </html>
    

    执行结果:

    二、Django内置分页的拓展

    from django.shortcuts import render
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    user = []
    for i in range(1, 1001):
        dic = {'name': 'root' + str(i), 'pwd': i}
        user.append(dic)
    
    
    class DiyPaginator(Paginator):
        def __init__(self, current_page,max_pager_num, *args, **kwargs):
            """
            :param current_page:  当前页码
            :param max_pager_num: 显示页码个数的最大值
            :param args:
            :param kwargs:
            """
            self.current_page = int(current_page)
            self.max_pager_num = int(max_pager_num)
            super(DiyPaginator,self).__init__(*args,**kwargs)
    
        def pager_num_range(self):
            # 需要的参数
            # 当前页码    self.current_page
            # 页码数量    self.max_pager_num
            # 总页数      self.num_pages
    
            # 如果总页数小于页码个数最大值的情况
            if self.num_pages < self.max_pager_num:
                return range(1,self.num_pages+1)     # 返回 从 1 到 总页数
    
            # 如果总页数大于页码数量且当前所选页码小于页码数量的一半    
            part = self.max_pager_num//2
            if self.current_page <= part:
                return range(1,self.max_pager_num+1) # 返回 从 1 到 页码个数最大值
    
            # 如果当前页码加一半的页码 大于 总页数
            if (self.current_page+part) > self.num_pages:
                # 返回 从总页数-最大页码数 到 总页数      range的用法在此不作解释
                # 例如 96页+5页 超出总页数 则返回的范围是 从 总页数-最大页码数量+1 到 总页数+1    
                return range(self.num_pages-self.max_pager_num+1,self.num_pages+1)
    
            # 其余情况从 当前页码减去显示页码的平均值开始  到 当前页码加显示页码的平均值(并加一)结束
            return range(self.current_page-part,self.current_page+part+1)
    
    
    def index(request):
        p = request.GET.get('page')
        start = (int(p)-1)*10
        end = int(p)*10
        data = user[start:end]
        return render(request,'index.html',{'data':data,'user':user})
    
    
    def index1(request):
        current_page = request.GET.get('page')
        paginator = DiyPaginator(current_page, 9, user, 10)
        # Paginator所封装的方法
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
        try:
            posts = paginator.page(current_page)
            # has_next              是否有下一页
            # next_page_number      下一页页码
            # has_previous          是否有上一页
            # previous_page_number  上一页页码
            # object_list           分页之后的数据列表
            # number                当前页
            # paginator             paginator对象
        except PageNotAnInteger:      # 不是整形数字
            posts = paginator.page(1)
        except EmptyPage:             # 如果是空值
            posts = paginator.page(paginator.num_pages)
    
        return render(request,'index1.html',{'posts':posts})
    扩展内置分页
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            {% for row in posts.object_list %}
                <li>{{ row.name }}-{{ row.pwd }}</li>
            {% endfor %}
        </ul>
        {% include 'include/pager.html' %}
    </body>
    </html>
    
    ##################################
    include 组件代码
    
    {% if posts.has_previous %}
        <a href="/index1?page={{ posts.previous_page_number }}">上一页</a>
    {% endif %}
    
    {% for num in posts.paginator.pager_num_range %}
        {% if num == posts.number %}
            <a style="color: red;font-size: 20px" href="/index1?page={{ num }}">{{ num }}</a>
        {% else %}
            <a href="/index1?page={{ num }}">{{ num }}</a>
        {% endif %}
    {% endfor %}
    
    {% if posts.has_next %}
        <a href="/index1?page={{ posts.next_page_number }}">下一页</a>
    {% endif %}
    <span>
        当前页:{{ posts.number }}&nbsp;&nbsp;总页数:{{ posts.paginator.num_pages }}
    </span>
    扩展内置分页:HTML

     

    三、自定义分页(适用于任何地方)

    • 创建处理分页数据的类
    • 根据分页数据获取数据
    • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]或者额外的作出一些拓展也可以

    创建处理分页数据的类时,大致也需要四个参数(详情观看类构造方法)

      1、为了减少服务器内存的负载,不再获取所有数据的,而是获得所有数据的总个数,然后再根据索引查数据库的内容

      2、当前页码

      3、每页显示的行数

      4、页码显示的数量

    对于页数的显示大致也可以归类为三种情况(详情观看类中page_num_range函数)

      1、计算的总页数小于页码显示的数量

      2、计算的总页数大于页码显示的数量

        A、当前页数小于页码数量的一半

        B、当前页数加页码数量的一半超出总页数的范围

      3、正常情况

        从 当前页数 减 一半页码数量 到 当前页数 加 一半页码数量

     示例:

    首先,先建一个文件包取名为utils,并在改文件包下建一个pager.py的文件:

    views.py

    from django.shortcuts import render,HttpResponse
    from django.views import View
    from app01 import models
    from django.core.paginator import Paginator,Page,PageNotAnInteger,EmptyPage
    # 自定义页码
    from utils.pager import Pageinfo
    def custom(request):
        # 1、首先查询所有的用户信息的数据总个数
        all_count=models.Userinfo.objects.all().count()
    
        page_info = Pageinfo(request.GET.get('page'), all_count, 10, '/custom.html', 11)
        user_list = models.Userinfo.objects.all()[page_info.start():page_info.end()]
        return render(request,"custom.html",{"user_list":user_list,"page_info":page_info})
    

    pager.py

    class Pageinfo(object):
        def __init__(self,current_page,all_count,per_page,base_url,show_page=11):
        # current_page指的是当前页,all_count所有数据的总个数,per_page每一页有多少数据,base_url跳转的url,show_page=11每次共显示11个页码
            """
            分页
            :param current_page: 指的是当前页
            :param all_count:  数据库总行数
            :param per_page: 每一页有多少数据
            :param base_url: 跳转的url
            :param show_page: 每次共显示11个页码
            """
            try:
                self.current_page=int(current_page)
            except Exception as e:
                self.current_page=1
            self.per_page=per_page
            a,b=divmod(all_count,per_page)#用数据库的总行数除以每一页有多少数据
            # 如果整除的话,即余数为0,则:
            if b:#如果b有值的话
                self.all_pager=a+1
            else:
                self.all_pager=a
    
            self.show_page=show_page
            self.base_url=base_url
        def start(self):
            """
            定义开始的行数,举例:如果点击的是第二页,(2-1)*10=10,是从第10条数据开始
            :return: 返回上一行结尾的数据
            """
            return (self.current_page-1)*self.per_page
    
        def end(self):
            """
            取的是结束的数据,用当前页乘以一页有10条数据
            举例:如果点击的是第二页,2*10=20,是第20条数据结束
            :return: 
            """
            return self.current_page*self.per_page
    
        def pager(self):
            page_list=[]
            half=int((self.show_page-1)/2)
            # 如果总页数小于所应该展示的页数,例:如果总页数是5页,但是要求展示11条,总页数<11
            if self.all_pager<self.show_page:
                begin=1
                stop=self.all_pager+1#因为下面的for循环取值是左取右不取
    
            else:# 当总页数大于11页
                # 但是当点击的当前页<5的话,则应该显示1-11页
                if self.current_page<=half:
                    begin=1
                    stop=self.show_page+1
                else:#当点击的当前页大于5
                    if self.all_pager-self.current_page<half:
                    #当总页数减去点击的当前页<5的话,则应该显示后11条数据
                        begin=self.all_pager-self.show_page+1
                        stop=self.all_pager+1
                    else:
                        begin=self.current_page-half
                        stop=self.current_page+half+1
              #再判断一些特殊情况
            if self.current_page<=1:
                prev = "<li><a href='#'>上一页</a></li>"#点击上一页不跳动,还是当前状态
            else:#否则跳转到上一页
                prev="<li><a href='%s?page=%s'>上一页</a></li>"% (self.base_url,self.current_page-1,)
    
            page_list.append(prev)
    
            for i in range(begin,stop):
                if i==self.current_page:
                    # 如果点到当前页的话,则让点击的页码的颜色改变
                    temp="<li class='active'><a  href='%s?page=%s'>%s</a></li>" %(self.base_url,i,i,)
                else:
                    temp = "<li><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i,)
                page_list.append(temp)
    
            if self.current_page>=self.all_pager:
                after="<li><a href='#'>下一页</a></li>"#点击下一页不跳动,还是当前状态
            else:#否则跳转到下一页
                after = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url, self.current_page + 1,)
            page_list.append(after)
    
    
            return ''.join(page_list)

    custom,html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" />
    </head>
    <body>
    <h1>用户列表</h1>
    <ul>
        {% for i in user_list %}
            <li>{{ i.username }}</li>
        {% endfor %}
    </ul>
    
    <nav aria-label="Page navigation">
        <ul class="pagination">
            {{ page_info.pager|safe }}
        </ul>
    </nav>
    </body>
    </html>
    

    最终的执行结果是:(页面展示)

     

     

  • 相关阅读:
    Mac 安装 Python3
    在push的时候发生崩溃信息
    Swift3.0 和 Swift3.0.2的区别
    01- 简单值
    @objc || private || 按钮的点击事件
    extension的作用
    swift3.0中使用代码添加选中图片
    OC-创建瀑布流
    springboot项目控制台日志不是彩色的原因
    更改docker里mysql的字符编码
  • 原文地址:https://www.cnblogs.com/xuyuanyuan123/p/7106350.html
Copyright © 2011-2022 走看看