Django模型继承及在视图中转换为子类

2 投票
1 回答
1748 浏览
提问于 2025-04-18 08:56

这是一种内容管理系统类型的应用。

我有一个文章模型,还有一些在models.py里的特殊化模型。

class Article(models.Model):
    foo = models.CharField(max_length=50)
    bar = models.CharField(max_length=100,blank=True)
    DISPLAY_CHOICES = (
        ('N', 'None'),
        ('C','Carousel'),
        ('M','Marketing'),
        ('F','Featurette')
    ) 
    display = models.CharField(max_length=1, choices = DISPLAY_CHOICES)

def __unicode__(self):
    return self.title

class Artist(Article):
    website = models.URLField(max_length=200,blank=True)

class Venue(Article):
    location = models.CharField(max_length=150)
    map_link = models.URLField(max_length=200,blank=True)

class Event(Article):
    time = models.DateTimeField()
    venue = models.ForeignKey(Venue)
    performers = models.ManyToManyField(Artist)

我想根据文章的display属性以不同的方式来展示这些内容,但当我调用

articles.objects.all()

时,我仍然需要从子类中获取额外的属性,所以我写了

#views.py
def castToSubClass(article):
    try:
        return Artist.objects.get(article_ptr_id = article.id)
    except:
        try:
            return Event.objects.get(article_ptr_id = article.id)
        except:
            try:
                return Venue.objects.get(article_ptr_id = article.id)
            except:
                return article


def index(request):
    carousel = [castToSubClass(article) for article in Article.objects.filter(display='C']
    marketing = [castToSubClass(article) for article in Article.objects.filter(display='M'[:3]]
    featurettes = [castToSubClass(article) for article in Article.objects.filter(display='F']
    return render_to_response('frontpage.html',
    {
    'carousel': carousel,
    'marketing':marketing,
    'featurettes': featurettes
    })

来把它们都转换成合适的子类对象。这样做除了看起来有点繁琐之外,还意味着我每处理一个(或几乎每个)查询集中的项目,就要访问数据库两次。

有没有办法在最初调用管理器的时候就做到这一点呢?

谢谢。

1 个回答

0

用一个模型来存储所有内容,然后添加一个字段来区分文章类型。这样在模板中结合display,就可以为每种类型渲染不同的样式(就像tumblr那样)。

class Article(models.Model):
    foo = models.CharField(max_length=50)
    bar = models.CharField(max_length=100,blank=True)
    DISPLAY_CHOICES = (
        ('N', 'None'),
        ('C','Carousel'),
        ('M','Marketing'),
        ('F','Featurette')
    ) 
    display = models.CharField(max_length=1, choices = DISPLAY_CHOICES)
    ARTICLE_TYPE_CHOICES = (
        ('artist', 'Artist'),
        ('venue', 'Venue'),
        ('event', 'Event'),
    )
    type = models.CharField(max_length=32, choices = ARTICLE_TYPE_CHOICES)
    website = models.URLField(max_length=200,blank=True, null=True)
    location = models.CharField(max_length=150, blank=True, null=True)
    map_link = models.URLField(max_length=200,blank=True, null=True)
    time = models.DateTimeField(null=True)
    venue = models.ForeignKey('self', null=True)
    performers = models.ManyToManyField('self', null=True)


def __unicode__(self):
    return self.title


#views.py
def index(request):
    carousel = Article.objects.filter(display='C')
    marketing = Article.objects.filter(display='M')
    featurettes = Article.objects.filter(display='F')
    return render_to_response('frontpage.html',{'carousel': carousel, 'marketing':marketing, 'featurettes': featurettes})

撰写回答