【问题标题】:ManyToManyField and South migration多对多场和南迁移
【发布时间】:2011-08-30 22:48:01
【问题描述】:

我有带有 M2M 字段的用户配置文件模型

class Account(models.Model):
    ...
    friends = models.ManyToManyField('self', symmetrical=True, blank=True)
    ...

现在我需要知道如何以及何时将彼此添加为好友 我为此创建了一个模型

class Account(models.Model):
    ...
    friends = models.ManyToManyField('self', symmetrical=False, blank=True, through="Relationship")
    ...


class Relationship(models.Model):    
    """ Friends """        
    from_account = models.ForeignKey(Account, related_name="relationship_set_from_account")            
    to_account = models.ForeignKey(Account, related_name="relationship_set_to_account")
    # ... some special fields for friends relationship

    class Meta:                    
        db_table = "accounts_account_friends"            
        unique_together = ('from_account','to_account')

我是否应该为此更改创建任何迁移? 如果您有任何建议,请随时写在这里。

谢谢

PS:accounts_account 表已经包含记录

【问题讨论】:

    标签: django django-models django-south


    【解决方案1】:

    您在那里进行编码的方式是手动定义一个模型,该模型与 Django 自动为您创建的 m2m 连接表执行相同的工作。问题是,自动创建的表将被称为accounts_relationship_friend

    因此,您在那里所做的将创建一个模型,该模型试图复制 ORM 在表面下所做的事情,但它指向错误的表。

    如果您不需要显式连接模型,我会将其从您的代码库中移除,而不是创建迁移来添加它,而是使用 M2M 来查找朋友之间的关系。 (我并没有考虑太深,但它应该可以工作)。

    但是,如果您想对现有的关系模型做一些特别的事情(例如,存储有关关系类型的属性等),我会将关系模型声明为您在 Friend.friends 中使用的直通模型m2m 定义。 See the docs here.

    【讨论】:

    • 我有带有 m2m 字段 friends 的模型,并且数据库中有配置文件。现在我想向关系船添加一些特殊属性(创建日期等)。我创建了trough 表。而且我想知道:对于这种情况,我是否应该进行迁移。你的回答包含了很好的信息,但你可以看到我已经完成了。
    【解决方案2】:

    首先,如果可以的话,我会避免使用db_table 别名。这使得表结构更难理解,因为它不再与模型同步。

    其次,South API 提供db.rename_table() 等功能,可以通过手动编辑迁移文件来使用。您可以将 accounts_account_friends 表重命名为 accounts_relation(Django 会默认命名它),并添加其他列。

    这种组合为您提供以下迁移:

    def forwards(self, orm):
        # the Account.friends field is a many-to-many field which got a through= option now.
        # Instead of dropping+creating the table (or aliasing in Django),
        # rename it, and add the required columns.
    
        # Rename table
        db.delete_unique('accounts_account_friends', ['from_account', 'to_account'])
        db.rename_table('accounts_account_friends', 'accounts_relationship')
    
        # Add extra fields
        db.add_column('accounts_relationship', 'some_field',  ...)
    
        # Restore unique constraint
        db.create_unique('accounts_relationship', ['from_account', 'to_account'])
    
    
    def backwards(self, orm):
    
        # Delete columns
        db.delete_column('accounts_relationship', 'some_field')
        db.delete_unique('accounts_relationship', ['from_account', 'to_account'])
    
        # Rename table
        db.rename_table('accounts_relationship', 'accounts_account_friends')
        db.create_unique('accounts_account_friends', ['from_account', 'to_account'])
    
    
    models = {
        # Copy this from the final-migration.py file, see below
    }
    

    唯一关系被删除,然后重新创建,因此约束具有正确的名称。

    使用以下技巧可以轻松生成添加列语句:

    • models.py 中添加仅具有外键字段的 Relationship 模型,并且尚未对 M2M 字段进行任何更改。
    • 迁移到它
    • 将字段添加到Relationship 模型。
    • 做一个./manage.py schemamigration app --auto --stdout | tee final-migration.py | grep column
    • 恢复第一次迁移。

    那么你就拥有了构建迁移文件所需的一切。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-24
      • 1970-01-01
      • 1970-01-01
      • 2014-09-17
      • 2011-09-28
      • 2023-04-07
      • 2021-12-27
      • 1970-01-01
      相关资源
      最近更新 更多