ORM多表操作

url反向解析

由于将来项目中的不同功能对应的url路径可能会发生变化,所以我们在每个url路径上加上一个别名,将来通过别名反向解析来使用这个别名对应的路径,那么不管路径将来发生什么变化,只要别名不变,那么逻辑中使用这个路径的地方,都可以通过别名获取到

urlpatterns = [
    ...
    url(r'^add_book/', views.add_book, name='add_book'),  #name属性对应的值,就是这个路径的别名

]

views视图中使用url反向解析的方式

首先在视图中引入反向解析的方法
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})

html文件中使用url别名反向解析

针对无参数的路径: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')

创建第三张表的三种方式

方式一: 手动创建第三张表(不能用manytomanyfield提供的操作第三张表数据的方法)

# 想操作第三张,就需要自己写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()方法排序过的数据)

db_column指定列名称

title = models.CharField(max_length=64,db_column='xx')
author = models.ForeignKey(to="Author",db_column='ss')  # 指定外键连接时给列起名字

on_delete级联模式参数

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值
原文地址:https://www.cnblogs.com/fdsimin/p/13332963.html