一对一,多对多,数据表类型mysql和orm的区别,django-admin ,内置分页,自定义分页
表对表的一对一多对一关系
1. 一对一
models.py
oneTooneField
views.py:
##### 从母表查询子表的数据
### 反向查询
res.子表表名小写.子表的字段名
#### 从子表查询母表的数据
### 正向查询
res.关联字段.母表的字段名
2. 多对多:
models.py:
class Boy(models.Model):
bname = models.CharField(max_length=32)
class Girl(models.MOdel):
gname = models.CharField(max_length=32)
class b2g(models.MOdel):
b = models.ForeignKey("Boy", null=True)
g = models.ForeignKey("Girl", null=True)
views.py:
bulk_create()
添加数据的时候, 两种方式:
bobj = models.Boy.objects.filter(bname='雷俊').first()
gobj = models.Girl.objects.filter(gname='乔碧萝').first()
# models.Boy2Girl.objects.create(b_id=bobj.id, g_id=gobj.id)
models.Boy2Girl.objects.create(b=bobj, g=gobj)
1. 自己写第三张表
查询:
查询和雷俊约会的姑娘
#### 需求: 查找一下和雷俊约会的姑娘
#### 1.
# res = models.Boy.objects.filter(bname='雷俊').first()
# love_list = res.boy2girl_set.all()
# for love in love_list:
# print(love.g.gname)
#
##### 2.
# res = models.Boy2Girl.objects.filter(b__bname='雷俊').all()
# print(res) ### [obj, obj,....]
# for love in res:
# print(love.g.gname)
#
##### 3.
# res = models.Boy2Girl.objects.filter(b__bname='雷俊').values('g__gname').all()
# print(res) ### [{}]
2. 不写第三张表, 使用manytomanyfield
models.py:
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)
views.py:
res = models.Boy.objects.filter(bname='雷俊').first()
### 添加
# res.g.add(1)
# res.g.add(2,3)
### 删除
# res.g.remove(3)
### 查询
# res = models.Boy.objects.filter(bname='雷俊').first()
# print(res.g.all()) ####
### 清除
res.g.clear() ### 清空所有的记录
推荐:
第一种
因为第二种方式, 字段只能生成两个, 将来扩展的时候, 很不方便,需要重新打破字段
因此还是使用第一种方式,自定义创建第三张表
数据表类型
数字 | mysql | orm |
---|---|---|
tinyint | 不存在 | |
smallint | SmallIntegerField | |
mediumint | 不存在 | |
int(unsigned) | IntegerField PositiveIntegerField | |
bigint | BigIntegerField PositiveIntegerField | |
decimal | DecimalField | |
float | FloatField | |
字符串 | char | 不存在 |
varchar | Charfield | |
text | TextField | |
时间 | Date | DateField |
Datetime(2019-8-16 12:23:34 | DatetimeField |
参数
null : 是否为null
default: 默认值
primary_key: 是否为主键
db_index: 普通索引
unique: 唯一索引
db_column: 列名
class Meta:
### 联合唯一索引
unique_together = [
("b", 'g')
]
### 联合索引:
index_together = [
('b', 'g')
]
Django-admin:
首先先在里面添加内容:(在terminal >>>createsuperuser --用户名--密码)
from django.contrib import admin
# Register your models here.
from classes import models
admin.site.register(models.Test)
- django admin 数据类型中:(不是重点)
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 上传图片的宽度保存的数据库字段名(字符串)
- django admin 参数:
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'), ]
)
-
分页:
-
内置分页
res = Paginator(要分页的数据列表,每页显示的数据)users = res.page(当前页码) #### 当前页码的所有数据和属性
缺点:
只能将所有的页码循环的展示
-
views.py:
def test2(request):
# for i in range(296):
# name='root'+str(i)
# models.UserInfo.objects.create(name=name,age=20)
cur_page = request.GET.get('cur_page') ### 1
userlist = models.UserInfo.objects.all()
from django.core.paginator import Paginator
#
# # per_page: 每页显示条目数量
# # count: 数据总个数
# # num_pages:总页数
# # page_range:总页数的索引范围,如: (1,10),(1,200)
# # page: page对象
paginator = Paginator(userlist, 10)
#
# # has_next 是否有下一页
# # next_page_number 下一页页码
# # has_previous 是否有上一页
# # previous_page_number 上一页页码
# # object_list 分页之后的数据列表
# # number 当前页
# # paginator paginator对象
users = paginator.page(cur_page)
return render(request, 'index.html', {'users':users})
index.html:
<ul>
{% for user in users.object_list %}
<li>{{ user.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>
- 自定义分页:
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='/custom/?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='/custom/?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='/custom/?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='/custom/?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 custom(request):
cur_page = request.GET.get('cur_page')
cur_page = int(cur_page)
'''
mysql:
seelct * from userinfo limit 0, 10
seelct * from userinfo limit 10, 10
cur_page start show_page
1 0 10
2 10 10
3 20 10
n (n-1)*10, 10
limit (cur_page - 1) * show_page
'''
# total = models.UserInfo.objects.count()
total = models.UserInfo.objects.filter(id__lte=44).count()
page = PageInfo(cur_page, total)
start = page.get_start()
end = page.get_end()
### cur_page = 1 start = 0 end = 10
### cur_page = 2 start = 10 end = 20
### cur_page = 3 start =20 end = 30
# user_list = models.UserInfo.objects.all()[start:end]
user_list = models.UserInfo.objects.filter(id__lte=44)[start:end]
return render(request, "custom.html", {"user_list":user_list, "page":page})
custom.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Title</title>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<ul>
{% for user in user_list %}
<li>{{ user.name }}</li>
{% endfor %}
</ul>
<nav aria-label="Page navigation">
<ul class="pagination">
{{ page.get_page | safe}}
</ul>
</nav>
</body>
</html>
程序的道路上一去不复返