zoukankan      html  css  js  c++  java
  • Django-ORM之ForeignKey的使用-多对一关系

    ForeignKey使用俩表示两张表多对一关系的外键,外键字段要定义在多属性的表中。

    定义外键时,to的表可以直接写类名,但是需要注意类的定义顺序;也可以写字符串式的类名,这样就可以忽略class类的定义顺序;

    class Book(models.Model):
        title = models.CharField(max_length=32)
        pid = models.ForeignKey('Publisher',on_delete=models.CASCADE) # 外键  on_delete属性  2.0 必填 ,1.0版本默认是models.CASCADE,建议是手动写上
     【实例】
     class Book(models.Model):
        bid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        pub = models.ForeignKey("Publisher", on_delete=models.CASCADE)
     ​
        def __str__(self):
            return f"{self.bid}{self.title}{self.pub}"

    创建完成后会发生如图这种情况,pub自动变成了pub_id,无需惊讶,这就是它应有的样子~

    django数据库外键

    那么pub与pub_id之间有什么关系呢?听经过查看pub的type可以得出结论,pub得到的是一个对象,包含pub_id在内的外键对应的对象,在django中创建外键时,默认是以目标的主键作为对应项,以下的各个操作就会利用这一点。

     在本例中外键中
     pub_id == pub.pid  

    查询

     all_books = models.Book.objects.all()
     print(all_books)
     for book in all_books:
        print(book)
        print(book.pk)
        print(book.title)
        print(book.pub,type(book.pub))  # 所关联的对象 
        print(book.pub_id,type(book.pub_id))  # 所关联的对象的pk
        print('*' * 32)

    新增

     # 方式一
     models.Book.objects.create(title=title,pub=models.Publisher.objects.get(pk=pub_id))
     # 方式二
     models.Book.objects.create(title=title, pub_id=pub_id)

    删除

     pk = request.GET.get('pk')
     models.Book.objects.filter(pk=pk).delete()

    编辑

     book_obj.title = title
     # 修改外键列
     # 方式一:
     book_obj.pub_id = pub_id
     # 方式二:
     book_obj.pub = models.Publisher.objects.get(pk=pub_id)
     book_obj.save()

    外键的操作

    【新建测试表结构】

    from django.db import models
     ​
     # Create your models here.
     class Publisher(models.Model):
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
     ​
        def __str__(self):
            return "<Publisher object: {} {}>".format(self.id, self.name)
     ​
     class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        phone = models.CharField(max_length=11)
     ​
        def __str__(self):
            return "<Author object: {} {}>".format(self.id, self.name)
     ​
     class Book(models.Model):
        title = models.CharField(max_length=32)
        publish_date = models.DateField(auto_now_add=True)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        memo = models.TextField(null=True)
        # 创建外键,关联publish
        publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE)
        # 创建多对多关联author
        author = models.ManyToManyField(to="Author")
     ​
        def __str__(self):
            return "<Book object: {} {} {} {}>".format(self.id, self.title,self.price,self.author)

    跨表对象查找正向

    所谓正向查找是指从建立外键的表查询目标表的查找,兄目标表查询建立外键的表就是反向查询。

     book_obj = models.Book.objects.first()
     print(book_obj)   # 输出book对象
     print(book_obj.publisher)   # book对象对应的外键对象
     print(book_obj.publisher.name)  # 外键对象的name属性

    跨表对象查找反向

    pub_obj = models.Publisher.objects.get(pk=1)
     print(pub_obj)  # 出版社对象
     print(pub_obj.name)  # 出版社名称
     print(pub_obj.book_set)  # 关系管理对象,与该出版社相关联的图书的关系,默认的书写方式:类名小写_set
     print(pub_obj.book_set.all())  # 所关联的所有的对象

    添加relate_name属性

    定义反向查询时的名字,例如将Book表的publisher属性添加related_name属性,会抵消默认情况的类名小写_set

    # 添加属性
     publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE,related_name='books')
     ​
     # 未添加属性时,反向查询
     pub_obj = models.Publisher.objects.get(pk=1)
     print(pub_obj.book_set)
     print(pub_obj.book_set.all())  
     # 添加属性后的反向查询
     pub_obj = models.Publisher.objects.get(pk=1)
     print(pub_obj.books)
     print(pub_obj.books.all())

    跨表字段查找正向

    # 查询'叽叽喳喳出版社'出版的书
     ret = models.Book.objects.filter(publisher__name='叽叽喳喳出版社')
     print(ret.all())

    跨表字段查找反向

     # 查找出版《叽叽喳喳》的出版社
     ret = models.Publisher.objects.filter(book__title='叽叽喳喳')
     print(ret.values())

    添加related_name属性

    # 添加属性
     publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE,related_name='books')
     # 反向查询时
     ret = models.Publisher.objects.filter(books__title='叽叽喳喳')
     print(ret)

    添加related_query_name属性

    在字段查找时related_query_name的优先级高于related_name,但是在对象查找时,related_query_name无效

     publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE,related_name='books',related_query_name='books1')
     # 反向查询时
     ret = models.Publisher.objects.filter(books1__title='叽叽喳喳')
     print(ret)

    关系管理对象的方法

    反向查询时才能取到关系管理对象
     # all
     pub_obj = models.Publisher.objects.get(pk=1)
     print(pub_obj.book_set.all())
     ​
     # set 设置对象
     pub_obj.book_set.set(models.Book.objects.filter(pk__in=[3,4]))
     ​
     # add  添加对象
     pub_obj.book_set.add(*models.Book.objects.filter(pk__in=[1,2]))
     ​
     # remove 移除外键,前提是外键字段可以为空
     pub_obj.book_set.remove(*models.Book.objects.filter(pk__in=[1,2]))
     ​
     # clear 清空,前提是外键字段可以为空
     pub_obj.book_set.clear(*models.Book.objects.filter(pk__in=[1,2]))
     ​
     # create 
     pub_obj.book_set.createtitle='叽叽喳喳的世界',publisher_id=2,price=99.9)
    

      

    仅供参考,欢迎指正
  • 相关阅读:
    fedora 安装open office
    git rebase(转)
    javascript typeof
    正则表达式入门
    XML格式
    zz 通用线程:Awk 实例,第 3部分
    ELF BIN HEX
    i2c总线(iic总线/ I square C)
    grep
    把Nginx注册成Windows 系统服务(转载)
  • 原文地址:https://www.cnblogs.com/jjzz1234/p/11607793.html
Copyright © 2011-2022 走看看