【问题标题】:Use custom through model on preexisting many to many relation在预先存在的多对多关系上使用自定义模型
【发布时间】:2015-01-18 15:05:46
【问题描述】:

我正在开发一个中型 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 值。

我们没有找到任何好的解决方案,只是觉得很头疼:)

有人可以帮助我们吗?

非常感谢。

【问题讨论】:

  • 你的第二点是open ticket的主题。
  • 票的最后一次修改是在 3 年前,所以我认为它不会很快关闭。我们需要一个解决方法。

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


【解决方案1】:

查看 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 支持弱得令人尴尬:(

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 2022-01-12
    • 2015-02-03
    • 1970-01-01
    • 2016-12-10
    • 2013-09-27
    • 2016-02-24
    相关资源
    最近更新 更多