Python 在先前存在的多对多关系上使用自定义直通模型

Python 在先前存在的多对多关系上使用自定义直通模型,python,django,postgresql,django-models,django-admin,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 (

我正在开发一个中等规模的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_表与该表完全相同。 这是我要避免的第一件事,因为在预先存在的表中仍然有大量数据。那么,我如何继续告诉django只添加新字段呢

还没有结束…我们还有第二个问题: 在我们的代码中添加/删除联系人组的方式如下:

contact.groups.add(group) - contact.groups.remove(group)
在django中使用自定义直通模型时,我们在ManytoManyRelatedManager上没有添加和删除方法,因此我们必须修复代码中的大量部分,显然我们希望避免这种情况。新字段实际上不包含任何特定值,它只需要存储auto\u now\u add值

我们没有找到任何好的解决方案,我们只是找到了一个不好的头部:

有人能帮我们吗


非常感谢。

查看Django源代码,您可以尝试以下方法,但可能会遇到一些意想不到的问题。例如,我不是100%认为AutoFields在没有更多探索的情况下可以工作;可为空的字段应该可以:

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属性的潜在意外副作用,可以修补add、remove和set方法,将auto_created临时设置为True,并在调用后将其还原


Django M2M的支持令人尴尬地薄弱:

您的第二点是一个问题。上次修改是在3年前,所以我认为它不会很快关闭。我们需要一个解决办法。