需要帮助 - 模型设计

时间:2014-03-03 10:33:57

标签: django postgresql django-models multiple-inheritance

这可能很长,但在我的制作中使用它之前我真的需要你的帮助。我有class Asset,这是其他base class的{​​{1}}等。)基本上是classes (like Photo, Question, Video。我需要这个来获取模板中的所有帖子或用户的所有对象。它做我想要的。但是我注意到,很多人反对Multiple Table Inheritance,有些人气馁Multiple Table Inheritance。所以,我真的需要你使用Multiple Table Inheritance的一般意见。而且,我还有其他选择吗?或者是否有任何其他方法可以获得Multiple Table Inheritance的所有对象(assets)?请帮我决定做什么。我正在使用django和postresql。如果我不清楚,请问我。如果有人能指导我完成这件事,我将非常感激和欣赏。

谢谢。

这是我的模特:

User

2 个答案:

答案 0 :(得分:1)

所以我认为你正在做某种时间线应用。我的建议是让您的Asset模型与您的不同资产类型建立OneToOneField关系。所以你的Asset模型看起来像是:

class Asset(models.Model):
    user = models.ForeignKey(User, related_name = "user_objects")
    likes = models.ManyToManyField(User, through="Like", related_name="Liked_user")
    comments = models.ManyToManyField(User, through="Comment", related_name="Commented_user")
    timestamp = models.DateTimeField(auto_now = True, auto_now_add= False)
    updated = models.DateTimeField(auto_now = False, auto_now_add = True)

    album = models.OneToOneField(Album, null=True, blank=True)
    picture = models.OneToOneField(Picture, null=True, blank=True)
    question = models.OneToOneField(Question, null=True, blank=True)
    answer = models.OneToOneField(Answer, null=True, blank=True)
    # etc...

    class Meta:
        ordering = ['-timestamp']

    def __unicode__(self):
        return self.__class__.__name__

AlbumPictureQuestion& Answer将不再继承Asset,但会成为标准模型。

通过这种方式,您可以在公共集合中拥有资源,并根据需要对它们进行排序/显示。然后,根据哪个字段不为空,这将是单个资产的“类型”。需要进行一些手动检查以确定类型并确保资产不是空的,但它们不同,以至于它们无论如何都需要自定义处理。我以前曾多次做过这种事情,但它对我的用例来说很好。

答案 1 :(得分:1)

现在我已经考虑过这个了,我想建议另一个使用Django contenttypes framework解决通用关系的解决方案。之前我没有注意到你有2级继承(即Asset-> Picture-> BackgroundImage)。我之前的回答仍然可行,但您必须添加到子模型的显式链接。这样您就可以干净地Asset链接到您的所有资产类型,反之亦然。

class Asset(models.Model):
    user = models.ForeignKey(User, related_name = "user_objects")
    likes = models.ManyToManyField(User, through="Like", related_name="Liked_user")
    comments = models.ManyToManyField(User, through="Comment", related_name="Commented_user")
    timestamp = models.DateTimeField(auto_now = True, auto_now_add= False)
    updated = models.DateTimeField(auto_now = False, auto_now_add = True)

    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    class Meta:
        ordering = ['-timestamp']

    def __unicode__(self):
        return self.__class__.__name__

class Like(models.Model):
    asset = models.ForeignKey(Asset)
    liked_by = models.ForeignKey(User)
    liked_time = models.DateTimeField(auto_now = True, auto_now_add = False)

    def __unicode__(self):
        return "%s likes %s" % (self.liked_by, self.asset)

class Comment(models.Model):
    asset = models.ForeignKey(Asset)
    comment_by = models.ForeignKey(User)
    liked_time = models.DateTimeField(auto_now = True, auto_now_add = False)

    def __unicode__(self):
        return "%s likes %s" % (self.comment_by, self.asset)

def get_upload_file_name(instance, filename):
    return "uploaded_files/%s_%s" %(str(time()).replace('.','_'), filename)


class AlbumAsset(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    asset = generic.GenericRelation(Asset)

    def __unicode__(self):
        return self.__class__.__name__

class PictureAssetBase(models.Model):
    description = models.TextField()
    image = models.ImageField(upload_to=get_upload_file_name)
    album = models.ForeignKey(Album, null=True, blank=True, default = None)
    asset = generic.GenericRelation(Asset)

    def __unicode__(self):
        return self.__class__.__name__

    class Meta:
        abstract = True

class PictureAsset(PictureAssetBase):
    pass

class BackgroundImageAsset(PictureAssetBase):
    pass

class ProfilePictureAsset(PictureAssetBase):
    pass


class Tag(models.Model):
    title = models.CharField(max_length=40)
    description = models.TextField()

    def __unicode__(self):
        return self.title

class QuestionAsset(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    tags = models.ManyToManyField(Tag)
    asset = generic.GenericRelation(Asset)

    def __unicode__(self):
        return self.title

class AnswerAsset(models.Model):
    description = models.TextField()
    question = models.ForeignKey(Question)
    asset = generic.GenericRelation(Asset)

    def __unicode__(self):
        return self.description 

请注意content_object中的Asset字段。我还建议您为照片制作ABC PictureAssetBase(注意abstract=True作为docs here中的说明)并PictureAssetBackgroundImageAsset& ProfilePictureAsset继承了这一点。

所有资产类型模型都通过AssetGenericRelation具有反向关系。通过这种方式,您可以自由添加新资产类型,而对其他模型的影响最小。在您的视图等中,您显然需要为每种类型提供特殊处理,但您可以通过Asset中的content_type字段确定链接的资产类型,或者添加显式类型字段并自行处理。