Day 08 表单创建及查询
一、多表操作之模型创建
首先整理相关关系(逻辑上存在错误o(╥﹏╥)o)
Models
from django.db import models
# Create your models here.
class Company(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
address = models.CharField(max_length=254)
leader = models.CharField(max_length=32)
class Department(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32, unique=True)
task = models.CharField(max_length=32)
established = models.DateTimeField()
# to='Employee'Employee(ForeignKey,一对多)
# to_field='id'跟哪个字段做关联
# ForeignKey对到数据中的字段是int类型
# employee=models.ForeignKey(to='Publish',to_field='id')
# employee = models.ForeignKey(to='Publish') # 不写,默认跟主键做关联
employee = models.ForeignKey(to='Employee') # 一个部分拥有多个员工
company = models.ManyToManyField(to='Company') # 不同公司拥有相同部门
class Employee(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
gender = models.SmallIntegerField()
employee_detail = models.OneToOneField(to='EmployeeDetail', to_field='id', on_delete=models.CASCADE)
class EmployeeDetail(models.Model): # 无足轻重
id = models.AutoField(primary_key=True)
salary = models.IntegerField()
address = models.CharField(max_length=254)
phone = models.CharField(max_length=32)
6 同步到mysql数据库
-配置文件
-pymysql.install_as_mysqldb()
-公司可以用过的mysqlclient
-两条命令
7 2.x版本的django
-外键字段必须加 参数:on_delete
-1.x版本不需要,默认就是级联删除
-假设,
删除出版社,该出版社出版的所有图书也都删除,on_delete=models.CASCADE
删除出版社,该出版社出版的图书不删除,设置为空on_delete=models.SET_NULL,null=True
删除出版社,该出版社出版的图书不删除,设置为默认on_delete=models.SET_DEFAULT,default=0
批量写入文件(相关配置)
faker相关用法参考
import django, os, random, time
from faker import Faker
f = Faker(locale='zh-CN') # 设置成中国信息
a1 = (2000, 1, 1, 0, 0, 0, 0, 0, 0) # 设置开始日期时间元组(2020-01-01 00:00:00)
a2 = (2015, 12, 31, 23, 59, 59, 0, 0, 0) # 设置结束日期时间元组(2015-12-31 23:59:59)
start = time.mktime(a1) # 生成开始时间戳
end = time.mktime(a2) # 生成结束时间戳
t = random.randint(start, end) # 在开始和结束时间戳中随机取出一个
date_touple = time.localtime(t) # 将时间戳生成时间元组
date = time.strftime("%Y-%m-%d", date_touple) # 将时间元组转成格式化字符串(1976-05-21)
if __name__ == '__main__':
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Myproject07.settings")
django.setup()
from app01.models import *
二、基本写入文件
# 普通添加记录
job_list = []
for i in range(10):
Company.objects.create(
name=f.company(),
address=f.province() + f.street_address(),
leader=f.name(),
)
# 一对一添加记录,注意先后顺序
for i in range(40):
job_name = f.name()
job_list.append(job_name)
res = EmployeeDetail.objects.create(
salary=random.randint(8000, 15000),
address=f.address(),
phone=f.phone_number(),
)
Employee.objects.create(
name=f.name(),
gender=random.randint(0, 1),
employee_detail=res
)
三、一对多添加记录
for i in range(15):
t = random.randint(start, end) # 在开始和结束时间戳中随机取出一个
date_tuple = time.localtime(t) # 将时间戳生成时间元组
date = time.strftime("%Y-%m-%d", date_tuple) # 将时间元组转成格式化字符串
Department.objects.create(
name=f.job(),
task=f.job()[0:4],
established=date,
# 一对多文件写入 写入对象
employee=Employee.objects.get(id=random.randint(1, 40)),
# company=Company.objects.get(id=random.randint(115, 144))
# 这种方法暂时不要使用
#如果Model中包含多对多关系,那么就会报错:ValueError: “needs to have a value for field ”id“ before this many-to-many relationship can be used”解决办法是,先把data中的多对多数据取出,然后创建model,最后建立多对多关系。
)
由于多对多字段还没有创建,所以创建的关联表中是没有数据
四、多对多文件写入(相关api add ,remove,set clear)
1、通过id新增
company从115开始是因为我有这么多数据
# 1.首先我们要找到 含有多对多表的一个对象
# for i in range(10):
# department = Department.objects.get(id=i+1)
# # 可以添加 多个值
# department.company.add(random.randint(115, 144))
department = Department.objects.get(id=11)
# 可以添加 多个值
department.company.add(115, 120)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fx48UNKh-1602727694098)(C:\Users\S\AppData\Roaming\Typora\typora-user-images\image-20201014211026059.png)]
这样多对多的数据就写入进去了
2、通过对象添加字段
company1 = Company.objects.get(id=122)
company2 = Company.objects.get(id=126)
department = Department.objects.get(id=14)
# 可以添加 多个值
department.company.add(company1, company2)
# 同样可以混合添加
department.company.add(133, company2)
3、修改删除
3.1 删除(remove clear)
# 选择删除
department = Department.objects.get(id=14)
# 删除部门id为14 的company1 同样也可以为id
department.company.remove(company1)
# 全部删除
department = Department.objects.get(id=14)
# 删除部门id为14 所有的公司
department.company.clear()
注意:没有相关联的id也是不会报错的
3.2修改(set)
# set是先清空再添加作者
department = Department.objects.get(id=14)
department.company.add(133)
department.company.set({144: 122})
跨表查询有两种方式
-基于对象的跨表查询:子查询
-基于双下划线的跨表查询:关联查询,连表查询
五、基于对象的跨表查询(正向反向)
一对一查询(不适用set)
# 正向查询
# id为1的 职员 的电话号码
employee = Employee.objects.get(id=1)
employee_detail = employee.employee_detail
print(employee.name, employee_detail.phone)
# 反向查询
# 电话号码为 13653093989 的职员名字
employee_detail = EmployeeDetail.objects.get(phone='13653093989')
name = employee_detail.employee.name
print(name)
一对多查询
#1.查询主键为1的 部门 的 职员 所在的地址
# 1.查询主键为1的 部门 的 职员 所在的地址
department = Department.objects.get(id=1)
employee = department.employee # 找到id为i 对应的职员
employee_address = employee.employee_detail.address # 一对一查找他的信息找到地址
print(employee_address)
# 反向查找
# id为9的 职员 所在部门的名字
employee = Employee.objects.get(id=9)
department = employee.department_set.all().first().name
print(department)
多对多查询
# 正向
# 1. id为14的 部门 所对应的 公司 名字
department = Department.objects.get(id=14)
companys = department.company.all()
for i in companys:
print(i.name)
# 反向
# 2. 查询主键为124的 公司 的 所有部门 名称 这其实是反向查找,company上是没有关联键的,
#表名小写_set.方法()
company = Company.objects.get(id=124)
departments = company.department_set.all()
for i in departments:
print(i.name)
正向查找:
有关联表内的 关联字段 直接对象.字段名
反向查找(不适用一对一):
被关联表内没有关联字段 被关联表对象.关联表名小写_set.all()
六.基于双下划线的跨表查询
连表查询
基于对象的跨表查询,先查对象,通过对象再去查另一个对象(正向:字段名,反向:表名小写/表名小写_set.all())
一对多
正向:字段名 反向:表名小写 filter,values,values_list(写 __ 跨表)
# id为124公司名字 所有的部门名字,任务
# 反向
res1 = Company.objects.filter(id=124).values('department__name', 'department__task')
for i in res1:
print(i)
#正向
res2 = Department.objects.filter(company__id=124).values('name', 'task')
for i in res2:
print(i)
----------------------------------------------
{'department__name': '市场助理', 'department__task': '手机应用'}
{'department__name': '广告创意/设计主管/专员', 'department__task': '地勤人员'}
{'department__name': '救生员', 'department__task': '调研员'}
{'department__name': '磨工', 'department__task': '促销主管'}
多对多
#反向
# res=models.Author.objects.filter(name='egon').values('book__name','book__price')
# print(res)
# 正向
# res=models.Book.objects.filter(authors__name='egon').values('name','price')
# print(res)
#查询egon的手机号
# res=models.Author.objects.filter(name='egon').values('author_detail__phone')
# print(res)
# res=models.AuthorDetail.objects.filter(author__name='egon').values('phone')
# print(res)
七、进阶连续跨表查询
# 员工信息id为 7 的 员工所在的公司名字
res = EmployeeDetail.objects.get(id=7).employee.department_set.values('company__name', 'company__address')
print(res)
# 先找到 detail对象,一对一找到employee对象, 反向查找到 department对象 最后基于双下划线查询到具体
扩展
1 看一看这篇博客
https://www.cnblogs.com/nokiaguy/p/13803370.html
2 安装模块相关
pip3 install django
# 本质是去https://pypi.python.org/simple,搜这个模块,会根据你的平台下载在一个安装包(windows平台是whl),下载完,再安装
# pip安装失败的情况
# 我们可以绕过它,有了whl文件以后,自己装
# https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv
pip3 install django.whl
# 官方库没有上传到pypi,官方也不给制作whl文件
#如何安装 包 (setup.py)
到达安装目录,setup.py所在的目录
python setup.py build
python setup.py install
# 配置清华源,豆瓣源,本质是
豆瓣源会把pypi,包拉到自己的服务器上,以后你再下,去它的服务器上下,所以速度快
# 你自己写的包,如何上传到pypi上给别人使用?
2 外键关系要不要建立
1 关联字段与外键约束没有必然的联系(建管理字段是为了进行查询,建约束是为了不出现脏数据)
2 默认情况,关联关系建好以后,外键约束就自然建立了
3 实际工作中,外键约束一般不建(影响效率),都是人为约束(代码约束)
-db_constraint=False
4 表模型和数据库表的对应,不要直接修改表(这是可以的,但是不建议),要修改表模型,同步到表中