ORM是“对象-关系-映射”的简称,主要作用是定义模型类以及属性。每个模型都可以被映射为数据库中的一个数据表,而类属性被映射为为数据字段。
models 编码风格
from django.db import models
class ModelName(models.Model):
field1 = models.xxfield(..)
field2 = models.xxfield(..)
...
class Meta:
db_table = ...
other_metas = ...
creat
# 创建表sql
CREATE TABLE employee(
id INT PRIMARY KEY auto_increment ,
name VARCHAR (20),
gender BIT default 1,
birthday DATA ,
department VARCHAR (20),
salary DECIMAL (8,2) unsigned,
);
# 创建表ORM
class Employee(models.Model):
id=models.AutoField(primary_key=True)
name=models.CharField(max_length=32)
gender=models.BooleanField()
birthday=models.DateField()
department=models.CharField(max_length=32)
salary=models.DecimalField(max_digits=8,decimal_places=2)
增删改查
# 添加表数据sql
INSERT employee (name,gender,birthday,salary,department)
VALUES ("alex",1,"1985-12-12",8000,"保洁部");
# 添加表数据ORM
emp=Employee(name="alex",gender=True,birthday="1985-12-12",epartment="保洁部")
emp.save()
# 查询表数据sql
SELECT * FROM employee WHERE age=24;
# 查询表数据ORM
Employee.objects.filter(age=24)
# 更新表数据sql
UPDATE employee SET birthday="1989-10-24" WHERE id=1;
# 更新表数据ORM
Employee.objects.filter(id=1).update(birthday="1989-10-24")
# 删除表数据sql
DELETE FROM employee WHERE name="alex"
# 删除表数据ORM
Employee.objects.filter(name="alex").delete()
说明
1、表名称是自动生成的,如果需要自定义表名,需要在model的Meta类中指定 db_table 参数,建议使用小写表名,特别是使用MySQL作为后端数据库时。
2、id字段是自动添加的,如果想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 即可。如果Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列。
3、Django会根据配置文件中指定的数据库后端类型来生成相应的SQL语句,支持MySQL5.5及更高版本。
假设一个公司有多个员工,多个员工隶属于一个公司。
可以用foreign key来指定多对一的关系
# models.py
class Department(models.Model): # 主表
dep_name = models.CharField(max_length=20,verbose_name='部门名称')
desc = models.CharField(max_length=20,verbose_name='部门描述')
class Meta: # 从表
verbose_name = "部门表"
verbose_name_plural = verbose_name
db_table = 'department'
def __str__(self):
return self.dep_name
class Employee(models.Model):
emp_name = models.CharField(max_length=20,verbose_name='姓名')
job = models.CharField(max_length=20,verbose_name='职位')
salary = models.IntegerField(verbose_name='工资')
dapartment = models.ForeignKey(to=Department, on_delete=models.CASCADE, verbose_name='部门')
class Meta:
verbose_name = "员工表"
verbose_name_plural = verbose_name
db_table = 'employee'
def __str__(self):
return self.emp_name
# views.py
class DepartmentView(View):
def get(self,request):
department = Department.objects.all()
return render(request,'department.html',{'department':department})
<以下代码为增加操作,上面的代码为方便写路由>
def post(self,request):
emp_name = request.POST.get('emp_name')
job = request.POST.get('job')
salary = request.POST.get('salary')
dapartment = request.POST.get('dapartment')
try:
Employee.objects.create(
emp_name=emp_name,
job=job,
salary=salary,
dapartment_id=dapartment)
except Exception as e:
print(e)
return HttpResponse("添加失败")
return redirect('/dep/')
# url路由
path('dep/',views.DepartmentView.as_view()),
# 删
class DelEmployeeView(View):
def get(self,request,id):
employee_data = Employee.objects.get(id=id)
dep_id = employee_data.dapartment_id
employee_data.delete()
return redirect(f'/emp/{dep_id}')
# url路由
path('delemp//' ,views.DelEmployeeView.as_view()),
# 改
class UpdateEmployeeView(View):
def get(self,request,id):
try:
employee_data = Employee.objects.get(id=id)
except Exception as e:
print(e)
return HttpResponse("页面不存在")
return render(request,'index.html',{'employee':employee_data})
def post(self,request,id):
emp_name = request.POST.get('emp_name')
job = request.POST.get('job')
salary = request.POST.get('salary')
dapartment = request.POST.get('dapartment')
try:
Employee.objects.filter(id=id).update(
emp_name = emp_name,
job = job,
salary = salary,
dapartment_id = dapartment
)
except Exception as e:
print(e)
return HttpResponse('修改数据失败')
return redirect('/dep/')
# url路由
path('updateemp//' ,views.UpdateEmployeeView.as_view())
# 点击主表某字段以获取从表对应信息
class EmployeeView(View):
def get(self,request,id):
employee = Employee.objects.filter(dapartment_id=id)
return render(request,'employee.html',{'employee':employee})
# url路由
path('emp//' ,views.EmployeeView.as_view()),
假设一个人只能有一个对象,一个人不能有多个对象
使用OneToOneField用来定义一对一关系
主表查子表将子表名小写
子表查主表直接用连接的字段来查即可
假设一个音乐家隶属于多个乐队,而一个乐队有多个音乐家。
使用ManyToManyField字段定义
数据的添加
模型类.objects.create(需要添加的字段=‘’)
乐队 = 表名.objects.create(表名小写_name=“Jack”)
数据的删除
乐队.表名.remove(音乐家)
数据的查询
主表查子表
主表.band_set.all()
子表查主表
子表.主表字段.all()
字段名 | 详解 |
---|---|
AutoField | int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。 |
IntegerField | 一个整数类型,范围在 -2147483648 to 2147483647。(一般不用它来存手机号(位数也不够),直接用字符串存 |
CharField | 字符类型,必须提供max_length参数, max_length表示字符长度。Django中的CharField对应的MySQL数据库中的varchar类型,没有设置对应char类型的字段 |
DateField | 日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。 |
DateTimeField | 日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。 |
字段参数 | |
null | 用于表示某个字段可以为空。 |
unique | 如果设置为unique=True 则该字段在此表中必须是唯一的 。 |
db_index | 如果db_index=True 则代表着为此字段设置索引。 |
default | 为该字段设置默认值。 |
auto_now_add | DateField和DateTimeField,配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。 |
auto_now | 配置上auto_now=True,每次更新数据记录的时候会更新该字段。 |
关系字段 | |
ForeignKey | 外键类型在ORM中用来表示外键关联关系,一般把ForeignKey字段设置在 '一对多’中’多’的一方。ForeignKey可以和其他表做关联关系同时也可以和自身做关联关系。 |
字段参数 | |
to | 设置要关联的表。 |
to_field | 设置要关联的字段 |
on_delete | 当删除关联表中的数据时,当前表与其关联的行的行为。(参考上面的例子) |
ManyToManyField | 用于表示多对多的关联关系。在数据库中通过第三张表来建立关联关系 |
related_name | 同ForeignKey字段 |
related_query_name | 同ForeignKey字段。 |
symmetrical | 仅用于多对多自关联时,指定内部是否创建反向操作的字段。默认为True。 |
through | 在使用ManyToManyField字段时,Django将自动生成一张表来管理多对多的关联关系。但我们也可以手动创建第三张表来管理多对多关系,此时就需要通过through来指定第三张表的表名。 |
through_fields | 设置关联的字段。 |
db_table | 默认创建第三张表时,数据库中表的名称。 |
这里的 CreatedTime和uLastUpdatedTime存到数据库中的时间总是UTC时区的时间(比北京时间慢了8个小时)。如果不需要在程序中特别处理时区(timezone-aware),显示为北京时间,就要把时区关闭:
将全局设置settings.py中的USE_TZ = True 改为 USE_TZ = False 即关闭时区
如果还要保持USE_TZ=True,则可设置为CreatedTime = models.DateTimeField(default=datetime.now().replace(tzinfo=utc))。
Meta类封装了一些数据库的信息
字段名 | 详解 |
---|---|
db_table | ORM在数据库中的表名默认是 app_类名,可以通过db_table可以重写表名。 |
index_together | 联合索引 |
unique_together | 联合唯一索引,unique_together这个选项用于:当你需要通过两个字段保持唯一性时使用。比如假设你希望,一个Person的FirstName和LastName两者的组合必须是唯一的,那么需要这样设置:unique_together = ((“first_name”, “last_name”),) 一个ManyToManyField不能包含在unique_together中。如果你需要验证关联到ManyToManyField字段的唯一验证,尝试使用signal(信号)或者明确指定through属性。 |
ordering | 指定默认按什么字段排序。ordering=[‘order_date’] # 按订单升序排列ordering=[‘-order_date’] # 按订单降序排列,-表示降序ordering=[‘?order_date’] # 随机排序,?表示随机ordering=[‘-pub_date’,‘author’] # 以pub_date为降序,在以author升序排列 |
verbose_name | verbose_name的意思很简单,就是给你的模型类起一个更可读的名字一般定义为中文,我们:verbose_name = “学校” |
verbose_name_plural | 这个选项是指定,模型的复数形式是什么,比如:verbose_name_plural = "学校"如果不指定Django会自动在模型名称后加一个’s’ |
abstract | Options.abstract 这个属性是定义当前的模型是不是一个抽象类。所谓抽象类是不会对应数据库表的。一般我们用它来归纳一些公共属性字段,然后继承它的子类可以继承这些字段。如果abstract = True 这个model就是一个抽象类 |
app_label | 这个选型只在一种情况下使用,就是你的模型不在默认的应用程序包下的models.py文件中,这时候需要指定你这个模型是哪个应用程序的。如果一个model定义在默认的models.py,例如如果你的app的models在myapp.models子模块下,你必须定义app_label让Django知道它属于哪一个app,app_label = ‘myapp’ |
db_teblespace | 定义这个model所使用的数据库表空间。如果在项目的settin中定义那么它会使用这个值 |
get_latest_by | 在model中指定一个DateField或者DateTimeField。这个设置让你在使用model的Manager上的lastest方法时,默认使用指定字段来排序 |
managed | 默认值为True,这意味着Django可以使用syncdb和reset命令来创建或移除对应的数据库。默认值为True,如果你不希望这么做,可以把manage的值设置为False |
order_with_respect_to | 这个选项一般用于多对多的关系中,它指向一个关联对象,就是说关联对象找到这个对象后它是经过排序的。指定这个属性后你会得到一个get_xxx_order()和set_xxx_order()的方法,通过它们你可以设置或者回去排序的对象 |
permissions | permissions主要是为了在Django Admin管理模块下使用的,如果你设置了这个属性可以让指定的方法权限描述更清晰可读。Django自动为每个设置了admin的对象创建添加,删除和修改的权限。 |
proxy | 这是为了实现代理模型使用的,如果proxy = True,表示model是其父的代理 model |