example - Django Rest Framework: Acceda a los detalles de los elementos mediante slug en lugar de ID
django rest framework serializer (2)
¿Es posible usar la barra de un objeto (o cualquier otro campo) para acceder a los detalles de un artículo, en lugar de usar la ID?
Por ejemplo, si tengo un elemento con el slug "lorem" y el ID 1. Por defecto, la URL es http://localhost:9999/items/1/
. Quiero acceder a través de http://localhost:9999/items/lorem/
lugar.
La adición de lookup_field
en la clase Meta del serializador no hizo nada para cambiar la URL generada automáticamente ni me permitió acceder al elemento escribiendo manualmente el slug en lugar de la ID en la URL.
modelos.py
class Item(models.Model):
slug = models.CharField(max_length=100, unique=True)
title = models.CharField(max_length=100, blank=True, default='''')
# An arbitrary, user provided, URL
item_url = models.URLField(unique=True)
serializers.py
class ClassItemSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Item
fields = (''url'', ''slug'', ''title'', ''item_url'')
vistas.py
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
urls.py
router = DefaultRouter()
router.register(r''items'', views.ItemViewSet)
urlpatterns = [
url(r''^'', include(router.urls)),
]
JSON generado:
[
{
"url": "http://localhost:9999/items/1/",
"slug": "lorem",
"title": "Lorem",
"item_url": "http://example.com"
}
]
Debes establecer lookup_field
en tu serializador:
class ItemSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Item
fields = (''url'', ''slug'', ''title'', ''item_url'')
lookup_field = ''slug''
extra_kwargs = {
''url'': {''lookup_field'': ''slug''}
}
y en su opinión:
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
lookup_field = ''slug''
Obtuve este resultado:
~ curl http://127.0.0.1:8000/items/testslug/ | python -mjson.tool
{
"item_url": "https://example.com/",
"slug": "testslug",
"title": "Test Title",
"url": "http://127.0.0.1:8000/items/testslug/"
}
En algunos casos, es posible que desee tener tanto el valor pk
"nivel bajo" como la pk
más semántica. Me gusta tener ambas opciones personalmente y hacer esto configurando lookup_field
más adelante en el método as_view()
en mi urls.py
Nota: los siguientes valores predeterminados son
pk
con una búsqueda opcional deslug
. Para combinar esto con la respuesta anterior, cambiaría el campo delookup_field
continuación para que sea"pk"
lugar de"slug".
from django.conf.urls import *
from rest_framework.urlpatterns import format_suffix_patterns
from myobjects import views as myviews
# simplify the view definitions by splitting out the options
REQDICT = {
''get'': ''retrieve'',
''put'': ''update'',
''patch'': ''partial_update'',
''delete'': ''destroy''
}
# define the pk detail view
myobject_detail = myviews.MyObjectViewset.as_view(REQDICT)
# define the slug detail view
myobject_slug_detail = myviews.MyObjectViewset.as_view(REQDICT, lookup_field=''slug'')
urlpatterns = [
url(r"^myobjects/(?P<pk>/d*)/$",
myobject_detail,
name = ''myobject-detail''),
url(r"^myobjects/(?P<slug>[-/w]+)/$",
myobject_slug_detail,
name = ''myobject-slug-detail''),
]
urlpatterns = format_suffix_patterns(urlpatterns)
Esto también podría estar en tus
views.py
- mi preferencia es verlo al lado de la lista deurlpatterns
.