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等诸多功能. ...
随机推荐
- 【C++】深度探索C++对象模型读书笔记--Data语意学(The Semantics of data)
1. 一个空类的大小是1 byte.这是为了让这一类的两个对象得以在内存中配置独一无二的地址. 2. Nonstatic data member 放置的是“个别的class object”感兴趣的数据 ...
- [LeetCode] Climbing Sairs
You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...
- dom对象转成jquery对象时候 变成数组 jquery转成dom时候 取数组第一个
- 【Java】自动获取某表某列的最大ID数
使用场景: 当需要往数据库插入数据时,表的主键需要接着已经有的数据后面进行自增.比如已经wq_customer表里,主键为TBL_ID,如果是空表,那么插入的数据TBL_ID设置为1,如果已经有n条数 ...
- mysql安装使用详细教程
1.数据库存储数据的方式与Excel类似. 一.数据库介绍 1.什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库, 每个数据库都有一个或多个不同的API用于创建,访 ...
- C#中string[]数组和list<string>泛型的相互转换 【转】
http://www.cnblogs.com/szjdw/archive/2012/03/09/2387885.html 1,从System.String[]转到List<System.Stri ...
- Unity3D for VR 学习(4): 自绘摄像机的视口区域锥体
在Unity Editor下,当选择Camera组件后,可呈现出Camera视口区域锥体,非常方便.但是当选择其他物体,如Cube后,就无法得知是否在Camera市口区内了,这里我找到了雨松MOMO的 ...
- MySQL数据库无法远程连接的解决办法
远程登陆数据库的时候出现了下面出错信息: ERROR 2003 (HY000): Can't connect to MySQL server on 'xxx.xxx.xxx.xxx', 经过今天下午的 ...
- 洛谷 P2498 [SDOI2012]拯救小云公主 解题报告
P2498 [SDOI2012]拯救小云公主 题目描述 英雄又即将踏上拯救公主的道路-- 这次的拯救目标是--爱和正义的小云公主. 英雄来到\(boss\)的洞穴门口,他一下子就懵了,因为面前不只是一 ...
- Linux下chkconfig命令详解--(启动或停止)和查询系统服务的运行级信息
chkconfig命令主要用来更新(启动或停止)和查询系统服务的运行级信息.谨记chkconfig不是立即自动禁止或激活一个服务,它只是简单的改变了符号连接. 使用语法:chkconfig [--ad ...