django ManyToManyField和on_delete [英] django ManyToManyField and on_delete

查看:648
本文介绍了django ManyToManyField和on_delete的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

django上的ForeignKey s具有属性 on_delete 来指定被引用对象被删除时的行为。有什么办法可以获得类似于 ManyToManyField



假设我有以下模型

  class House(models.Model):
owner = models.ManyToManyField(Person)

默认的行为就是级联,所以如果我删除一个刚刚拥有房屋的人,那么它就会从业主消失(这显然不再拥有房屋)。我想要的是,如果一个人是所有者,则不能被删除。也就是说,我想要 on_delete = models.PROTECT 。这是可能的吗?



我内部知道 ManyToManyField 被翻译成另一个模型,两个 ForeignKey (在这种情况下是一个人到一个人,一个人),所以应该可以实现这一点。任何想法如何?我想避免设置通过属性到一个新的模型,因为这将导致一个新的表(我想保留旧的)。



编辑:我已经跟踪了django创建适当的m2m模型的位置:

  def create_many_to_many_intermediary_model(field,klass):
from django.db import models
#...
#构造并返回新类。
return type(name,(models.Model,),{
'Meta':meta,
'__module__':klass .__ module__,
from_:models.ForeignKey ,
related_name ='%s +'%name,
db_tablespace = field.db_tablespace),
to:models.ForeignKey(to_model,
related_name ='%s +'%name,
db_tablespace = field.db_tablespace)
})

相关行为

  to:models.ForeignKey(to_model,
related_name ='%s +'%name,
db_tablespace = field.db_tablespace)

我希望它是

  to:models.ForeignKey(to_model,
related_name ='%s +'%name,
db_tablespace = field.db_tablespace,
on_delete = models.PROTECT)

除了猴子修补整个事情并创建一个我们认为最聪明的事情是使用一个明确的表格。我意识到你已经表示你不愿意因为这会导致一个新的表(我想保留旧表)。



我怀疑你的担心是失去你所拥有的数据。如果您使用South,您可以轻松地将现有的自动中间表转换为显式的OR,您可以创建一个全新的OR,然后将现有数据迁移到新表,然后再删除旧表。 p>

这两种方法都在这里解释:添加通过表到django字段并与South迁移?



考虑到您想对其定义做出的更改,我可能会选择创建一个新表,然后迁移您的数据。测试以确保您的所有数据仍然存在(并且您的更改执行您想要的),然后删除旧的中间表。



考虑到这些表只会每行持有3个整数,即使您有很多房屋和业主,这也可能是一个非常易于管理的练习。


ForeignKeys on django have the attribute on_delete to specify the behavior when the referenced object is deleted. Is there any way to get something similar for ManyToManyField?

Suppose I have the following model

class House(models.Model):
    owners = models.ManyToManyField(Person)

The default behavior is to cascade, so if I delete a person that happens to own a house, it just vanishes from owners (that is, obviously, it no longer owns any houses). What I'd like to have is that if a person is an owner, it can not be deleted. That is, I want on_delete=models.PROTECT. Is this possible?

I know internally ManyToManyField is translated to another model with two ForeignKeys (in this case one to house and one to person), so it should be possible to achieve this. Any ideas how to? I'd like to avoid setting the through attribute to a new model, because this would result in a new table (I'd like to keep the old one).

Edit: I've tracked where django creates the appropriate m2m model:

def create_many_to_many_intermediary_model(field, klass):
    from django.db import models
    # ... 
    # Construct and return the new class.
    return type(name, (models.Model,), {
        'Meta': meta,
        '__module__': klass.__module__,
        from_: models.ForeignKey(klass,
                                 related_name='%s+' % name,
                                 db_tablespace=field.db_tablespace),
        to: models.ForeignKey(to_model,
                              related_name='%s+' % name,
                              db_tablespace=field.db_tablespace)
    })

The relevant line is

to: models.ForeignKey(to_model,
                      related_name='%s+' % name,
                      db_tablespace=field.db_tablespace)

I'd like it to be

to: models.ForeignKey(to_model,
                      related_name='%s+' % name,
                      db_tablespace=field.db_tablespace,
                      on_delete=models.PROTECT)

Any way to do this other than monkey patching the whole thing and creating a new class for ManyToManyField?

解决方案

I think the smartest thing to do is use an explicit through table. I realise that you've stated you would prefer not to "because this would result in a new table (I'd like to keep the old one)."

I suspect your concern is over losing the data you have. If you're using South, you can easily "convert" your existing, automatic intermediate table to an explicit one OR, you can create a completely new one, then migrate your existing data to the new table before dropping your old one.

Both of these methods are explained here: Adding a "through" table to django field and migrating with South?

Considering the change you'd like to make to its definition, I'd probably go with the option of creating a new table, then migrating your data over. Test to make sure all your data is still there (and that your change does what you want), then drop the old intermediate table.

Considering that these tables will both only hold 3 integers per row, this is likely to be a very manageable exercise even if you have a lot of houses and owners.

这篇关于django ManyToManyField和on_delete的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆