简化这个django查询

时间:2014-05-21 18:32:22

标签: python django

我有一个Post对象可以联系'文章'的PostTypes。或者'组织'。帖子有一个名为approved的字段,一个名为published的字段,还有一个跟踪Post的所有先前版本的历史记录。我想获得最新批准和发布的帖子。

class Post(Published, models.Model):
    headline = models.CharField(max_length=255)
    posttype = models.ForeignKey(PostType)
    organization = models.ManyToManyField('self', null=True,blank=True)
    history = HistoricalRecords() # django-simple-history   
    status = models.IntegerField(
        choices=settings.STATUS_CHOICES,
        default=settings.DRAFT_STATUS, # or can be settings.PUBLISHED_STATUS
        )

class PostType(models.Model):
    slug = models.CharField(max_length=32)
    name = models.CharField(max_length=15)

以下是图示:

sdf

这是我获得最新批准和发布的帖子的复杂方式。

  def get_context_data(self, **kwargs):
    context = super(ArticleCreate, self).get_context_data(**kwargs)

    # Get me all the posttypes except for articles
    exclude_articles = PostType.objects.exclude(slug__icontains="article")

    # get me approved organizations (i.e. not articles) that are approved
    orgs = Post.objects.filter(approved = True).filter(posttype__in=exclude_articles)
    result = []

    # for each of the organization, get me the latest published history
    for org in orgs:
        result.append(org.history.filter(status=settings.PUBLISHED_STATUS).order_by('-modified_date')[0].history_object)

    context['form'].fields['organization'].queryset = result
    return context

上面这样做的方法是返回一个列表而不是queryset(这是另一个问题)。我们可以简化这个并获得一个查询集吗?

1 个答案:

答案 0 :(得分:1)

现在,我还没有尝试过这种重构,所以请把它当作指针使用它!

首先,您不需要链接.filter()来电。你可以"只是"在一个过滤器调用中使用CSV样式并使用Q对象,然后您可以在过滤器中执行否定查询。

然后我们可以继续使用关系,现在我还没有使用过Django Simple History,但我猜测它可以用于正常的FK遍历。

这意味着您可以通过普通history__status访问者访问历史记录状态,最后,使用.values()方法可以直接从一个或多个值中获取列表因此,DB避免执行res.append(org[0].something)

所以,正如我所说的那样,我还没有尝试过这个代码,但它应该给你指向正确的方向。

def get_context_data(self, **kwargs):
    context = super(ArticleCreate, self).get_context_data(**kwargs)

    result = Post.objects.filter(approved = True, ~Q(posttype__slug_icontains="article"), \
                                history__status=settings.PUBLISHED_STATUS) \
                                .order_by('-modified_date').values('history_object')

    context['form'].fields['organization'].queryset = result
    return context

现在这没有任何意义,而且它很难阅读,所以我建议您将其移至Post模型经理。

class PostManager(models.ModelManager):

    def approved_and_published_posts(self):
        return self.get_queryset().filter(approved = True, ~Q(posttype__slug_icontains="article"), \
        history__status=settings.PUBLISHED_STATUS) \
        .order_by('-modified_date').values('history_object')


class Post(models.Model):
    objects = PostManager()

然后在您看来,您可以随时执行此操作:

orgs = Post.objects.approved_and_published_posts()

希望这会有所帮助,并至少指出你正确的方向!