django之关系及查询,数据类型,约束,分页
关系
1. 一对一(水平分表)
母表:
UserInfo
id name age
子表:
private
id salary sp
创建模型语句:
class UserInfo(models.Model):
name = models.CharField(max_length=32, null=True)
age = models.IntegerField(null=True) class Private(models.Model):
salary = models.CharField(max_length=32, null=True)
sp = models.OneToOneField("UserInfo", null=True) # OneToOneField 一对一
创建数据:
models.UserInfo.objects.create(name="潘立府",age="18")
# 注意字段sp_id才是Private表的真实字段。sp则是一个对象
models.Private.objects.create(salary='50000',sp_id='1')
需求:从母表中查询子表中的数据(查询一下name='xxxx'的salary)
res = models.UserInfo.objects.filter(name='plf').first() # 语法: res.子表表名小写.子表字段名
print(res.private.salary)
需求:从子表中查询母表中的数据(查询一下salary=xxxx的姓名和年龄)
# 从子表查询母表中的数据
res = models.Private.objects.filter(salary=5000).first() # 语法: 对象.关联的字段.母表的字段
print(res.sp.name,res.sp.age)
2. 多对多
相亲的模型
Boy:
id name Girl:
id name
1 真真
2 连连
3 爱爱
4 凤姐
5 乔碧萝 boy2girl(bid和gid应该是联合唯一)
id bid gid
1 1 1
2 1 2
3 1 3
4 2 2
5 2 4
6 2 5建表语句:
# 第一种创建方式
"""
class Boy(models.Model):
bname = models.CharField(max_length=32,null=True) class Girl(models.Model):
gname = models.CharField(max_length=32,null=True) class Boy2Girl(models.Model):
b = models.ForeignKey("Boy",null=True)
g = models.ForeignKey("Girl",null=True) # 联合唯一索引
class Meta:
unique_together = [
('b','g')
] # 联合索引
#class Meta:
# index_together = [
# ('b','g')
# ]
""" # 第二种创建方式
"""
class UserInfo(models.Model):
name = models.CharField(max_length=32, null=True)
age = models.IntegerField(null=True) class Private(models.Model):
salary = models.CharField(max_length=32, null=True)
sp = models.OneToOneField("UserInfo", null=True) class Boy(models.Model):
bname = models.CharField(max_length=32,null=True)
g = models.ManyToManyField('Girl',null=True) class Girl(models.Model):
gname = models.CharField(max_length=32,null=True) """ # 两种方式的区别
'''
第一种方式比较的灵活,自己可以添加任意的字段 第二种方式比较死板,只能生成两个字段。如果将来业务扩展,就需要重新打破重来 因此,推荐使用第一种方式。
'''
创建数据:
boyinfo = [
models.Boy(bname='雷俊'),
models.Boy(bname='雷鸣'),
models.Boy(bname='雷震子'),
models.Boy(bname='雷锋'),
models.Boy(bname='雷军'), ]
models.Boy.objects.bulk_create(boyinfo) girlinfo = [
models.Girl(gname="真真"),
models.Girl(gname="练练"),
models.Girl(gname="爱爱"),
models.Girl(gname="凤姐"),
models.Girl(gname="乔碧萝"), ]
models.Girl.objects.bulk_create(girlinfo) b2ginfo = [
models.Boy2Girl(b_id=1,g_id=1),
models.Boy2Girl(b_id=1,g_id=2),
models.Boy2Girl(b_id=1,g_id=3),
models.Boy2Girl(b_id=2,g_id=4),
models.Boy2Girl(b_id=2,g_id=5),
models.Boy2Girl(b_id=1,g_id=5),
]
models.Boy2Girl.objects.bulk_create(b2ginfo) # 另类的创建数据的方式
bobj = models.Boy.objects.filter(bname='雷俊').first()
gobj = models.Boy.objects.filter(bname='乔碧萝').first() # 第一种
models.Boy2Girl.objects.create(b=bobj,g=gobj) # 第二种
models.Boy2Girl.objects.create(b_id=bobj.id,g_id=gobj.id)
需求:查找一下和雷俊约会的姑娘
# 第一种方式:从Boy表中开始查询
res = models.Boy.objects.filter(bname='雷俊').first()
# res 是一个对象: Boy object
res = res.boy2girl_set.all()
for i in res:
# i对象是 Boy2Girl 的对象
# i.g 是一个对象。然后直接使用.获取gname
print(i.g.gname)
print(res) # 第二种方式:从Boy2Girl表开始查询
res = models.Boy2Girl.objects.filter(b__bname='雷俊').all()
print(res)
for love in res:
print(love.g.gname) # 第三种方式:在第二种方式的基础上进行改进
res = models.Boy2Girl.objects.filter(b__bname='雷俊').values('g__gname')
print(res)
'''
<QuerySet [{'g__gname': '真真'}, {'g__gname': '练练'}, {'g__gname': '爱爱'}, {'g__gname': '乔碧萝'}]>
''' # 第四种方式:
res = models.Boy.objects.filter(bname='雷俊').values('boy2girl__g__gname')
print(res)
数据列类型
数字类型(重点)
mysql orm tinyint 不存在 smallint SmallIntegerField mediumint 不存在 int(unsigned) IntegerField(PositiveIntegerField) bigint(unsigned) BigIntegerField(PositiveBigIntegerField) decimal DecimalField float FloatField double 不存在 字符串
mysql orm char 不存在 varchar CharField text TextField 时间
mysql orm date DateField datetime DateTimeField orm中数据类型:
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 上传图片的宽度保存的数据库字段名(字符串)
数据类型的约束
参数
mysql约束
null 数据库中字段是否可以为空
db_column 数据库中字段的列名
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
orm约束
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'), ]
)
分页
一:django内置分页
urls.py
urlpatterns = [
url(r'^test2/', views.test2),
]
views.py
def test2(request): cur_page = request.GET.get('cur_page')
print(cur_page,type(cur_page))
cur_page = int(cur_page)
userlist = models.UserInfo.objects.all()
from django.core.paginator import Paginator
paginator = Paginator(userlist,10)
users = paginator.page(cur_page) return render(request,'index.html',{'users':users}) # paginator拥有的属性
# per_page :每页显示的条目的数量
# count :数据总个数
# num_pages :总页数
# page_range:总页数的索引范围 如:(1,10),(1,200)
# page :page对象 # users拥有的属性
# has_next 是否有下一页
# next_page_number 下一页页码
# has_previous 是否有上一页
# previous_page_number 上一页页码
# object_list 分页之后的数据列表
# number 当前页
# paginator paginator对象
index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <ul> {% for foo in users.object_list %}
<li>{{ foo.name }}</li>
{% endfor %} {% if users.has_previous %}
<a href="/test2/?cur_page={{ users.previous_page_number }}">上一页</a>
{% endif %} {% for num in users.paginator.page_range %}
<a href="/test2/?cur_page={{ num }}">{{ num }}</a>
{% endfor %} {% if users.has_next %}
<a href="/test2/?cur_page={{ users.next_page_number }}">下一页</a>
{% endif %} </ul> </body>
</html>
二:自定义分页
urls.py
urlpatterns = [
url(r'^test3/', views.test3),
]
views.py
class PageInfo():
def __init__(self,cur_page,total,per_page=10,show_page=11):
self.cur_page = cur_page # 当前页
self.per_page = per_page # 一页显示多少行数据
self.total = total # 总数据有多少行
self.show_page = show_page # 页面显示多少索引 a,b = divmod(self.total,self.per_page) if b:
a = a + 1
self.total_page = a # 总页数 def get_start(self):
start = (self.cur_page - 1) * self.per_page
return start def get_end(self):
return self.cur_page * self.per_page def get_page(self):
half = (self.show_page - 1) // 2 #### taotal_page = 5 < show_page = 11
if self.total_page < self.show_page:
begin = 1
end = self.total_page
else:
#### 左边极值判断
if self.cur_page - half <= 0:
begin = 1
# end = self.cur_page + half
end = self.show_page
#### 右边极值的判断
elif self.cur_page + half > self.total_page:
# begin = self.cur_page - half
begin = self.total_page - self.show_page + 1
end = self.total_page ### 31
#### 正常页码判断
else:
begin = self.cur_page - half
end = self.cur_page + half page_list = []
if self.cur_page == 1:
astr = "<li><a href='#' aria-label='Previous'><span aria-hidden='true'>«</span></a></li>"
else:
astr = "<li><a href='/test3/?cur_page=%s' aria-label='Previous'><span aria-hidden='true'>«</span></a></li>" % (
self.cur_page - 1)
page_list.append(astr) for i in range(begin, end + 1):
if self.cur_page == i:
# astr = "<a style='display:inline-block; padding:5px;margin:5px;background-color:red;' href='/custom/?cur_page=%s'>%s</a>" % (i, i)
astr = "<li class='active'><a href='/test3/?cur_page=%s'>%s</a></li>" % (i, i)
else:
# astr = "<a style='display:inline-block; padding:5px;margin:5px' href='/custom/?cur_page=%s'>%s</a>" % (i, i)
astr = "<li><a href='/test3/?cur_page=%s'>%s</a></li>" % (i, i)
page_list.append(astr) if self.cur_page == self.total_page:
astr = "<li><a href='#' aria-label='Next'><span aria-hidden='true'>»</span></a></li>"
else:
astr = "<li><a href='/test3/?cur_page=%s' aria-label='Next'><span aria-hidden='true'>»</span></a></li>" % (
self.cur_page + 1)
page_list.append(astr) s = " ".join(page_list) return s def test3(request): # mysql中limit的分页公式
'''
cur_page: 当前页
show_page_num: 显示多少页
start_page: 起始页 limit 起始位置a, 显示多少页b
a = ( cur_page - 1 ) * show_page_num
b = show_page_num
''' # 在django中的分页公式(models.UserInfo.objects.filter(id__lte=44)[start:end])
"""
show_page_num = 10
cur_page = 1 start = 0 end = 10
cur_page = 2 start = 10 end = 20
cur_page = 3 start =20 end = 30 start = (cur_page - 1) * show_page_num
end = cur_page * show_page_num
"""
cur_page = request.GET.get("cur_page")
cur_page = int(cur_page) total = models.UserInfo.objects.count() obj = PageInfo(cur_page,total) start = obj.get_start()
end = obj.get_end() # 获取总数据
user_list = models.UserInfo.objects.all()[start:end] return render(request,'custom.html',{"user_list":user_list,"page":obj})
custom.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <ul> {% for foo in users.object_list %}
<li>{{ foo.name }}</li>
{% endfor %} {% if users.has_previous %}
<a href="/test2/?cur_page={{ users.previous_page_number }}">上一页</a>
{% endif %} {% for num in users.paginator.page_range %}
<a href="/test2/?cur_page={{ num }}">{{ num }}</a>
{% endfor %} {% if users.has_next %}
<a href="/test2/?cur_page={{ users.next_page_number }}">下一页</a>
{% endif %} </ul> </body>
</html>
django之关系及查询,数据类型,约束,分页的更多相关文章
- Django项目:CRM(客户关系管理系统)--21--13PerfectCRM实现King_admin分页页数
{#table_data_list.html#} {## ————————08PerfectCRM实现King_admin显示注册表的字段表头————————#} {% extends 'king_m ...
- Django项目:CRM(客户关系管理系统)--19--11PerfectCRM实现King_admin分页显示条数
登陆密码设置参考 http://www.cnblogs.com/ujq3/p/8553784.html list_per_page = 2 #分页条数 list_per_page = 2 #分页条数 ...
- Django 之多表查询 与多表的使用
1.django的多表查询 主要区分为: 正向查询 逆向查询 1. 多表查询: 是一个复杂的查询,他分为对象查询和__模糊查询两种方式 2. 多表查询: 又分为 一对一查询, 一对多查询, 多对 ...
- Django多条件筛选查询
转自:https://www.jianshu.com/p/a86281df530e Django多条件筛选查询 主模型只存在外键一对多关系 模型设计 # 快捷筛选状态 class Status(mod ...
- Lucene查询索引(分页)
分页查询只需传入每页显示记录数和当前页就可以实现分页查询功能 Lucene分页查询是对搜索返回的结果进行分页,而不是对搜索结果的总数量进行分页,因此我们搜索的时候都是返回前n条记录 package c ...
- django之跨表查询及添加记录
一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many); 一本书只应该由一个出版商出 ...
- Django的ORM常用查询操作总结(Django编程-3)
Django的ORM常用查询操作总结(Django编程-3) 示例:一个Student model: class Student(models.Model): name=models.CharFiel ...
- Django框架----跨表查询及添加记录
一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many); 一本书只应该由一个出版商出 ...
- Django框架 之 ORM查询操作详解
Django框架 之 ORM查询操作详解 浏览目录 一般操作 ForeignKey操作 ManyToManyField 聚合查询 分组查询 F查询和Q查询 事务 Django终端打印SQL语句 在Py ...
随机推荐
- python3读取、写入、追加写入excel文件
由于excel版本不同,python处理的时候选择的库页不同. 一.操作对应版本表格需要用到的库 1.操作xls格式的表格文件,需要用到的库如下: 读取:xlrd 写入:xlwt 修改(追加写入):x ...
- SQL操作DBF
--从SQL Server查询器预览dBase 文件中数据select * from openrowset('MICROSOFT.ACE.OLEDB.12.0','dBase 5.0;database ...
- (转)DNS使用的是TCP协议还是UDP协议
转自:DNS使用的是TCP协议还是UDP协议 DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类.但很少有人知道DNS分别在什么情况下 ...
- SSL扫描工具
工具: sslciphercheck sslscan sslciphercheck.exe -h ip -p 443 有些IP会报错:
- Pandas初体验之数据结构——Series和DataFrame
Pandas是为了解决数据分析任务而创建的,纳入了大量的库和标准数据模型,提供了高效地操作大型数据集所需的工具. 对于Pandas包,在Python中常见的导入方法如下: from pandas im ...
- 剑指offer 面试题. 二叉搜索树的第k个结点
题目描述 给定一棵二叉搜索树,请找出其中的第k小的结点.例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4. 解: 由于二叉搜索树的中序遍历是升序,所以在中 ...
- vue mvvm原理与简单实现 -- 上篇
Object.defineProperty介绍-- let obj = {}; Object.defineProperty(obj,'school',{ configurable : true, // ...
- es2.0的语法学习
确定文档和查询有多么相关的过程被称为打分(scoring):将查询作为输入,使用不同的手段来确定每一篇文档的得分,将每一个因素最后通过公式综合起来,返回该文档的最终得分.这个综合考量的过程,就是我们希 ...
- VS2015+EF+MySql问题
1.出现框架不兼容问题: 解决方法:a.在web.config或者app.config中加入所示代码: b.引用mysqlConnector.net中的所有dll,一般路径在D:\Program Fi ...
- centos安装虚拟机,桥接网络连接失败
centos安装虚拟机,桥接网络连接失败 待办 即使是虚拟机也要在网络选择网桥连接方式之后,点击连接网线才可以,虚拟机都是按照有线进行连接的.