解决Django多表继承中涉及的表中的字段名称冲突

时间:2011-11-01 05:19:56

标签: django django-models

我正在寻找一种解决以下模型中出现的字段名称冲突的好方法:

from django.db import models
from django.contrib.auth.models import User

class OauthProfile(models.Model):

    user = models.ForeignKey(User, null=True, blank=True, default=None)
    oauth_token = models.CharField(max_length=200)
    oauth_secret = models.CharField(max_length=200)

class TwitterProfileInfo(OauthProfile):

    user_id = models.IntegerField(unique=True)
    screen_name = models.CharField(max_length=40, unique=True)

OauthProfile模型在appname_oauthprofile表中生成一个名为user_id的列,而继承自OauthProfile的TwitterProfileInfo模型在appname_twitterprofileinfo表中生成一个同名的列。故意在根User对象之前创建配置文件,因此我已将OauthProfile用户属性定义为允许NULL,默认值为None。

当保存类型为TwitterProfileInfo的对象而不为其用户属性赋值或显式将其分配给None时,我希望appname_oauthprofile.user_id在数据库中保留为NULL。相反,查看PostgreSQL日志,我可以看到它被分配了我分配给对象的user_id属性的值。这会导致引用完整性错误,因为auth_user表中没有行具有该值。

myProfile = TwitterProfileInfo()
myProfile.user = None
myProfile.user_id = 12345 # Django tries to assign this to appname_oauthprofile.user_id
myProfile.screen_name = 'sometwitteruser'
myProfile.oauth_token = '1234567890abcdefg'
myProfile.oauth_secret = 'sometauthtokensecret'
myProfile.save() # results in error

我可以重命名其中一个冲突字段,例如将TwitterProfileInfo字段名称更改为类似于twitter_user_id的字段。但我想知道是否有办法解决这个冲突而不这样做。如果我没有对数据库的控制并且被限制使用这些列名称,我将如何定义这些模型以使其工作?

2 个答案:

答案 0 :(得分:1)

Django的多表继承就是这样的反模式。它有各种可怕的后果,就像你注意到的那样。

您的问题的答案是,不要使用继承。在TwitterProfileInfoOauthProfile之间使用明确的OneToOneField。数据库结构完全相同,您可以完全控制如何引用字段。唯一的区别是你需要单独实例化和保存OauthProfile对象,并明确设置关系:

my_oauth = OauthProfile(oauth_token='1234567890abcdefg', oauth_secret='sometauthtokensecret')
my_oauth.save()
my_twitter = TwitterProfileInfo(oauth_profile=my_oauth, user_id=12345)
my_twitter.save()

答案 1 :(得分:0)

我不确定为什么我最初没有想到db_column选项。这很好,至少就这个例子而言:

class TwitterProfileInfo(OauthProfile):

    twitter_user_id = models.IntegerField(db_column='user_id', unique=True)
    screen_name = models.CharField(max_length=40, unique=True)

然后在其他地方......

myProfile = TwitterProfileInfo()
myProfile.user = None
myProfile.twitter_user_id = 12345 # use the "custom" attribute name instead
myProfile.screen_name = 'sometwitteruser'
myProfile.oauth_token = '1234567890abcdefg'
myProfile.oauth_secret = 'sometauthtokensecret'
myProfile.save() # no error

但是,我很好奇与Django的多表继承相关的负面后果。如果它们很重要,那么我将倾向于接受Daniel's回答。