Search code examples
pythonpython-3.xdjangodjango-viewsdjango-listview

Django ListView: 'this_object_id' is not defined


I keep having issues when I want to refer to a specific object in ListView.

My views:

class SongList(generic.ListView):
    model = models.Song
    template_name = 'videos/song_list.html'
    context_object_name = 'song_list'

    def get_context_data(self, **kwargs):
        context = super(SongList, self).get_context_data(**kwargs)
        user_flash = Flashcard.objects.filter(owner=self.request.user).values_list('question', flat=True)
        song = models.Song.objects.get(pk=this_object_id)  #works if hard-coded
        lyrics_list = models.Song.objects.get(song=song).lyrics_as_list()
        user_word = list(set(user_flash) & set(lyrics_list))
        context['percent_known'] = (len(user_word)/len(set((lyrics_list))))*100
        return context

I get the following error: name 'this_object_id' is not defined

I've tried various variations, but I keep getting errors, e.g.

self.kwargs['pk']
self.kwargs.get['pk']

Then I get the error: KeyError 'pk'

It works when I hard-code the pk, so the problem is not elsewhere my code. It also works when I do it in my DetailView (using self.kwargs['pk']), but I need access to percent_known for every object in my ListView. How can I do this? I can sort of understand why it doesn't work, ListView is for a list of objects, so it doesn't know for what object I want to get this info for... but there must be a way I can do it for every object? Or is there another way to get access to percent_known for every object?


Solution

  • The main issue here is that in the get_context_data() method you are trying to access information for a single item, when you are actually managing a list.

    If you have some difficult calculations to perform for every object of your list, you can access those objects in the get_context_data(), like:

    def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
    
            for song in context['song_list']:
                 # Here you already have the current Song object you want to process
                 lyrics_list = models.Song.objects.get(song=song).lyrics_as_list()
    
                 # and so on...
            
            return context
    
    

    Another more efficient option would be to perform this calculations using the Django ORM system, annotating the Songs list under the get_queryset() method.