1.一对一
#models.py:
class UserInfo(models.Model):
name = models.CharField(max_length=32,null=True)
age = models.InterField(null=True)
class Private(models.Model):
salary = models.CharField(max_length=32,null=True)
sp = models.OneToOneField("UserInfo",null=True)
OneToOneField:一对一,默认要求该字段必须是唯一的外键关系(unique)
#views.py
from home impoort models
models.UserInfo.objects.create(name="zekai", age=18)
models.Private.objects.create(salary=5000,sp_id=1)
def test(request):
#从母表查询子表中的数据
## 查询一下name='zekai'的这条数据所对应的的salary
res = models.UserInfo.objects.filter(name="zekai").first()
#子表表名小写,子表字段名
print(res.private.salary)
#从子表查询母表中的数据
##查询一下salary = 5000的这个数据所对应的的用户的信息
res = models.Private.objects.filter(salary=5000).first()
#关联的字段名,母表的字段名
print(res.sp.name,res.sp.age)
2.多对多
#models.py
class Boy(models.Model):
bname = models.CharField(max_length=32null=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')
]
#views.py
boyinfo = [
models.Boy(bname="雷俊"),
models.Boy(banme="雷鸣"),
models.Boy(bname="雷震子"),
models.Boy(bname="雷锋"),
models.Boy(bname="雷军"),
]
models.Boy.objects.bulk_create(boyinfo)
grilinfo = [
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=1,g_id=5),
models.Boy2Girl(b_id=2,g_id=4),
models.Boy2Girl(b_id=2,g_id=5),
]
models.Boy2Girl.objects.bulk_create(b2ginfo)
#需求: 查找一下和雷俊约会的姑娘
#方法1:
res = models.BOy,objects.filter(bname="雷俊").first()
love_list = res.boy2girl_set.all()
for lover in love_list:
print(lover.g.gname)
#2.方法2:
res = models.Boy2Girl.objects.filter(b__bname="雷俊").all()
for lover in love_list:
print(lover.g.gname)
#3.方法3:
res = models.Boy2Girl.objects.filter(b__bname="雷俊").values('g__gname').all()
manytomanyfiled
#models.py:
class Boy(models.Model):
banme = 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)
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(banme="雷俊).first()
print(res.g.all())
##清除:
res.g.clear() ##清空所有记录
区别:
第一种方式比较的灵活,自己可以添加任意的字段;
第二种方式比较死板,只能生成两个字段,业务扩展时,就需要重新打破重来;推荐使用地中方式.
3.表中的数据类型
| 数字 |
mysql |
|
ORM |
|
tinyint |
|
不存在 |
|
smallint |
|
SmallIntegerField |
|
mediumintint |
|
不存在 |
|
int(unsigned) |
|
IntergerField | PositiveIntegerField |
|
bigint |
|
BigIntergerField | PositiveBigIntergerField |
|
decimal |
|
DecimalField |
|
float |
|
FloatField |
|
double |
|
不存在 |
| 字符串 |
char |
|
不存在 |
|
varchar |
|
CharField |
|
text |
|
TextField |
| 时间日期 |
date |
|
DateField |
|
datetime |
|
DateTimeField |
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 上传图片的宽度保存的数据库字段名(字符串)
参数:(掌握)
null 数据库中字段是否可以为空
db_column 数据库中字段的列名
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
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'), ]
)
python manage.py createsuperuser 创建超级用户
#admin.py
from home import models
admin.site.register(models.Test)
class Test(models.Model):
name = models.CharField(max_length=32, null=True, db_column='username', db_index=True, verbose_name='姓名',help_text=("提示信息"))
age = models.IntegerField(null=True, unique=True)
email = models.EmailField(null=True)
g = [
(1, 'male'),
(2, 'female')
]
gender = models.IntegerField(choices=g, default=1)
ip = models.GenericIPAddressField(null=True)
file = models.FileField(null=True)
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"),
],
null=True
)
4.分页
内置分页
127.0.0.1/test1/?cur_page=1/
#views.py
def test1(request):
# for i in range(300):
# name = "name" +str(i)
# models.UserInfo.objects.create(name=name,age=18)
cur_page = request.GET.get('cur_page')
userlist = models.UserInfo.objects.all()
from django.core.paginator import Paginator
# per page:每页显示条目数
# count:数据总个数
# num pages:总页数
#page range: 总页数的索引范围,如(1,200)
#page: page对象
paginator =Paginator(userlist,15)
# has next 是否下一页
# next page number 下一页页码
# has previous 是否上一页
# between page number 上一页页码
# object list 分页之后的数据类型
# number 当前页
# paginator paginator对象
users = paginator.page(cur_page)
return render(request,"index.html",{"users":users})
#index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for user in users.object_list %}
<li>{{ user.name }}</li>
{% endfor %}
{% if users.has_previous %}
<a href="/test1/?cur_page={{ users.previous_page_number }}">上一页</a>
{% endif %}
{% for num in users.paginator.page_range %}
<a href="/test1/?cur_page={{ num }}">{{ num }}</a>
{% endfor %}
{% if users.has_next %}
<a href="/test1/?cur_page={{ users.next_page_number }}">下一页</a>
{% endif %}
</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>