Search code examples
djangodjango-viewsdjango-filter

Django, exclude from main list, but viewable from django filter


I'm trying to add an archive section to my site, though when I say archive, I mean just not visible in the main list view that is the home page, the site is small and the projects are just small amounts of text so space and optimization are never going to be needed. I use django-filter to search through projects by department(Area in my code), and "Archive" is down as one of the departments. I've tried using exclude in the queryset, but of course that just removes any projects with area="Archive" completely so that the "Archive" section is empty. How can I get archived projects removed from the main list view but searchable via the filter.

View:

def project_list_view(request):
    project_list = Project.objects.annotate(
        display_date = models.Case(
            models.When(models.Q(staff_trials__isnull=True) | models.Q(timeline_switch=False), then=models.F('launch')),
            models.When(models.Q(staff_trials__isnull=False) & models.Q(timeline_switch=True), then=models.F('staff_trials')),
            output_field=models.DateField(),
        )
    ).exclude(area='1').order_by('-slip', 'display_date')

    project_filter = ProjectFilter(request.GET, queryset=project_list)
    return render(
        request,
        'project_portal/project_list.html',
        {'filter': project_filter}
        )

filter:

class ProjectFilter(django_filters.FilterSet):

    class Meta:
        model = Project
        fields = ['area', 'user']

For clarity, Area has it's own Model with a foreign key to the Project model, and the departments are just entries in the database. The above code kind of does what I want, but as mentioned before makes archived projects not accessible in any way, whereas I want them to show if "Archive" is picked from the search dropdown.


Solution

  • One possible solution is add exclude to your queryset only if area filter not equal to archived:

    def project_list_view(request):
        project_list = Project.objects.annotate(
            display_date = models.Case(
                models.When(models.Q(staff_trials__isnull=True) | models.Q(timeline_switch=False), then=models.F('launch')),
                models.When(models.Q(staff_trials__isnull=False) & models.Q(timeline_switch=True), then=models.F('staff_trials')),
                output_field=models.DateField(),
            )
        ).order_by('-slip', 'display_date')
    
        if request.GET.get('area') != '1':
            project_list = project_list.exclude(area='1')
    
        project_filter = ProjectFilter(request.GET, queryset=project_list)
        return render(
            request,
            'project_portal/project_list.html',
            {'filter': project_filter}
            )