5

我为我的网站编写了一个小 qna 脚本,为了防止用户开始讨论,我希望每个用户只能回复一次。

class Q(models.Model):
  text = models.TextField()
  user = models.ForeignKeyField('auth.User')

class A(models.Model):
  text = models.TextField()
  user = models.ForeignKeyField('auth.User')
  q = models.ForeignKeyField('Q')
  class Meta:
    unique_together = (('user','q'),)

现在迁移给了我:

return Database.Cursor.execute(self, query, params)
  django.db.utils.IntegrityError: columns user_id, q_id are not unique

当然,独特性与现有数据发生冲突。我现在需要知道的是如何告诉迁移删除冲突的答案。一个愚蠢的解决方案,比如保留第一个找到的解决方案已经是一个很大的帮助。更好的是通过自定义函数比较冲突的 A 的方法。

我正在使用新的迁移系统运行 Django-1.7 - 而不是 South。

谢谢你的帮助!

4

1 回答 1

6

您只需要创建一个数据迁移,您确实可以在其中编写自定义函数来使用您想要的任何逻辑。有关详细信息,请参阅文档

例如,只保留最低的数据迁移Answer id(这应该是最早答案的一个很好的代理),可能看起来像这样:

from django.db import models, migrations

def make_unique(apps, schema_editor):
    A = apps.get_model("yourappname", "A")

    # get all unique pairs of (user, question)
    all_user_qs = A.objects.values_list("user_id", "q_id").distinct()

    # for each pair, delete all but the first
    for user_id, q_id in all_user_qs:
        late_answers = A.objects.filter(user_id=user_id, q_id=q_id).order_by('id')[1:]
        A.objects.filter(id__in=list(late_answers)).delete()

class Migration(migrations.Migration): 

    dependencies = [ 
        ('yourappname', '0001_initial'),
    ]

    operations = [ 
        migrations.RunPython(make_unique), 
    ]

(这不是我的想法,当然是破坏性的,所以请以此为例。在执行所有这些删除操作之前,您可能需要考虑备份您的数据。)

回顾一下:删除您尝试运行的迁移并摆脱唯一约束。按照文档中的说明创建一个空的数据迁移。编写一个函数来删除数据库中当前存在的非唯一数据。然后重新添加唯一约束并运行makemigrations. 最后,使用migrate.

于 2015-01-08T08:01:09.860 回答