Home > Enterprise >  ListView and get_queryset with two models
ListView and get_queryset with two models

Time:02-01

I have 2 models in which I need to do a search:

class Movies(models.Model):
    title = models.CharField(max_length=100)

    class Meta:
        db_table = "movies"

    def __str__(self):
        return self.title


class Actors(models.Model):
    name = models.CharField(max_length=100)
    movies = models.ManyToManyField(Movies, related_name="actors")

    class Meta:
        db_table = "actors"

    def __str__(self):
        return self.name

I have a search form and need to search in Movies title and Actors name. I know how to make view for search in one model:

class SearchView(ListView):
    template_name = "search_results.html"
    model = Actors

    def get_queryset(self):
        query = self.request.GET.get('q')
        object_list = Actors.objects.filter(name__icontains=query)
        return object_list

But how to make when I want to search in two models? The result should then list the occurrences in actor names and occurrences in movie titles separately in the template. How to update my View easily?

I tried to add a method get_context_data to extend the context, but unfortunately I don't know how to access the second model in get_query-set. I use default db.sqlite3.

Thank you very much!

CodePudding user response:

You were on the right track with adding a get_context_data function, as in a ListView the get_queryset function is used for model that the list view is based on. This should work for the get_context_data function:

def get_context_data(self,*args,**kwargs):
   context = super(SearchView,self).get_context_data(*args,**kwargs)
   
   query = self.request.GET.get('q')
   movies = Movies.objects.filter(title__icontains=query)

   context['movies_list'] = movies
   return context

Then in your template you would access the movies by the context variable name {{ movies_list }}.

Let me know if you have any questions.

CodePudding user response:

 class SearchView(ListView):
        template_name = "search_results.html"
        context_object_name = 'actors'
        model = Actors
        movies = None
    
        def get_queryset(self):
            qs = super().get_queryset()
            query = self.request.GET.get('q')
            if query:
               qs= qs.filter(name__icontains=query)
               movies = Movies.objects.filter(title__icontains=query).all()
               if movies:
                  self.movies = movies
            return qs

        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['movies'] = self.movies
            return context
  •  Tags:  
  • Related