【问题标题】:Order a recipe queryset by replies number using django-disqus使用 django-disqus 按回复编号订购食谱查询集
【发布时间】:2018-03-08 18:57:18
【问题描述】:

我有一个recipe 模型:

class Recipe(models.Model):
    title = models.CharField(_("Recipe Title"), max_length=250)
    slug = models.SlugField(_('slug'), unique=True)
    author = models.ForeignKey(User, verbose_name=_('user'))
...

我需要为大多数评论食谱创建一个视图,我正在使用django-disqus 来处理食谱的 cmets,但我不知道如何按食谱的评论编号订购查询集。

class PopRecipeListView(GlobalQueryMixin, ListView):
    model = Recipe
    context_object_name = "recipe_list"
    template_name = 'recipe/recipe_top_list.html'

    def get_queryset(self):
        qs = super(PopRecipeListView, self).get_queryset()

        if qs:
            qs = qs.extra(
                select={
                    'comments': # get comment numbers
                }
            ).filter(shared=True).order_by('-rate')[:20]

        return qs

我在文档中找到了这个:https://disqus.com/api/docs/forums/listThreads/ 我可以得到一个带有站点和论坛 id 的 json 文件并遍历它们以获得正确的密钥,但我认为这并不容易。

看起来更深入,我可以使用以下方法获取json 文件: var url = "https://disqus.com/api/3.0/forums/listThreads.json?api_key=" + api_key + "&forum=" + forum; //+ "&limit=100";,但我不确定。

好的,我有下一个函数来获取该参数:

def get_comments_by_site():
    api_key = settings.DISQUS_API_KEY
    forum = settings.DISQUS_WEBSITE_SHORTNAME

    url = 'https://disqus.com/api/3.0/forums/listThreads.json?api_key={0}&forum={1}&limit=100'.format(api_key, forum)

    raw = requests.get(url)
    dict = json.loads(raw)

    values = {}

    for thread in dict['response']:
        item = {thread['slug']: thread['posts']}
        values.update(item)

    return values


def get_comments_number(slug):
    return values[slug]

我创建了两个不同的函数,因为我希望 View 一次获取所有值,然后在 query 中调用 secong 函数以从获取的字典中获取值。

我创建了一个mixin 来整合这两个功能:

class DisqusCommentsNumber(object):
    values = {}

    def get_comments_by_site(self):
        api_key = settings.DISQUS_API_KEY
        forum = settings.DISQUS_WEBSITE_SHORTNAME

        url = 'https://disqus.com/api/3.0/forums/listThreads.json?api_key={0}&forum={1}&limit=100'.format(api_key,
                                                                                                          forum)

        raw = requests.get(url)
        dict = json.loads(raw)

        for thread in dict['response']:
            item = {thread['slug']: thread['posts']}
            self.values.update(item)

        return self.values

    def get_comments_number(self, slug):
        return self.values[slug]

我在这里使用annotate

def get_queryset(self):
    qs = super(PopRecipeListView, self).get_queryset()

    if qs:
        qs = qs.annotate(num_comments=get_comments_number('slug')).filter(shared=True).order_by('-num_comments')

    return qs

我将annotate 替换为extra 并且:

def get_queryset(self): qs = super(PopRecipeListView, self).get_queryset()

if qs:
    qs = qs.extra(
        select={
            'num_comments': '{0}'.format(
                self.get_comments_number(Recipe.slug)
            )
        }
    ).filter(shared=True).order_by('-num_comments')

return qs

现在我得到这个错误: KeyError at /recipe/popular/ <django.db.models.query_utils.DeferredAttribute object at 0x7f90048f7470>

我认为mixin 有问题。

我更新了在dispatch 函数中获取所有值的视图,但我收到了这个错误:

KeyError at /recipe/popular/
<django.db.models.query_utils.DeferredAttribute object at 0x7f6ffebfa4e0>

代码here

我现在正在测试其他方法: 我做了一个函数来获取这个值,因为模型是一个属性:

@property
def get_comments_number(self):
    api_key = settings.DISQUS_API_KEY
    forum = settings.DISQUS_WEBSITE_SHORTNAME
    url = 'https://disqus.com/api/3.0/forums/listThreads.json?api_key={0}&forum={1}&thread:ident={2}'.format(
        api_key,
        forum,
        self.slug
    )
    raw = requests.get(url)
    thread = json.loads(raw.content)

    return thread['response'][0]['posts']

有了这个和一个新的字段排序会更容易,但是,我如何使用这个函数来获取值并保存在数据库中? 哪种方法最适合这项任务?

谢谢。

【问题讨论】:

  • 显示Recipe的模型定义

标签: python django disqus


【解决方案1】:

尝试.annotate(),然后按这个新注释的属性排序。

请看这里:https://docs.djangoproject.com/en/2.0/ref/models/querysets/#annotate

【讨论】:

  • 我可以使用字典中的 slug 过滤函数并获取相应的值一个新的注释值吗?
  • 不,我不能。我测试了它,我得到了这个:KeyError at /recipe/popular/ 'slug'
  • @SalahAdDin 这个调用似乎是错误的get_comments_number('slug'),因为那里有某些 slug 值,而不是常量键 slug。查看item = {thread['slug']: thread['posts']}中的代码
  • 如果您在Recipe 模型中有slug 作为字段,请像F('slug') 一样访问它并记住导入from django.db.models import F
  • 为了什么?我现在正在使用额外的,但我遇到了其他问题。
【解决方案2】:

最后我改变了我的方法:

我在recipe 模型中创建了一个新的函数属性:

    @property
    def get_comments_number(self):
        api_key = settings.DISQUS_API_KEY
        forum = settings.DISQUS_WEBSITE_SHORTNAME
        url = 'https://disqus.com/api/3.0/forums/listThreads.json?api_key={0}&forum={1}&thread:ident={2}'.format(
            api_key,
            forum,
            self.slug
        )
        raw = requests.get(url)
        thread = json.loads(raw.content)

        return thread['response'][0]['posts']

之后,我在模型中添加了一个新字段以保存 comment's number 值。

最后,我在DetailView 中调用该属性以更新评论的编号:

def dispatch(self, request, *args, **kwargs):

# TODO: maybe it is necessary create a task for update this in other cases
r = self.get_object()
r.comments = r.get_comments_number
r.save()

# check if the recipe is a private recipe if so through a 404 error
if r.shared == False and self.object.author != request.user:
    output = _("Recipe {0} is marked Private").format(self.get_object().slug)
    raise Http404(output)
else:
    return super(RecipeDetailView, self).dispatch(request, *args, **kwargs)

现在我可以在另一个视图中按评论编号进行过滤:

qs = qs.filter(shared=True).order_by('-comments')

就是这样。

【讨论】:

    猜你喜欢
    • 2012-01-18
    • 2013-01-12
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 1970-01-01
    • 1970-01-01
    • 2020-08-30
    相关资源
    最近更新 更多