Django多对多关系插入控件 [英] Django Many-to-Many relation insertion control

查看:144
本文介绍了Django多对多关系插入控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下模型:

class Item(models.Model):
    # fields
    # ...

class Collection(models.Model):
    items = models.ManyToManyField(Item, related_name="collections")
    # other fields
    # ...

现在我想要两件事:


  1. 我想控制一个项目可以添加到集合

  2. 我想要 Collection 更新其一些字段,如果项目被添加或删除。

  1. I want to control if an Item can be added to a Collection.
  2. I want the Collection to update some of its fields if an Item was added or removed.

对于第二个问题,我知道有一个django.db.models.signals.m2m_changed ,我可以用来钩住关系的变化。是否允许/确定更改信号回调中的集合?我可以使用信号中止插入问题1?

For the second issue I know that there is the django.db.models.signals.m2m_changed which I can use to hook into changes of the relation. Is it allowed/ok to change the Collection within the signal callback? Can I use the signal also for "aborting" the insertion for issue 1?

推荐答案

我认为最好的方法来接近两个您所需的行为不是使用信号,而是在通过表中重写的save()和delete()方法,您将使用参数 through 请参阅: https ://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField.through 。并且: https://docs.djangoproject.com/en/ dev / topics / db / models /#覆盖预定义模型方法

I think the best way to approach both of your desired behaviors is not with signals, but rather with an overridden save() and delete() method on the through table which you would define explicitly using the argument through see: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField.through. and this: https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods

这样的一个例子:

# -*- coding: utf-8 -*-

from django.db import models


class Item(models.Model):
    # fields
    # ...

class Collection(models.Model):
    items = models.ManyToManyField(Item, related_name="collections", through="CollectionItem")
    # other fields
    # ...

class CollectionItem(models.Model):
    collection = models.ForeignKey(Collection)
    item = models.ForeignKey(Item)

    def save(self, *args, **kwargs):
        # Only allow this relationship to be created on some_condition
        # Part 1 of your question.
        if some_condition:
            super(CollectionItem, self).save(*args, **kwargs)

            # Update some fields on Collection when this
            # relationship is created
            # Part 2 of your question (1/2)
            self.Collection.updateSomeFields()

    def delete(self, *args, **kwargs):
        collection = self.collection
        super(CollectionItem, self).delete(*args, **kwargs)

        # Update some fields on Collection when this relationship
        # is destroyed.
        # Part 2 of your question (2/2)
        collection.updateSomeFields()

顺便说一句,你会发现,添加一个关系会通过模型导致一个保存信号。

Incidentally, you'll find that adding a relationship will cause a save-signal on this through model.

而且,关于信号一旦你有通过表,你就可以听pre_save和/或post_save信号,但是他们都不会允许你直接否决关系的创建。

And, regarding signals, once you have the through table in place, you'd be able to listen for pre_save and/or post_save signals, but neither of them will allow you to directly veto the creation of the relationship.

如果您的一个或两个模型由第三方提供,您真的无法创建通过表,那么是的,信号路由可能是唯一的路要走。

If one or both of your models are supplied by a 3rd party and you really cannot create the through table, then, yes, the signal route may be the only way to go.

https://docs.djangoproject.com/en/dev / ref / signals /#m2m-changed

在这种情况下,您可以监听m2m_changed事件并触发对您的收藏对象的更新(第2部分你的问题),并追溯地删除不适当的crea关系(你的问题的第1部分)。但是,如果可以的话,由于后者比较丑陋,所以如果可以,我会坚持使用明确的表格。

In which case, you could listen for the m2m_changed event and trigger updates to your collection objects (part 2 of your question) and retroactively delete inappropriately created relationships (part 1 of your question). However, as this latter bit is a fugly kludgy, I'd stick with the explicit through table if you can.

这篇关于Django多对多关系插入控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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