zoukankan      html  css  js  c++  java
  • 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值
  • 相关阅读:
    GTest交流与经验总结
    linux i2c驱动架构-dm368 i2c驱动分析
    在不同编译环境中如何使用sleep()函数
    Android应用之基本的组件(一)
    Java Arrays Tutorial (3)
    ASP.NET中操作SQL数据库
    安卓开发06:布局-线性布局 LinearLayout
    在开发 ExtJS 应用程序常犯的 10 个错误
    每天4个linux命令--步骤一
    获取CPU序列号
  • 原文地址:https://www.cnblogs.com/fdsimin/p/13332963.html
Copyright © 2011-2022 走看看