5

I've been trying to pass a UUID4 id into the url for a specific detail page.

After browsing Stackoverflow and other sites, here's what I've tried so far:

  1. Passing the url path as path('car/<uuid:id>/', views.CarDetailView.as_view(), name='car-detail'),

But this raises the error: Generic detail view CarDetailView must be called with either an object pk or a slug in the URLconf..

Since the uuid field is composed of both letters and numbers, I can't use an int.

  1. So I used this:

path(r"^(?P<car_model>\w+)/$", views.CarDetailView.as_view(), name='car-detail'),

which returns the messy and broken url: showroom/%5E(%3FP09c32f72-5863-49fa-a42a-1d0fed274c4e%5Cw+)/$

  1. Then I tried reverting to the original, but using a def_object method in the View class.
def get_object(self):
    object = get_object_or_404(CarInstance,title=self.kwargs['car_model'])
    return object

But this returns the error: "KeyError at /showroom/car/09c32f72-5863-49fa-a42a-1d0fed274c4e/ 'car_model'"

models.py

class CarInstance(models.Model):
    manufacturer = models.ForeignKey('Manufacturer', on_delete=models.SET_NULL, null=True)
    car_model = models.CharField('Model', max_length=50, null=True)

views.py

class CarDetailView(generic.DetailView):
    model = CarInstance
    template_name = 'car_detail'

    def get_queryset(self):
         return CarInstance.objects.all()

    def get_object(self):
           object = get_object_or_404(CarInstance,title=self.kwargs['car_model'])
           return object

    def get_absolute_url(self):
            return reverse('showroom:car-detail', args=[str(self.pk)])

The urls should be be formatted as showroom/car/09c32f72-5863-49fa-a42a-1d0fed274c4e/, which brings up the detail view for the specific object.

Any ideas?

Update

According to the answer below, I changed the get_object override to

    slug_field = 'title'
    slug_url_kwarg = 'car_detail'

But I'm still getting the same urlconf must be called with slug or int error. Should I define the slugh in the models?

Update 2

I've changed the urlconf, but it's raising the same error. Here's the full traceback

Environment:


Request Method: GET
Request URL: http://localhost:8000/showroom/car/09c32f72-5863-49fa-a42a-1d0fed274c4e/

Django Version: 2.2.5
Python Version: 3.7.4
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'showroom']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "C:\Users\USER\Envs\torque\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\USER\Envs\torque\lib\site-packages\django\core\handlers\base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\USER\Envs\torque\lib\site-packages\django\core\handlers\base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\USER\Envs\torque\lib\site-packages\django\views\generic\base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "C:\Users\USER\Envs\torque\lib\site-packages\django\views\generic\base.py" in dispatch
  97.         return handler(request, *args, **kwargs)

File "C:\Users\USER\Envs\torque\lib\site-packages\django\views\generic\detail.py" in get
  106.         self.object = self.get_object()

File "C:\Users\USER\Envs\torque\lib\site-packages\django\views\generic\detail.py" in get_object
  47.                 "pk or a slug in the URLconf." % self.__class__.__name__

Exception Type: AttributeError at /showroom/car/09c32f72-5863-49fa-a42a-1d0fed274c4e/
Exception Value: Generic detail view CarDetailView must be called with either an object pk or a slug in the URLconf.

** Another update **

Thanks to help from @ruddra, I changed the path to match the slug_url_kwarg = 'car_detail' It looks like this now:

path('car/<slug:car_detail>/', views.CarDetailView.as_view(), name='car-detail')

However, now the page raises a 404 error.

Page not found (404)
Request Method: GET
Request URL:    http://localhost:8000/showroom/car/09c32f72-5863-49fa-a42a-1d0fed274c4e/
Raised by:  showroom.views.CarDetailView
No car instance found matching the query

3 Answers 3

6

You don't need to override get_object() method. You can simply use slug_url_kwarg and slug_field. Like this:

class CarDetailView(generic.DetailView):
    model = CarInstance
    template_name = 'car_detail'
    slug_field = 'title'
    slug_url_kwarg = 'car_model'

More information can be found in get_object() documentation.

Sign up to request clarification or add additional context in comments.

12 Comments

Thanks for the clarification. I'm still getting the "Generic detail view CarDetailView must be called with either an object pk or a slug in the URLconf." though.
Can you please try with path('car/<uuid:car_model>/', views.CarDetailView.as_view(), name='car-detail')?
@Rene from your implementation, slug_url_kwarg is car_detail, so change the url to path('car/<uuid:car_detail>/', views.CarDetailView.as_view(), name='car-detail')
Means it did not find any Car instance for the UUID you have provided. Please check the DB or from django shell or admin site if you have an instance with that uuid.
I'll open a new question since the original issue was addressed.
|
2

Although this is too late.However, someone could find it helpful.You can modify your modules as below:

Your models.py:

import uuid as uuid_lib
class CarInstance(models.Model):
    manufacturer = models.ForeignKey('Manufacturer', on_delete=models.SET_NULL, null=True)
    car_model = models.CharField('Model', max_length=50, null=True)
    uuid = models.UUIDField(
        db_index=True,
        default=uuid_lib.uuid4,
        editable=False, 
        unique=True,)

urls.py:

path('car/<uuid:uuid>/', views.CarDetailView.as_view(), name='car-detail'),

Lastly your views.py:

class CarDetailView(generic.DetailView):
    model = CarInstance
    template_name = 'car_detail'
    slug_field = 'uuid'
    slug_url_kwarg = 'uuid'

Comments

0
  1. Create get_absolute_url() in models.py:
def get_absolute_url(self):
    return reverse('car-detail', args=[str(self.<yourUUIDFieldName>)]) # self.car_model
  1. Set URL in urls.py:
urlpatterns = [
    path('car/<uuid:yourUUIDFieldName>/', # 'car:<uuid:car_model'>
    views.CarDetailView.as_view(), name='car-detail'),
]
  1. Try to change the views:
class CarDetailView(DetailView):
    model = CarInstance
    slug_field = '<uuid:yourUUIDFieldName>' # -> 'car_model'
    slug_url_kwarg = '<uuid:yourUUIDFieldName>' # -> 'car_model'
    template_name = 'car_detail.html'
  1. In addition try this if you like:
import uuid
car_model = models.UUIDField(default=uuid.uuid4, unique=True)

Replace yourUUIDFieldName with car_model check if this works, in my way, i have no idea, i'm just a beginner like others, hope u get something out of it

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.