0

I have the following mixin in which I want retrieve the User model data to place these data on different clase based views that I am developing:

class UserProfileDataMixin(object):
    def get_context_data(self, **kwargs):
        context = super(UserProfileDataMixin, self).get_context_data(**kwargs)
        user = self.request.user
        #context['userprofile'] = user.profile
        if user.is_authenticated():
            context['userprofile'] = user.profile
        return context

Then, I have the following search view in which I have lookup users according to the following criteria with Q objects:

When we search by username and full_name field

class SearchView(UserProfileDataMixin, ListView):
    template_name = 'search.html'
    def get(self, request, *args, **kwargs):
        query = request.GET.get("q")
        qs = None
        if query:
            qs = User.objects.filter(
                Q(username__icontains=query) |
                Q(full_name__icontains=query)
            )
        context = {"users": qs}

        return render(request, "search.html", context)

When I inherit from UserProfileDataMixin this mixin gives me the possibility of having the userprofile context variable to pass it to my search.html template, which inherit from layout.html template, in which I perform the following validation:

search.html template

{% extends "layout.html" %}

layout.html template

{% if userprofile %}
    I put the data of user by example:
    avatar, username, full_name, and menu options to my app.   
{% endif %}

Until here, alls OK, but my class based view SearchView does not apply the UserProfileDataMixin because, I cannot get the user data on my template, which coming from layout.html.

When I get the search users template I get that:

enter image description here

I've change slightly my class based view SearchView overriding the get_queryset method instead of get method a

class SearchView(UserProfileDataMixin, ListView):
        template_name = 'search.html'
    def get_queryset(self):
        query = self.request.GET.get("q")
        qs = None
        if query:
            qs = User.objects.filter(
                Q(username__icontains=query) |
                Q(full_name__icontains=query)
            )
        context = {"users": qs}
        return render(self.request, "search.html", context)

And my my class based view SearchView apply the UserProfileDataMixin because I can get the user data from layout.html on my template. Now appear my top header menu which is bring by UserProfileDataMixin

enter image description here

But I have now the inconvenient of my Q lookup query does not works

Why is the reason to UserProfileDataMixin does not applied on my class based view SearchView when I override the get method but if when I override get_queryset method, but this remove the effect of my custom lookup q object query?

When should I use get,and when use get_queryset?

In this answer question explain about of the subject, and I think that use the get_queryset is suited, but, why my query is not performed of the same way as when I use get method? And why using the get method my UserProfileDataMixin is not inherited?

bgarcial
  • 2,915
  • 10
  • 56
  • 123

1 Answers1

1

The base implementation of get() calls get_context_data() for you. However, because you have overridden get() with your own implementation, you would need to call get_context_data() yourself.

class SearchView(UserProfileDataMixin, ListView):
    template_name = 'search.html'

    def get(self, request, *args, **kwargs):
        query = request.GET.get("q")
        qs = None
        if query:
            qs = User.objects.filter(
                Q(username__icontains=query) |
                Q(full_name__icontains=query)
            )

        # Get the context data from the base class (mixin) and update it
        context = super(SearchView, self).get_context_data()
        context["users"] = qs

        return render(request, "search.html", context)

However, a better solution may be to not override get() at all, and implement a view specific get_context_data() in your SearchView. e.g.

class SearchView(UserProfileDataMixin, ListView):
    template_name = 'search.html'

    def get_context_data(self, **kwargs):
        query = self.request.GET.get("q")
        qs = None
        if query:
            qs = User.objects.filter(
                Q(username__icontains=query) |
                Q(full_name__icontains=query)
            )
        context = super(SearchView, self).get_context_data(**kwargs)
        context["users"] = qs
        return context

Lastly, your get_queryset() implementation is not doing the right thing, because that method is meant to return a QuerySet object, whereas in your case it is rendering a template.

Will Keeling
  • 22,055
  • 4
  • 51
  • 61