Django/MySql未遵循unique_together

2 投票
1 回答
1516 浏览
提问于 2025-04-16 05:22

我正在使用Django和MySQL(InnoDB),在我的Django模型中有以下内容:

class RowLock(models.Model):
    table_name = models.CharField(blank = False, max_length = 30)
    locked_row_id = models.IntegerField(null = False)
    process_id = models.IntegerField(null = True)
    thread_id = models.IntegerField(null = True)
    class Meta:
        db_table = "row_locks"
        unique_together = (("table_name", "locked_row_id"),)

运行命令 python manage.py sql app_name 会得到:

但是在MySQL客户端中执行 desc row_locks 会得到:

mysql> desc row_locks;
+---------------+-------------+------+-----+---------+----------------+
| Field         | Type        | Null | Key | Default | Extra          |
+---------------+-------------+------+-----+---------+----------------+
| id            | int(11)     | NO   | PRI | NULL    | auto_increment |
| table_name    | varchar(30) | NO   |     | NULL    |                |
| locked_row_id | int(11)     | NO   |     | NULL    |                |
| process_id    | int(11)     | YES  |     | NULL    |                |
| thread_id     | int(11)     | YES  |     | NULL    |                |
+---------------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

我还检查过,可以在表 table_name 和 locked_row_id 中插入相同值的重复行,而不会出现完整性错误。

现在我猜测我可能做错了什么,因为这么明显的问题不应该是个bug,但我看不出来,

如果有人能帮我看看就太好了。

罗伯

更新:
所以正如多米尼克指出的,问题是south迁移没有创建唯一约束。我本可以考虑做两个迁移,一个是创建表,另一个是添加 unique_together - 不知道那样是否可行 - 可能有时间的话会试试。

无论如何,我通过手动编辑south迁移脚本中的forward方法解决了这个问题,具体如下:

由south生成的:

class Migration(SchemaMigration):

    def forwards(self, orm):

        # Adding model 'RowLock'                                                                                           
        db.create_table('row_locks', (
            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('table_name', self.gf('django.db.models.fields.CharField')(max_length=30)),
            ('locked_row_id', self.gf('django.db.models.fields.IntegerField')()),
            ('process_id', self.gf('django.db.models.fields.IntegerField')(null=True)),
            ('thread_id', self.gf('django.db.models.fields.IntegerField')(null=True)),
        ))
        db.send_create_signal('manager', ['RowLock'])

手动编辑后的:

class Migration(SchemaMigration):

    def forwards(self, orm):

        # Adding model 'RowLock'                                                                                           
        db.create_table('row_locks', (
            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
            ('table_name', self.gf('django.db.models.fields.CharField')(max_length=30)),
            ('locked_row_id', self.gf('django.db.models.fields.IntegerField')()),
            ('process_id', self.gf('django.db.models.fields.IntegerField')(null=True)),
            ('thread_id', self.gf('django.db.models.fields.IntegerField')(null=True)),
        ))
        db.create_index('row_locks', ['table_name','locked_row_id'], unique=True)
        db.send_create_signal('manager', ['RowLock'])

1 个回答

6

为了完整起见,我最后的更新可能应该作为一个回答来添加。

我通过手动编辑南方迁移的前进方法来解决这个问题,并添加了这一行:

db.create_index('row_locks', ['table_name','locked_row_id'], unique=True)

Rob

撰写回答