Ryan
Ryan

Reputation: 147

Attribute Error: Generic Detail View must be called with either an object pk or a slug in the URLconf in tests

I've spent a lot of time today reviewing other posts that reference this issue both here and throughout Google. I cannot, however, find a solution when this occurs in a test. I am using pytest in my project and get this error on one of my detail views only when testing the view. The view itself works on my actual site. Here's my code:

views.py

class CarrierDetailView(LoginRequiredMixin, DetailView):
    model = Carrier
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        quotes = self.object.quotes.all()
        context['quotes'] = quotes
        return context

models.py

class Carrier(models.Model):
    TYPE_CHOICES = [
        ('WYO', 'WYO'),
        ('PRIVATE', 'Private')
    ]
    carrier_name = models.CharField(max_length=50)
    carrier_type = models.CharField(max_length=7, choices=TYPE_CHOICES)

    def __str__(self):
        return self.carrier_name

urls.py

    path('carrier/<int:pk>/', views.CarrierDetailView.as_view(), name='carrier-detail'),

and test_views.py

class CarrierDetailViewTest(TestCase):
    def test_carrier_detail_view(self):
        self.factory = RequestFactory()
        self.carrier = models.Carrier.objects.create(carrier_name='NatGen', carrier_type='WYO', id=2)
        path = reverse('quote-checklist:carrier-detail', kwargs={'pk':2})
        request = RequestFactory().get(path)
        request.user = User.objects.create_user(username='ryan', email='[email protected]', password='password')
        response = views.CarrierDetailView.as_view()(request, kwargs={'pk':2})
        assert response.status_code == 200

    def test_carrier_detail_template(self):
        assert('carrier_detail.html')

Please note in the tests I've received this error both with the kwargs in the response/path and without. I've also successfully tested the url for this view using the following test code:

    def test_carrier_detail_view_url(self):
        path = reverse('quote-checklist:carrier-detail', kwargs={'pk':1})
        assert resolve(path).view_name == 'quote-checklist:carrier-detail'

I appreciate in advance any insight others may have to offer.

Upvotes: 2

Views: 2071

Answers (2)

Ryan
Ryan

Reputation: 147

The answer turned out to be bdbd's suggestion. I changed my response to

response = views.CarrierDetailView.as_view()(request, **{'pk':2})

Thank you for the help!

Upvotes: 4

Ashin Shakya
Ashin Shakya

Reputation: 776

Try changing quotes = self.object.quotes.all() to quotes = self.get_object().quotes.all()

Upvotes: 0

Related Questions