如何在Django中为我的模型设置两个主键字段

时间:2013-05-28 19:56:13

标签: python django django-models model primary-key

我有一个这样的模型:

class Hop(models.Model):
    migration = models.ForeignKey('Migration')
    host = models.ForeignKey(User, related_name='host_set')

我想迁移并将两者一起作为主键。

3 个答案:

答案 0 :(得分:58)

我会稍微改变一下。

我会使用默认主键(自动字段),并使用元类属性unique_together

class Hop(models.Model):
    migration = models.ForeignKey('Migration')
    host = models.ForeignKey(User, related_name='host_set')

    class Meta:
        unique_together = (("migration", "host"),)

它将充当“代理”主键列。

如果您确实想要创建多列主键,请查看this app

答案 1 :(得分:12)

目前,Django模型仅支持单列主键。如果您没有为模型中的字段指定primary_key = True,Django会自动创建一列id作为主键。

unique_together中的属性Meta只是数据的约束。

答案 2 :(得分:2)

如果你应该在遗留数据库上使用django,则无法修改db_schema

有解决此问题的解决方法(丑陋)

覆盖模型保存或删除功能

  

使用raw sql语句保存或删除对象

类BaseModel(models.Model):

def get_max_length_unique_key(self):
    max_len_unique_key = []
    for unique_key in self._meta.unique_together:
        if len(unique_key) > len(max_len_unique_key):
            max_len_unique_key = unique_key
    return max_len_unique_key

def get_db_conn(self):
    db_cnn = DbManage(db_ip, db_port, DATABASES_USER, DATABASES_PASSWORD, self._meta.db_table)
    db_cnn.connect()
    return db_cnn

def save(self, *args, **kwargs):
    self.delete()
    cnn, databasename = self.get_db_conn()
    update_tables = self._meta.db_table
    key_list = ""
    values_list = ""
    for field in self._meta.fields:
        key_list += "%s," % field.name
        values_list += "\'%s\'," % str(getattr(self, field.name))

    key_list = key_list[:len(key_list) - 1]
    values_list = values_list[:len(values_list) - 1]

    sql = "insert into %s(%s) values(%s)" % (update_tables, key_list, values_list)
    logger.info("insert new record to %s" % databasename)
    cnn.excute_sql(sql)
    cnn.close()

def delete(self, *args, **kwargs):
    cnn = self.get_db_conn()
    update_tables = self._meta.db_table
    sql = "delete from %s where " % update_tables
    for uk in self.get_max_length_unique_key():
        sql += "%s=\'%s\' and " % (uk, getattr(self, uk))
    sql = sql[:len(sql) - 4]

    logger.info("delete record from %s" % update_tables)
    cnn.excute_sql(sql)
    cnn.close()
    pass

class Meta:
    abstract = True

class ImageList(BaseModel):

field1 = models.CharField(primary_key=True, max_length=30)
field2 = models.CharField(primary_key=True, max_length=30)
field3 = models.CharField(primary_key=True, max_length=30)
body = models.CharField(max_length=2000, blank=True, null=True)
updated_on = models.DateTimeField(blank=True, null=True)

class Meta:
    managed = True
    db_table = 'image_list'
    unique_together = (('field1', 'field2', 'field3'),)