Reputation: 61
I'm working on an website where user (if logged in) can perform a calculation and see all of his calculations listed. My website has two groups: Clients and Administrators where Clients are not allowed to see any other members' calculations except their own while Administrators are. Authentication is based on Django's built in User class and for each group I created separate views and templates. Templates have similar behavior but different displaying messages. When Clients want to see their calculations, correct information is displayed but the template rendered is for Administrators rather than for Clients.
views.py
#Administrators' view function
class CalculationListView(generic.ListView):
model = Calculation
paginate_by = 10
#Users' view function
class CalculationsByUserListView(LoginRequiredMixin, generic.ListView):
model = Calculation
paginate_by = 10
def get_queryset(self):
return Calculation.objects.filter(userid=self.request.user)
urls.py
urlpatterns = [
path('', views.index, name='index'),
path('calculations/', views.CalculationListView.as_view(), name='calculations'),
path('calculation/<int:pk>', views.CalculationDetailView.as_view(), name='calculation-detail'),
]
urlpatterns += [
path('mycalculation/', views.CalculationsByUserListView.as_view(), name='mycalcs'),
]
Template names
Administrators: calculation_list.html
Clients: calculations_user.html
EDIT: I mistakenly posted wrong test function. So, here's the one that produced the output referenced few lines below.
test.py
def test_logged_in_uses_correct_template(self):
login = self.client.login(username='testuser1', password='1X<ISRUkw+tuK')
response = self.client.get(reverse('mycalcs'))
# Check if user is logged in
self.assertEqual(str(response.context['user']), 'testuser1')
# Check for the response "success"
self.assertEqual(response.status_code, 200)
# Check if correct template used
self.assertTemplateUsed(response,'cycle/calculations_user.html')
Test response
======================================================================
FAIL: test_logged_in_uses_correct_template (cycle.tests.test_views.CalculationsByUserListViewTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\DEBIEVEL\Desktop\Work\Edited\django_test\orc2\cycle\tests\test_views.py", line 80, in test_logged_in_uses_correct_template
self.assertTemplateUsed(response, 'cycle/calculations_user.html')
File "C:\ProgramData\Anaconda3\lib\site-packages\django\test\testcases.py", line 661, in assertTemplateUsed
% (template_name, ', '.join(template_names))
AssertionError: False is not true : Template 'cycle/calculations_user.html' was not a template used to render the response. Actual template(s) used: cycle/calculation_list.html, base_generic.html
I tried changing mappings and names of the urls but than I get NoReverseMatch error when I run server but the above test passes. I'm not sure where exactly did I mess up so any help is welcome.
Upvotes: 1
Views: 254
Reputation: 61
So the issue wasn't in the view definition but in the template. Once I applied @Willem Van Onsem's solution, I started getting NoReverseMatch error for part of my template that actually displays the list. Upon further inspection I discovered it is the for loop in the template that actually raised an error. Since I haven't posted template code before, we were not able to spot it earlier.
The old for loop:
<ul>
{% for calc in calculation_list %}
<li> <a href="{% url 'calculation-detail' calc.user.pk %}"> Performed on {{calc.time_calculated}}</a>
</li>
{% endfor %}
</ul>
New for loop:
<ul>
{% for calc in calculation_list %}
<li> <a href="{{ calc.get_absolute_url }}"> Performed on {{calc.time_calculated}}</a>
</li>
{% endfor %}
</ul>
I also needed to move this specific template out of the templates/cycle folder to only templates/ Once, that was done, everything worked fine.
Upvotes: 0
Reputation: 476534
You should specify the name of the templates in the ListView
s. By default a ListView
[Django-doc] will use the name of the model (here calculation
), and then add a suffix _list
to it, this thus means that a ListView
with Calculation
as model, will render the calculation_list.html
template.
But this makes no sense for the CalculationsByUserListView
, you thus should specify the template_name
[Django-doc] with:
class CalculationsByUserListView(LoginRequiredMixin, generic.ListView):
model = Calculation
paginate_by = 10
template_name = 'calculations_user.html'
def get_queryset(self):
return Calculation.objects.filter(userid=self.request.user)
Upvotes: 1