python - 简化这个 Django 查询

标签 python django

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

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

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

最佳答案

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

首先,您不需要链接 .filter() 调用。您可以在一个过滤器调用中“仅”使用 CSV 样式,并使用 Q对象,那么您可以在过滤器中执行否定查询。

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

所以这意味着您可以通过普通的 history__status 访问器访问历史状态,最后,使用 .values()方法将允许您直接从数据库中获取仅包含 1 个或多个值的列表,从而避免执行 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()

希望这对您有所帮助,至少能为您指明正确的方向!

关于python - 简化这个 Django 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23791166/

相关文章:

python - 使用嵌套 for 循环更新 dict

python : run multiple queries in parallel and get the first finished

python - 是否有 django 的 'hello world' 网站?或者(我已经安装了 django,现在是什么)?

python - 将图像模型与相似图像相关联

python - 如何在 Django 中将外键设置为默认值?

python - 如何查找 int 是否在数组数组中?

python - 使用 matshow 时 matplotlib 中的自定义颜色

python - 在 django 中重定向后无法访问 cookie

Django 模板渲染缓慢

javascript - Django Ajax 通信,Django 不识别为 Ajax(使用 request.is_ajax() )