change router lookup field or lookup regex in detail_route

1,913 views
Skip to first unread message

Mark Mikofski

unread,
Jul 25, 2017, 6:56:25 PM7/25/17
to Django REST framework
I want to add a detail view in addition to the standard router views, that uses a UUID field instead of pk

I have a viewset for standard crud operations for a django model

eg: the model is a list of weather sites

class Weather(models.Model):
  name
= models.CharField(max_length=100)
  latitude
= models.FloatField()
  longitude = models.FloatField()
  ambient_temp
= models.FloatField()
  shared_key
= models.UUIDField()
  owner
=models.ForeignKey(User)

so the views and serializers are very basic

class WeatherViewSet(viewsets.ModelViewSet):
  queryset
= Weather.objects.all()

class WeatherSerializer(serializers.ModelSerializer):
 
class Meta:
    model
= Weather
    fields
= '__all__'

Now I just want to add a detail view that returns the `Weather.objects.get(shared_key=<key>)` instead of by pk

can I just add a `@detail_route` to a method in the view?

class WeatherViewSet(viewsets.ModelViewSet):
  queryset
= Weather.objects.all()

 
@detail_route(lookup_field='shared_key',lookup_regex='[0-9a-f]{32}'
 
def get_weather_by_key(self, request, key=None):
   
return Response(Weather.objects.get(shared_key=key)

thanks,
Mark

Alex Pol

unread,
Aug 4, 2017, 4:48:13 AM8/4/17
to Django REST framework
Yes, you can, but don't forget to name kwarg in function same as lookup field

@detail_route(lookup_field='shared_key',lookup_regex='[0-9a-f]{32}')
def get_weather_by_key(self, request, 
shared_key=None):
    
return Response(Weather.objects.get(shared_key=
shared_key)

Mark Mikofski

unread,
Aug 4, 2017, 7:27:35 PM8/4/17
to Django REST framework
Hi Alex,
Got it - make sure the keyword args are exactly the same, so use shared_key for both the decorator and the underlying function.
Thanks!

Mark Mikofski

unread,
Aug 5, 2017, 4:21:08 AM8/5/17
to Django REST framework
It didn't work exactly the way I was hoping. I can't just add `lookup_value_regex` to the `@detail_route`, it needs to be part of the viewset.

MyViewSet(viewsets.ViewSet):
    lookup_field = 'blah'
    lookup_value_regex = 'pattern'

if I don't have these in my viewset then I get an error:

>TypeError:MyViewSet() received an invalid keyword 'lookup_value_regex'
>   Fiel "~/myproject/myproject/myapp/urls.py", line 92, in <module>
>     url(r'^', include(router.urls)),
>   File "/home/applmgr/.local/lib/python2.7/site-packages/rest_framework/routers.py", line 82, in urls
>     self._urls = self.get_urls()
>   File "~/.local/lib/python2.7/site-packages/rest_framework/routers.py", line 373, in get_urls
>     urls = super(DefaultRouter, self).get_urls()
>   File "~/.local/lib/python2.7/site-packages/rest_framework/routers.py", line 271, in get_urls
>     view = viewset.as_view(mapping, **route.initkwargs)
>   File "~/.local/lib/python2.7/site-packages/rest_framework/viewsets.py", line 67, in as_view
>     cls.__name__, key))

but what I want is an _additional_ endpoint so I can lookup records by either pk _or_ uuid.
Reply all
Reply to author
Forward
0 new messages