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

时间:2021-10-25 22:07:58

I have a model like this:

我有一个这样的模型:

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

I want to migration and host both together be primary key.

我想要迁移和主机都是主键。

3 个解决方案

#1


47  

I would implement this slightly differently.

我将以稍微不同的方式实现它。

I would use a default primary key (auto field), and use the meta class property, unique_together

我将使用默认的主键(auto field),并使用meta类属性unique_together

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

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

It would act as a "surrogate" primary key column.

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

If you really want to create a multi-column primary key, look into this app

如果您真的想要创建一个多列主键,请查看这个应用程序。

#2


6  

Currently, Django models only support a single column primary-key. If you don't specific primary_key = True for the field in your model, Django will automatically create a column id as a primary key.

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

The attribute unique_together in class Meta is only constraints for your data.

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

#3


0  

if you should use django on legacy database, you can't modify db_schema

如果应该在遗留数据库上使用django,则不能修改db_schema

there is a workaround (ugly) method to fix this issue

有一个解决(丑陋的)方法来解决这个问题

override the models save or delete function

覆盖模型保存或删除功能

use raw sql statement to save or delete object

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

class BaseModel(models.Model):

类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):

类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'),)

#1


47  

I would implement this slightly differently.

我将以稍微不同的方式实现它。

I would use a default primary key (auto field), and use the meta class property, unique_together

我将使用默认的主键(auto field),并使用meta类属性unique_together

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

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

It would act as a "surrogate" primary key column.

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

If you really want to create a multi-column primary key, look into this app

如果您真的想要创建一个多列主键,请查看这个应用程序。

#2


6  

Currently, Django models only support a single column primary-key. If you don't specific primary_key = True for the field in your model, Django will automatically create a column id as a primary key.

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

The attribute unique_together in class Meta is only constraints for your data.

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

#3


0  

if you should use django on legacy database, you can't modify db_schema

如果应该在遗留数据库上使用django,则不能修改db_schema

there is a workaround (ugly) method to fix this issue

有一个解决(丑陋的)方法来解决这个问题

override the models save or delete function

覆盖模型保存或删除功能

use raw sql statement to save or delete object

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

class BaseModel(models.Model):

类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):

类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'),)