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_112233\d+', 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() # 修改单条数据
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的时候才执行。
示例:
- # ==========多对多的练习
- # 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_112233\d+', message='又错误了', code='c2'),
- EmailValidator(message='又错误了', code='c3'), ]
- )
三、多表关系及参数
- 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操作
- ##################################################################
- # 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': '','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': '','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):
- # 是否有结果
五、小结
- # 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)
B、设置数据表显示名称
- class UserType(models.Model):
- name = models.CharField(max_length=50)
- class Meta:
- verbose_name = '用户类型'
- verbose_name_plural = '用户类型'
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)
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)
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)
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)
分页
一、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 }} 总页数:{{ 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>
最终的执行结果是:(页面展示)
django框架<二>的更多相关文章
- MVC其实很简单(Django框架)
Django框架MVC其实很简单 让我们来研究一个简单的例子,通过该实例,你可以分辨出,通过Web框架来实现的功能与之前的方式有何不同. 下面就是通过使用Django来完成以上功能的例子: 首先,我们 ...
- Django框架-目录文件简介
Rhel6.5 Django1.10 Python3.5 Django框架-目录文件简介 1.介绍Django Django:一个可以使Web开发工作愉快并且高效的Web开发框架. 使用Django, ...
- Django框架学习
两个月前学习的Django框架,写了个简易婚恋调查网站,代码就懒得全贴了,有两张图记录下
- django框架的models
在django的框架设计中采用了mtv模型,即Model,template,viewer Model相对于传统的三层或者mvc框架来说就相当对数据处理层,它主要负责与数据的交互,在使用django框架 ...
- Windows上python开发--2安装django框架
Windows上python开发--2安装django框架 分类: 服务器后台开发2014-05-17 21:22 2310人阅读 评论(2) 收藏 举报 python django 上一篇文章中讲了 ...
- MySQL在Django框架下的基本操作(MySQL在Linux下配置)
[原]本文根据实际操作主要介绍了Django框架下MySQL的一些常用操作,核心内容如下: ------------------------------------------------------ ...
- django框架介绍
主要内容 1. Django框架发展 2. Django架构,MTV模式 3. 开发流程 4. 开发实例——Poll python下各种框架 一 ...
- Django学习(二) Django框架简单搭建
为了快速学习Python进行Web的开发,所以我不准备从Python的基础学起,直接从Django框架入手,边学框架边学Python的基础知识. 下面就开始Django的快速开发之旅吧. 关于Djan ...
- Django - Django框架 简单介绍
Django框架 简单介绍 本文地址: http://blog.csdn.net/caroline_wendy/article/details/29172271 1. 介绍 Django是一个开放源码 ...
- Django框架全面讲解
Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. ...
随机推荐
- vue render function
vue render function https://vuejs.org/v2/guide/render-function.html { // Same API as `v-bind:class`, ...
- Java内存区域介绍
Java虚拟机把内存划分成几个区域,每个区域都有各自的职责.下面将逐一分析每个区域. 有助于我们了解,每个方法,变量,对象等都去哪儿了! 程序计数器: 它占用一块很小的内存空间,可以看作是当前线程所执 ...
- wp如何代码重启手机
用过windows phone手机操作系统的人都知道,wp的系统设置界面很长一串,我们并不能快速进入想要的设置项,更受不了的是有些常用的设置项竟然在最下边.因为前段时间没事做,于是乎写了个wp的工具类 ...
- C++解析(2):进化后的 const 分析
0.目录 1.C语言中的const 2.C++中的const 3.对比 3.1 C语言与C++中的const 3.2 C++中的const与宏定义 4.小结 1.C语言中的const const修饰的 ...
- BZOJ3771 Triple 【NTT + 容斥】
题目链接 BZOJ3771 题解 做水题放松一下 先构造\(A_i\)为\(x\)指数的生成函数\(A(x)\) 再构造\(2A_i\)为指数的生成函数\(B(x)\) 再构造\(3A_i\)为指数的 ...
- Linux之Makefile20160707
说一下LINUX下的Makefile,直接根据实际碰到的Makefile进行解读: 当make的目标为all时,-C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile:M=$(PWD ...
- Java Socket TCP编程(Server端多线程处理)
package com; import java.io.*; import java.net.Socket; /** * Socket Client * <p> * Created by ...
- 服务器上 tomcat 配置了 tomcat-users 但是还是 403 的问题
默认情况下,tomcat 限制了只能本机访问 如果我们想要修改这个设置: 编辑 webapps/manager/META-INF/context.xml <!--<Valve classN ...
- jinja2 中的 Template 批量替换json字符串中的内容
项目中用到elasticsearch,使用Json格式查询方式,一个查询语句中有好几个地方需要替换,且替换的值都相同.最开始把json转为字符串发方式,利用format函数处理,发现再转回json时无 ...
- windows下MySQL 5.7+ 解压缩版安装配置方法--转载
方法来自伟大的互联网. 1.去官网下载https://dev.mysql.com/downloads/mysql/.zip格式的MySQL Server的压缩包,根据需要选择x86或x64版.注意:下 ...