ORM多表操作
urlpatterns = [ ... url(r'^add_book/', views.add_book, name='add_book'), #name属性对应的值,就是这个路径的别名 ]
首先在视图中引入反向解析的方法 from django.urls import reverse #url别名反向解析,通过name别名对应的数据,解析出我们的url路径 1 针对没有参数的别名 url(r'^add_book/', views.add_book, name='add_book'), 反向解析:reverse('book_list') 2 针对含有无名分组的url:url(r'^book_list/v2/(\d+)/(\d+)/', views.book_list, name='book_list'), 反向解析:reverse('book_list',args=(11,22)) 3 针对含有有名分组的url:url(r'^book_list/v2/(?P<year>\d+)/(?P<month>\d+)/', views.book_list, name='book_list'), 反向解析:reverse('book_list',kwargs={'year':2022,'month':11})
针对无参数的路径:url(r'^add_book/', views.add_book, name='add_book'), 反向解析:<a href="{% url 'add_book'%}" class="btn btn-primary">添加书籍</a> 这对有参数的路径:url(r'^add_book/(\d+)/(\d+)/', views.add_book, name='add_book'), url(r'^add_book/(?P<year>\d+)/(?P<month>\d+)/', views.add_book, name='add_book'), 反向解析: <a href="{% url 'add_book' 2020 12 %}" class="btn btn-primary">添加书籍</a>
ORM多表创建
from django.db import models class Author(models.Model): id = models.AutoField(primary_key=True) # 其实模型类中的id主键字段不需要我们手动指定,django的orm默认会给每张表都添加一个id字段并且为主键,如果我们自己指定了主键,以我们自己指定的为准,就不会自动帮你添加主键字段了 name = models.CharField(max_length=32) age = models.IntegerField() # ad = models.ForeignKey(to='AuthorDetail',to_field='id',on_delete=models.CASCADE) ad = models.OneToOneField('AuthorDetail') # 相当于foreign+unique
# 补充: 如models.ForeignKey(AuthorDetail)这里面的外键关联的表,可以不写引号,但是如果不写引号,那么这个外键关联的表必须在写这个外键字段的表上面,一般我们都写上引号,这样就不用考虑哪个表写在上面,哪个表写在下面了 # ad = models.ForeignKey(AuthorDetail, on_delete=models.CASCADE) # to=可以不用写,to_field='id'也可以不用写,自动找到是to=那张表的id字段 # django 1.11 版本的foreignkey 默认有on_delete=models.CASCADE这个属性,所以如果要做这种级联删除模式,可以不用写这个属性,但是django2.0之后,必须要自己手动加上这个属性 class AuthorDetail(models.Model): birthday = models.DateField() telephore = models.CharField(max_length=24) address = models.CharField(max_length=64) class Publish(models.Model): name = models.CharField(max_length=64) city = models.CharField(max_length=64) class Book(models.Model): title = models.CharField(max_length=64) pub_date = models.DateField() price = models.DecimalField(max_digits=10,decimal_places=2) authors = models.ManyToManyField('Author') # authors在执行数据库同步指令之后,不会生成字段,而是会帮我们生成一个第三张表,这个表就是书籍表和作者表的多对多关系表 pud = models.ForeignKey('Publish') # ForeignKey这个类,生成数据库字段的时候,会自动将该属性名称_id作为我们的数据库字段名称
to
设置要关联的表。
to_field
设置要关联的字段。
on_delete
同ForeignKey字段。
创建一对多关系字段时的一些参数
to 设置要关联的表 to_field 设置要关联的表的字段 related_name 反向操作时,使用的字段名,用于代替原反向查询时的'表名_set'。 related_query_name 反向查询操作时,使用的连接前缀,用于替换表名。 on_delete 当删除关联表中的数据时,当前表与其关联的行的行为。
创建多对多关系字段时的一些参数
多对多的参数: to 设置要关联的表 related_name 同ForeignKey字段。 related_query_name 同ForeignKey字段。 through 在使用ManyToManyField字段时,Django将自动生成一张表来管理多对多的关联关系。 但我们也可以手动创建第三张表来管理多对多关系,此时就需要通过 through来指定第三张表的表名。 through_fields 设置关联的字段。 db_table 默认创建第三张表时,数据库中表的名称。 示例:authors = models.ManyToManyField('Author',db_table='xx')
# 想操作第三张,就需要自己写sql或者直接对第三张表来添加数据, # 比如models.Author2Book.objects.create(author_id=1,book_id=1,xx='...') class Book(models.Model): title = models.CharField(max_length=32, verbose_name="书名") class Author(models.Model): name = models.CharField(max_length=32, verbose_name="作者姓名") # 自己创建第三张表,分别通过外键关联书和作者 class Author2Book(models.Model): author = models.ForeignKey(to="Author") book = models.ForeignKey(to="Book") xx = models.CharField(max_length=32) #拓展字段 class Meta: unique_together = ("author", "book")
方式二: 中介模型,orm提供的有些方法可以用,有些用不了,比如add添加数据的方法
# 手动创建第三张表,并通过ManyToManyField来指定一下这个关系表 class Book(models.Model): title = models.CharField(max_length=32, verbose_name="书名") # 自己创建第三张表,并通过ManyToManyField指定关联 class Author(models.Model): name = models.CharField(max_length=32, verbose_name="作者姓名") books = models.ManyToManyField(to="Book", through="Author2Book", through_fields=("author", "book")) # through_fields接受一个2元组('field1','field2'): # 其中field1是定义ManyToManyField的模型外键的名(author),field2是关联目标模型(book)的外键名。 # 比如author_obj的id为1 author_obj.books.add(1,2) ''' Author2Book id author_id book_id xx 1 1 1 怎么添加 2 1 2 怎么添加 add方法搞不定 ''' class Author2Book(models.Model): author = models.ForeignKey(to="Author") book = models.ForeignKey(to="Book") #可以扩展其他的字段了 xx = models.CharField(max_length=32) #拓展字段 class Meta: unique_together = ("author", "book")
方式三: 通过ManyToManyField自动生成第三张表(常用)
class Book(models.Model): title = models.CharField(max_length=32, verbose_name="书名") # 通过ORM自带的ManyToManyField自动创建第三张表 class Author(models.Model): name = models.CharField(max_length=32, verbose_name="作者姓名") books = models.ManyToManyField(to="Book", related_name="authors") #自动生成的第三张表我们是没有办法添加其他字段的
创建模型类时的一些元信息配置
元信息 ORM对应的类里面包含另一个Meta类,而Meta类封装了一些数据库的信息。主要字段如下: class Author2Book(models.Model): author = models.ForeignKey(to="Author") book = models.ForeignKey(to="Book") class Meta: unique_together = ("author", "book") db_table ORM在数据库中的表名默认是 app_类名,可以通过db_table可以重写表名。db_table = 'book_model' index_together 联合索引。 unique_together 联合唯一索引。 ordering 指定默认按什么字段排序。 ordering = ['pub_date',] 只有设置了该属性,我们查询到的结果才可以被reverse(),否则是能对排序了的结果进行反转(order_by()方法排序过的数据)
title = models.CharField(max_length=64,db_column='xx') author = models.ForeignKey(to="Author",db_column='ss') # 指定外键连接时给列起名字
on_delete 当删除关联表中的数据时,当前表与其关联的行的行为。 models.CASCADE 删除关联数据,与之关联也删除 models.DO_NOTHING 删除关联数据,引发错误IntegrityError models.PROTECT 删除关联数据,引发错误ProtectedError models.SET_NULL 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空) #pub = models.ForeignKey('Publish',on_delete=models.SET_NULL, null=True) models.SET_DEFAULT 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值) models.SET 删除关联数据, a. 与之关联的值设置为指定值,设置:models.SET(值) b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
ForeignKey的db_contraint参数
db_constraint=False只加两者的关系,没有强制约束的效果,并且ORM外键相关的接口(方法)还能使用,所以如果将来建立外键,
并且不能有强制的约束关系,那么就可以将这个参数改为False customer = models.ForeignKey(verbose_name='关联客户', to='Customer',db_constraint=False)
from django.shortcuts import render,HttpResponse from app01 import models def add_info(M): # 一对一关系添加数据 models.AuthorDetail.objects.create( birthday="2010-07-20", telephore="123456", address="上海" ) # ... # 方式一: au_obj=models.AuthorDetail.objects.get(id=1) models.Author.objects.create( name="王五", age=18, ad=au_obj # #其实存在数据库中的还是au_obj的id值 ) # 方式二: models.Author.objects.create( name="李四", age=20, ad_id=2 ) return HttpResponse('OK')
一对多关系添加数据: 方式同一对一添加
# 一对多关系添加数据 models.Publish.objects.create( name="小花出版社", city="北京" ) # ... # 方式一: pub_obj = models.Publish.objects.get(id=2) models.Book.objects.create( title="人间", pub_date="2012-12-12", price=9.9, pud=pub_obj ) # 方式二: models.Book.objects.create( title="人生", pub_date="1998-12-12", price=19.9, pud_id=3 )
多对多关系添加数据
# 多对多关系添加数据 obj_book = models.Book.objects.create( title="人类", pub_date="2020-7-20", price=99.9, pud_id=2 ) obj_author1 = models.Author.objects.create( name="陈六六", age=19, ad_id=6 ) obj_auther2 = models.Author.objects.create( name="陈七七", age=21, ad_id=7 ) # 建立多对多的关系 # 方式一: obj_book.authors.add(obj_author1,obj_auther2) # 写对应作者的模型类对象 # 方式二: obj_book.authors.add(3,5) # 直接写作者记录的id值 # 方式三: obj_book = models.Book.objects.get(id=4) # 模型类对象 obj_book.authors.add(*[3,4]) # 直接写作者记录的id值