Django 代理模型如何添加字段?

11 投票
3 回答
17406 浏览
提问于 2025-04-16 23:58

我正在写一个类似报纸的Django应用程序。我有一些文章,还有一些在特定情况下显示的定制版本的文章。比如,我可能会有一篇文章的版本,它出现在报纸的首页上,并且标题比原来的短一些。所以,我有:

class Article(models.Model):
    """ A newspaper article with lots of fields """
    title = models.CharField(max_length=255)
    content = models.CharField(max_length=255)

    # Lots of fields...

我想要一个CustomArticle对象,它是Article的一个代理,但可以有一个可选的替代标题:

class CustomArticle(Article):
    """ An alternate version of a article """
    alternate_title = models.CharField(max_length=255)

    @property
    def title(self):
        """ use the alternate title if there is one """
        if self.custom_title:
            return self.alternate_title
        else:
            return self.title
            
    class Meta:
        proxy = True
    
    # Other fields and methods

可惜的是,我不能在代理中添加新的字段:

>>> TypeError: Abstract base class containing model fields not permitted for proxy model 'CustomArticle'

所以,我可以这样做:

class CustomArticle(models.Model):
    # Other methods...
    
    original = models.ForeignKey('Article')

    def __getattr__(self, name):
        if hasattr(self.original):
            return getattr(self.original, name)
        else:
            return super(self, CustomArticle).__getattr__(name)

但是不幸的是,__getattr__似乎在Django模型中不起作用。因为Article类中的字段可能会改变,所以在CustomArticle中为每个字段创建一个@property方法并不实际。那么,正确的做法是什么呢?

3 个回答

1

你有没有想过把CustomArticle变成Article的一个子类呢?Django的模型是支持继承的!你可以看看这个链接了解更多信息:https://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance

1

试试这样做:

class CustomArticle(models.Model):
    # Other methods...

    original = models.ForeignKey('Article')

    def __getattr__(self, name):
        return getattr(self.original, name)
3

看起来这个方法可能适用于 __getattr__

def __getattr__(self, key):

    if key not in ('original', '_ original_cache'):
        return getattr(self.original, key)      
    raise AttributeError("'%s' object has no attribute '%s'" % (self.__class__.__name__, key))

撰写回答