Kurosh Ghanizadeh
Kurosh Ghanizadeh

Reputation: 569

Django renders a template that does not exist in specified directory

I have model 'Video' and I have a list view for this model, then in another app I'm trying to create a view 'UserVideosListView' that is viewable to the dedicated user. when I open the page in the browser before making any templates for this view I'm able to see current user's videos (not all videos).

# inside 'users' app
class UserVideosListView(ListView):
    model = Video
    template_name = "users/user_videos.html"
    context_object_name = 'videos'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['videos'] = Video.objects.filter(author=self.request.user)
        return context

# inside 'videos' app
class VideoListView(ListView):
    model = Video
    paginate_by = 25
    template_name = 'videos/video_list.html'
    context_object_name = 'videos'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['videos'] = Video.published_videos.all()
        return context

P.S. I'm sure that the URL I'm entering is current, and there is no template inside the 'users' directory

Upvotes: 1

Views: 232

Answers (1)

NKSM
NKSM

Reputation: 5854

Django renders videos/video_list.html because ListView is based on MultipleObjectTemplateResponseMixin and BaseListView:

class ListView(MultipleObjectTemplateResponseMixin, BaseListView):
    """
    Render some list of objects, set by `self.model` or `self.queryset`.
    `self.queryset` can actually be any iterable of items, not just a queryset.
    """

Within MultipleObjectTemplateResponseMixin (GitHub), the template name is also generated based on the model.

# If the list is a queryset, we'll invent a template name based on the
# app and model name. This name gets put at the end of the template
# name list so that user-supplied names override the automatically-
# generated ones.
if hasattr(self.object_list, 'model'):
    opts = self.object_list.model._meta
    names.append("%s/%s%s.html" % (opts.app_label, opts.model_name, self.template_name_suffix))

Django docs says MultipleObjectTemplateResponseMixin:

template_name_suffix

The suffix to append to the auto-generated candidate template name. Default suffix is _list.

get_template_names()

Returns a list of candidate template names. Returns the following list:

  • the value of template_name on the view (if provided)
  • <app_label>/<model_name><template_name_suffix>.html

I suggest you to override get_queryset() method instead of get_context_data()

class UserVideosListView(ListView):
    model = Video
    context_object_name = 'videos'
    ...

    def get_queryset(self):
        return super().get_queryset().filter(author=self.request.user))

Upvotes: 2

Related Questions