How can set two primary key fields for my models in Django

前端 未结 3 2086
一整个雨季
一整个雨季 2020-12-07 17:46

I have a model like this:

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


        
相关标签:
3条回答
  • 2020-12-07 17:50

    I would implement this slightly differently.

    I would use a default primary key (auto field), and use the meta class property, 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

    0 讨论(0)
  • 2020-12-07 17:53

    if you should use django on legacy database, you can't modify 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
    
    class 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'),)
    
    0 讨论(0)
  • 2020-12-07 18:13

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

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

    0 讨论(0)
提交回复
热议问题