通过预先存在多对多关系的模型使用自定义

时间:2014-11-20 16:41:20

标签: python django postgresql django-models django-admin

我正在开发一个中型django应用程序,我们的常见情况是有一个联系模型,每个联系人可能是不同组的一部分。 这是应用程序当前的模型方法:

class Contact(models.Model):
    first_name = models.CharField (
        max_length = 100,
        verbose_name = _("First Name"),
    )
    last_name = models.CharField (
        max_length = 100,
        verbose_name = _("Last Name"),
    )
    groups = models.ManyToManyField(
        Group,
        related_name = "contacts",
        verbose_name = _("Groups"),        
    )  

我们的客户要求我们在特定管理区域中显示联系人何时加入其中的每个组。 所以我们还有一个由django自动创建的数据库表,其中存储了联系人和组之间的关系,我们只想在保存新记录时添加用于存储当前日期时间的新列,所以我们尝试过这种方法:

class ContactGroups(DateModel):

    contact = models.ForeignKey("Contact")
    group = models.ForeignKey("Group")
    created = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "contact_contact_groups"

class Contact(models.Model):
    first_name = models.CharField (
        max_length = 100,
        verbose_name = _("First Name"),
    )
    last_name = models.CharField (
        max_length = 100,
        verbose_name = _("Last Name"),
    )
    groups = models.ManyToManyField(
        Group,
        related_name = "contacts",
        verbose_name = _("Groups"),
        through=ContactGroups,
    )   

启动新的schemamigration django想要删除预先存在的表并创建新表(db_table与表具有完全相同)。 这是我想要避免的第一件事,因为我们在预先存在的表中仍然有很多数据。那么,我怎样才能告诉django只添加新字段?

它没有结束......我们还有第二个问题: 添加/删除联系人组是以这种方式在我们的代码中执行的:

contact.groups.add(group) - contact.groups.remove(group)

在django中使用自定义直通模型时,我们没有"添加"并且"删除" ManytoManyRelatedManager上的方法,所以我们应该在代码中修复大部分内容,显然我们想避免这种情况。事实上,新字段不包含任何特定值,只需存储auto_now_add值。

我们没有找到任何好的解决方案,我们发现了一个糟糕的头脑:)

有人可以帮助我们吗?

非常感谢。

1 个答案:

答案 0 :(得分:0)

看看Django源代码,您可以尝试以下方法,但它可能会有一些意想不到的陷阱(例如,我不是100%,如果没有更多的探索,AutoFields将工作;可以为空的字段应该没问题):< / p>

class SimpleCustomThroughModelMixin(object):
"""
A Mixin to provide add and remove methods to an M2M Manager.

Any custom fields on the through model must be auto fields or nullable.
"""
def __new__(cls, *args, **kwargs):
    obj = super(SimpleCustomThroughModelMixin, cls).__new__(cls, *args, **kwargs)
    for field in cls.custom_through_fields:
        getattr(cls, field).through._meta.auto_created = True
    return obj


class Contact(models.Model):
    custom_through_fields = ('groups',)

    first_name = models.CharField (
        max_length = 100,
        verbose_name = _("First Name"),
    )
    last_name = models.CharField (
        max_length = 100,
        verbose_name = _("Last Name"),
    )
    groups = models.ManyToManyField(
        Group,
        related_name = "contacts",
        verbose_name = _("Groups"),
        through=ContactGroups,
    )  

更好的是,为了避免更改auto_created属性的潜在意外副作用,可能是修补添加,删除和设置方法以临时将auto_created设置为True并在调用后将其还原。

Django M2M支持令人尴尬地处于弱势:(