如何通过类在 Django ManyToManyField 中使用 ManyRelatedManager 的 add()、set() 和clear() 方法?

问题描述 投票:0回答:2

我有以下型号,

Class Bank(models.Model):
    customers = models.ManyToManyField(Customer,'banks', through='bank_customer')

Class Customer(models.Model):
    name = models.CharField(max_length=50)

Class Bank_customer(models.Model):
    customer = models.ForeignKey(Customer,on_delete=models.CASCADE)
    bank = models.ForeignKey(Bank,on_delete=models.CASCADE)
    city = models.ForeignKey(City,on_delete=models.CASCADE)
    
Class City(models.Model):
    name = models.CharField(max_length=100)   

如何将

Customer
对象添加到
Bank
?以下不起作用

bank.customers.add(customer)

这里

bank
customer
是其类的已保存实例。这样做违反了
not_null
表中
city
外键的
Bank_customer
约束。

python django many-to-many manytomanyfield manyrelatedmanager
2个回答
3
投票

我将对模型进行此更改以开始。

  • 注意保留字

    class
    ,必须全部小写。

  • 定义类时,顺序很重要。继承或向后相关的类必须是“最后定义”。 (例如: Bank 必须在

    Customer
    之后定义,否则您将收到类似
    “客户未定义”
    或类似内容的错误)。

  • 我认为您可能需要
  • name

    模型中的

    Bank
    属性/字段。我的意思是,银行有名字。
    
    

  • Bank

    类中我认为最好明确使用相关名称关键字:

    related_name='banks'
    。它使可读性更好。
    
    

  • 使用 CapWords 约定命名类更加 Pythonic(
  • PEP 8

    )。 使用 BankCustomer 代替

    Bank_customer
    模型。
    
    


关于您的具体问题。

我这样做了:

c1 = Customer(name="Guido van Rossum") c1.save() b1 = Bank(name="Bank of America") b1.save()

然后我做了
b1.customers.add(c1)

并提出了这个错误:

IntegrityError: NOT NULL constraint failed: app2_bankcustomer.city_id
。 看来它在期待
city_id
中有
null=True
BankCustomer
中。
我继续:

ct1 = City('New York') ct1.save() bc1 = BankCustomer(customer=c1, bank=b1, city=ct1) bc1.save()

然后当我这样做时
b1.customers.add(c1)

没有出现任何错误。

问题是 

IntegrityError

错误,显然:


django.db.utils.IntegrityError: NOT NULL

--> 这是一个很常见的 初学者的错误。这意味着你有一个字段

null=False
(又名
default
)并且您正在尝试创建它 模型没有该字段有任何数据。 (
来源

所以你可以对
BankCustomer

做一点改变。您在

null=True
字段中添加
city
class BankCustomer(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    bank = models.ForeignKey(Bank, on_delete=models.CASCADE)
    city = models.ForeignKey(City, null=True, on_delete=models.CASCADE)

    def __str__(self):
        return f'{self.customer} - {self.bank} - {self.city}'

不要忘记运行 makemigrations 并迁移

此后,不会出现任何错误。

讨论该问题的其他一些来源:

django.db.utils.IntegrityError:NOT NULL 约束失败:app.area_id

django.db.utils.IntegrityError:NOT NULL 约束失败:products_product.image 图像字段错误

https://code.djangoproject.com/ticket/21783

https://forum.djangoproject.com/t/polls-not-null-constraint-failed/4396/2

https://github.com/sibtc/django-beginners-guide/issues/20

如果您检查管理员,您会发现
Bank

模型仅接受

name
而不接受
customers

enter image description here 我认为这是合乎逻辑的,因为你想使用

BankCustomer

(在你的代码中:

Bank_customer
)。
我希望这有帮助。


2
投票
ManyRelatedManager__add

源码,它接受

through_defaults
参数
def add(self, *objs, through_defaults=None):
...
                self._add_items(
                    self.source_field_name, self.target_field_name, *objs,
                    through_defaults=through_defaults,
                )
...

所以,而不是

bank.customers.add(customer)

尝试

bank.customers.add(customer, through_defaults={'city_id':SOME_CITY_OBJ_ID_YOU_WANT})

这也适用于 
.set()

功能

    

© www.soinside.com 2019 - 2024. All rights reserved.