Testing class-based views with custom context_object_name

I was following the docs at Advanced testing topics | Django documentation | Django with a CBV which has set a custom context_object_name (“reports” in my case).

If I try to access view.get_context_data() in my test class, I get the error:
AttributeError: ‘DashboardView’ object has no attribute ‘object_list’

I does work, if I specify my context_object_name here, too:
context = view.get_context_data(object_list=“reports”)

Although view is an instance of my CBV, so it does have access to context_object_name.
Is this something which can be added to Django, to check for this property?
If no object_list is passed, check if the class has a context_object_name set, otherwise set None.
This way I don’t have to double specify my context_object_name.

You can check for the existence of an attribute on a an object, and retrieve that attribute by name using Python’s hasattr and getattr functions.

Thank you for your message.

I’m aware of that. I’m asking if this could be a feature request for Django itself. So you don’t have to double specify such things.

I guess I’m not following what the issue is here then. You can interrogate the view for the existence of the context_object_name attribute, and then do whatever you need to do with that information.

It may be helpful if you posted the full code of the test you’re trying to run.

I’m not asking for my code, but for an addition to Django itself, because I think this is redundant.

class DashboardView(ListView):
    model = Report
    context_object_name = "reports"

class DashboardViewTest(TestCase):
    request = RequestFactory().get("dashboard")
    view = DashboardView()
    view.setup(request)

    context = view.get_context_data() # does not work

This will produce the error AttributeError: ‘DashboardView’ object has no attribute ‘object_list’

Django (not my code) could simply check, as I wrote above, for the existence of context_object_name, so I don’t have to specify it in my test (again):

class DashboardViewTest(TestCase):
    request = RequestFactory().get("dashboard")
    view = DashboardView()
    view.setup(request)

    context = view.get_context_data(object_list="reports") # this does work but is redundant

So currently I have to double specify reports, in my view and in my test, even though the view object in the test has access to context_object_name.

Does this make it more clear?

I’m writing here in this forum, because the Django docs says to ask here first before submitting a ticket.

Absolutely, thank you.

First, this specific situation you are encountering is due to the difference between a DetailView (as being shown in the docs) and a ListView.

In the sequence of events that occurs in a ListView, get_context_data is dependent upon being called within get. Or, more specifically, get_context_data shouldn’t be called until after get_queryset has been called, which is what sets self.object_list.

So the root issue here isn’t specifically naming object_list within your get_context_data, but that self.object_list hasn’t been set in those cases where you’re not explicitly passing object_list as a parameter.

If you add view.object_list = view.get_queryset() prior to context = view.get_context_data(), it will work.

Or, if you know that context_object_name is going to be set in the class:
context = view.get_context_data(object_list=view.context_object_name)

But as a side-note, I don’t consider this “redundant” in any meaningful sense of the word. You’re writing a test here, not adding to your core code. Some degree of repetition is going to occur as you are short-circuiting the normal flow of events through these views.

1 Like