【问题标题】:django-filter: merge 2 models in one filterdjango-filter:在一个过滤器中合并 2 个模型
【发布时间】:2016-03-26 23:35:49
【问题描述】:

我使用http://django-filter.readthedocs.org/en/latest/usage.html 并且有 2 个具有相同字段名称的模型,并且我需要为两个模型提供一个过滤器表单(不是单独的模型过滤器表单,因为对于 2 个字段,它将变成 4 个具有相同名称的表单字段)

class VkwallpostFilter(django_filters.FilterSet):
    date_created = django_filters.DateFilter(lookup_type='gte', label='Дата публикации', input_formats=['%Y-%m-%d'], initial=date.today)
    class Meta:
        model = Vkwallpost
        fields = ['project', 'date_created']

class FbpagepostFilter(django_filters.FilterSet):
    date_created = django_filters.DateFilter(lookup_type='gte', label='Дата публикации', input_formats=['%Y-%m-%d'], initial=date.today)
    class Meta:
        model = Fbpagepost
        fields = ['project', 'date_created']  

我现在无法配置视图以获取模型的合并查询集:

def wallpost_list(request):
    vk = VkwallpostFilter(request.GET, queryset=Vkwallpost.objects.all())
    fb = FbpagepostFilter(request.GET, queryset=Fbpagepost.objects.all())
    items = list(vk) + list(fb)
    items.sort(key=lambda i: i.date_created, reverse=True)
    return render_to_response('vk_list.html', {'filter': items})

如您所见,我可以将 2 个模型合并到一个列表中并作为“过滤器”传递给模板,但在这种情况下,模板中的整个表单都会消失!顺便说一句,过滤正在工作。 我猜它为什么会消失——因为它不知道在过滤器中选择什么类。

所以我需要在一个过滤器中合并 2 个模型

【问题讨论】:

  • @Hybrid 是的,当然,我得到一个错误'unsupported operand type(s) for |: 'VkwallpostFilter' and 'FbpagepostFilter'' 我认为那是因为 VkwallpostFilter 不是查询集,它是一个过滤器类.也尝试合并 queryset=Vkwallpost.objects.all() 但也没有运气

标签: django django-queryset django-filter


【解决方案1】:

我能够自己解决这个问题,但没有 django-filter 模块,下面的完整代码。 关键是使用显示表单的标准 django 视图(可以在文档中找到),在表单逻辑之后,我添加了负责显示帖子列表的代码(从行 criteria = {} 开始)

关键部分是将 url 参数的 dict 传递给 2 个模型的两个查询集,并根据 url 参数 'source' 选择要在 postlist 中显示的内容:

if source == 'vk':
    items = list(vkposts)
elif source == 'fb':
    items = list(fbposts)
else:
    items = list(vkposts) + list(fbposts)

如此完整的视图:

def wallpost_list(request, page_number=1):
    success = False
    project = ''
    date_created = ''
    text = ''
    source = ''

    if request.method == 'POST':
        postfilter_form = PostfilterForm(request.POST)
        if postfilter_form.is_valid():
            success = True
            project = postfilter_form.cleaned_data['project']
            date_created = postfilter_form.cleaned_data['date_created']
            #text = postfilter_form.cleaned_data['text']
            return redirect('posts/?project=%s&date_created=%s' % (project, date_created))
    else:
        postfilter_form = PostfilterForm(initial={'project':request.GET.get('project', '3'), 'date_created':request.GET.get('date_created', '3'),})

    criteria = {}
    last_date = date(2017, 12, 31)
    if 'author' in request.GET:
        criteria['from_id'] = int(request.GET['author'])
        success = True
    if 'likes' in request.GET:
        criteria['likes.count'] = int(equest.GET['likes'])  # {'$in': [int(sex) for sex in request.GET.getlist('sex')]}#int(request.GET['sex'])  #/?group=20548110&sex=1&sex=2   # This will return [1,2]
        success = True
    if 'comments' in request.GET:
        criteria['comments.count'] = int(request.GET['comments'])  # {'$elemMatch': {'artist': request.GET['music_artist']}}
        success = True
    if 'project' in request.GET:
        #project = Userproject.objects.get(name=self.request.GET['project'])
        criteria['project__name'] = request.GET['project']
        success = True
    if 'sentiment' in request.GET:
        criteria['sentiment'] = request.GET['sentiment']  # {'$elemMatch': {'artist': request.GET['music_artist']}}
        success = True
    if 'date_saved' in request.GET:
        criteria['date_saved__range'] = (parse(request.GET['date_saved']).date(), last_date)  # 'date': {'$gte': int(time.mktime(date_saved.timetuple()))}
        success = True
    if 'date_created' in request.GET:
        criteria['date_created__range'] = (parse(request.GET['date_created']).date(), last_date)  # 'date': {'$gte': int(time.mktime(date_saved.timetuple()))}
        success = True
    if 'source' in request.GET:
        source = request.GET['source'] 
        success = True         
    print(criteria)    

    vkposts = Vkwallpost.objects.filter(**criteria).order_by("-date_created")#[:5]
    fbposts = Fbpagepost.objects.filter(**criteria).order_by("-date_created")#[:5]
    if source == 'vk':
        items = list(vkposts)
    elif source == 'fb':
        items = list(fbposts)
    else:
        items = list(vkposts) + list(fbposts)
    items.sort(key=lambda i: i.date_created, reverse=True)
    post_list = items
    current_page = Paginator(post_list, 20)
    # context['post_list'] = items # post_list это VK + FB posts
    # vk = VkwallpostFilter(request.GET, queryset=Vkwallpost.objects.all())
    # fb = FbpagepostFilter(request.GET, queryset=Fbpagepost.objects.all())
    # items = list(vk) + list(fb)
    # items.sort(key=lambda i: i.date_created, reverse=True)
    return render_to_response('vk_list.html', {'post_list': current_page.page(page_number), 'postfilter_form': postfilter_form,
                                               'project': project, 'date_created': date_created, 'source': source, 'text': text, 'success': success}
                              , context_instance=RequestContext(request))

【讨论】:

    【解决方案2】:

    我看到了你的 github 帖子 :)

    您可以执行 vk.qs 和 fb.qs 来获取过滤后的 QuerySet。然后在您的上下文中,您需要 vk 和/或 fb,因为它们负责表单。

    【讨论】:

    • 能否提供完整代码?在上下文中我需要合并过滤器,而不是为 vk 和 fb 分开,想象我会分开,然后对于 2 个文件,我的用户需要输入 2x 过滤器 = 4
    • 只需使用一种形式,它会创建 get 参数,例如:?date_created=2015-12-24。这将自动过滤两个过滤器。
    • @ 我认为这是我们之间的误解)我有问题地指出,如果我对 2 个 qs 使用一种形式,我根本看不到。我能够自己解决这个问题,但没有 django-filter 模块
    猜你喜欢
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    相关资源
    最近更新 更多