web-dev-qa-db-fra.com

De quel paramètre base_name ai-je besoin dans mon itinéraire pour que cette API Django fonctionne?

Je crée une application Django qui expose une API REST par laquelle les utilisateurs peuvent interroger les modèles de mon application. Je suis les instructions ici .

Mon itinéraire ressemble à ceci dans url.py de myApp:

from rest_framework import routers
router = routers.DefaultRouter()    router.register(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsViewSet)
url(r'^api/', include(router.urls)),

Mon modèle ressemble à ceci:

class MyObject(models.Model):
    name = models.TextField()

Mon sérialiseur ressemble à ceci:

class MyObjectSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyObject
    fields = ('id', 'name',)

Mon ensemble de vues ressemble à ceci:

class MyObjectsViewSet(viewsets.ViewSet):

    def retrieve(self,request,pk=None):
        queryset = MyObjects.objects.get(pk=pk).customMyObjectList()

        if not queryset:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        else:
            serializer = MyObjectSerializer(queryset)
            return Response(serializer.data,status=status.HTTP_200_OK)

Lorsque j'appuie sur/api/myObjects/60/j'obtiens l'erreur suivante:

base_name argument non spécifié, et n'a pas pu déterminer automatiquement le nom à partir de l'ensemble de vues, car il n'a pas de .model ou .queryset attribut.

Je comprends de ici que j'ai besoin d'un paramètre base_name sur mon itinéraire. Mais d'après les documents, il n'est pas clair pour moi quelle devrait être la valeur de ce paramètre base_name. Quelqu'un peut-il me dire à quoi devrait ressembler l'itinéraire avec le nom_base?

30
Saqib Ali

Essayez de le faire dans votre urls.py. Le troisième paramètre "Personne" peut être tout ce que vous voulez.

router.register(r'person/food', views.PersonViewSet, 'Person')
43
Eric Lee

Vous avez peut-être juste besoin de définir le base_name paramètre pour votre routeur avec le nom de l'objet: MyObject, dans votre cas.

router.register(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsViewSet, base_name="MyObject")

http://www.Django-rest-framework.org/api-guide/routers/#Usage

13
Hugo Hernani

Permettez-moi d'expliquer pourquoi nous avons besoin d'un base_name en premier lieu, puis passons à la valeur possible de base_name.

Si vous avez déjà utilisé les Django urls sans rest-framework (DRF) auparavant, vous l'auriez spécifié comme ceci:

urlpatterns = [
    url(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsListView.as_view(), name='myobject-list'),
    url(r'myObjects/(?P<id>\d+)/?$', views.MyObjectsDetailView.as_view(), name='myobject-detail'),
]

Ici, si vous voyez, il y a un paramètre nom qui identifiait l'url dans l'espace de noms actuel (qui est l'application).

C'est exactement ce que Django-rest-framework essaie de faire automatiquement, car drf sait si la vue est liste ou détail (à cause de l'ensemble de vues ). il suffit d'ajouter quelques préfixe pour différencier les URL. C'est le but de nom_base (préfixe).

Dans la plupart des scénarios, vous pouvez donner rl ou nom de la ressource comme nom_base. Dans votre cas, base_name = myobject. DRF générera nom_base + type_vue comme paramètre nom comme myobject_list & myobject_detail.

Note: Habituellement, nom_base sera automatiquement obtenu à partir de queryset = champ (de la vue), car il est le même pour tous les types de vues d'un ensemble de vues. Mais si vous spécifiez la méthode get_queryset au lieu de queryset, cela signifie probablement que vous avez un ensemble de requêtes différent pour différents types de vue (comme la liste, les détails). Ainsi, DRF vous demandera de spécifier un base_name commun pour tous les types de vue pour une ressource.

9
Sriram

Une solution alternative pourrait être d'utiliser un ModelViewSet qui dérivera automatiquement le nom de base du modèle.

Assurez-vous simplement et dites-lui quel modèle utiliser:

Étant donné que ModelViewSet étend GenericAPIView, vous devrez normalement fournir au moins les attributs queryset et serializer_class, ou le raccourci d'attribut de modèle.

3
GreenGuerilla

mentionnez simplement ceci,

queryset = MyObjects.objects.all()

comme ça,

class MyObjectsViewSet(viewsets.ViewSet):
    queryset = MyObjects.objects.all()

dans votre Viewset correspondant dans views.py au lieu de mentionner sous

def récupérer () ...

ça a marché pour moi :)

2
Mohideen bin Mohammed

this est une réponse utile, lisez les détails.

tl; dr

Il est utilisé comme nom de base des modèles d'URL générés (par exemple, `` myobject-detail '' ou `` myobject-list '').

2
ingaham