Django बाकी फ्रेमवर्क - "उपयोगकर्ता-विवरण" नाम का उपयोग करके हाइपरलिंक किए गए संबंध के लिए URL को हल नहीं कर सका


108

मैं Django रेस्ट फ्रेमवर्क में एक प्रोजेक्ट बना रहा हूं जहां उपयोगकर्ता अपने वाइन सेलर को देखने के लिए लॉगिन कर सकते हैं। मेरे ModelViewSets ठीक काम कर रहे थे और अचानक मुझे यह निराशाजनक त्रुटि मिली:

"उपयोगकर्ता-विवरण" नाम का उपयोग करके हाइपरलिंक किए गए संबंध के लिए URL को हल नहीं किया जा सका। आप अपने एपीआई में संबंधित मॉडल को शामिल करने में विफल हो सकते हैं, या lookup_fieldइस क्षेत्र पर विशेषता को गलत तरीके से कॉन्फ़िगर कर सकते हैं ।

ट्रेसबैक शो:

    [12/Dec/2013 18:35:29] "GET /bottles/ HTTP/1.1" 500 76677
Internal Server Error: /bottles/
Traceback (most recent call last):
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/viewsets.py", line 78, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 57, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/views.py", line 399, in dispatch
    response = self.handle_exception(exc)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/views.py", line 396, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/mixins.py", line 96, in list
    return Response(serializer.data)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/serializers.py", line 535, in data
    self._data = [self.to_native(item) for item in obj]
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/serializers.py", line 325, in to_native
    value = field.field_to_native(obj, field_name)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/relations.py", line 153, in field_to_native
    return self.to_native(value)
  File "/Users/bpipat/.virtualenvs/usertest2/lib/python2.7/site-packages/rest_framework/relations.py", line 452, in to_native
    raise Exception(msg % view_name)
Exception: Could not resolve URL for hyperlinked relationship using view 
name "user-detail". You may have failed to include the related model in 
your API, or incorrectly configured the `lookup_field` attribute on this 
field.

मेरे पास एक कस्टम ईमेल उपयोगकर्ता मॉडल और मॉडल मॉडल में बोतल मॉडल है:

class Bottle(models.Model):    
      wine = models.ForeignKey(Wine, null=False)
      user = models.ForeignKey(User, null=False, related_name='bottles')

मेरे धारावाहिक:

class BottleSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Bottle
        fields = ('url', 'wine', 'user')

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ('email', 'first_name', 'last_name', 'password', 'is_superuser')

मेरे विचार:

class BottleViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows bottles to be viewed or edited.
    """
    queryset = Bottle.objects.all()
    serializer_class = BottleSerializer

class UserViewSet(ListCreateAPIView):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

और अंत में यूआरएल:

router = routers.DefaultRouter()
router.register(r'bottles', views.BottleViewSet, base_name='bottles')

urlpatterns = patterns('',
    url(r'^', include(router.urls)),
    # ...

मेरे पास उपयोगकर्ता विवरण नहीं है और मैं नहीं देखता कि यह समस्या कहां से आ सकती है। कोई विचार?

धन्यवाद

जवाबों:


96

क्योंकि यह एक है HyperlinkedModelSerializerअपने serializer संबंधित के लिए URL का समाधान करने की कोशिश कर रहा है Userअपने पर Bottle
जैसा कि आपके पास उपयोगकर्ता विवरण नहीं है, यह ऐसा नहीं कर सकता। इसलिए अपवाद।

  1. क्या केवल UserViewSetराउटर के साथ पंजीकरण करने से आपकी समस्या हल नहीं होगी?
  2. आप URL को हल करने BottleSerializerके UserSerializerबजाय स्पष्ट रूप से उपयोग करने के लिए अपने उपयोगकर्ता क्षेत्र को परिभाषित कर सकते हैं । इसके लिए नेस्टेड ऑब्जेक्ट्स से निपटने के लिए सीरीकेयर डॉक्स देखें ।

1
बहुत धन्यवाद, मैंने अपने राउटर में UserViewSet टिप्पणी की थी, जिसने इसे हल किया!
bpipat

5
सूत्र ---- यह स्पष्ट रूप से करते हैं --- बहुत जादू करने के लिए बहुत समय खो दिया है।
andilabs 14

क्या आप कृपया बता सकते हैं कि मेरी परियोजना में क्या गलत है ?
JJD

@ बृजेशचौहान- धन्यवाद! अब तय हो गया।
कार्लटन गिब्सन

कारण यह काम नहीं कर रहा था क्योंकि django पैरामीटर उपयोगकर्ता के लिए आपके वर्तमान दृश्य में उपयोगकर्ता से संबंधित डेटा दिखाना चाहता था। आमतौर पर यह उपलब्ध मूल्यों की एक सूची तैयार करता है। चूंकि UserViewSet को परिभाषित नहीं किया गया था इसलिए यह वेबपेज को प्रस्तुत करने के लिए विवरण को खींचने में सक्षम नहीं था। UserViewSet को जोड़ना और डिफ़ॉल्ट राउटर के तहत पुन: व्यवस्थित करना सभी घटकों को रेंडर करने के लिए बात को पूरा करता है।
15

65

मैं इस त्रुटि के पार भी आया और इसे इस प्रकार हल किया:

कारण यह है कि मैं "** - विवरण" (view_name, उदा: उपयोगकर्ता-विस्तार) एक नाम स्थान देना भूल गया। इसलिए, Django रेस्ट फ्रेमवर्क को वह दृश्य नहीं मिला।

मेरे प्रोजेक्ट में एक ऐप है, मान लीजिए कि मेरा प्रोजेक्ट का नाम है myproject , और ऐप का नाम हैmyapp

दो urls.py फ़ाइल है, एक है myproject/urls.pyऔर दूसरी है myapp/urls.py। मैं एप्लिकेशन को एक नाम स्थान देता हूंmyproject/urls.py , जैसे:

url(r'', include(myapp.urls, namespace="myapp")),

मैंने बाकी ढांचे के राउटर को पंजीकृत किया myapp/urls.py , और फिर यह त्रुटि मिली।

मेरा समाधान स्पष्ट रूप से नाम स्थान के साथ url प्रदान करना था:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="myapp:user-detail")

    class Meta:
        model = User
        fields = ('url', 'username')

और इसने मेरी समस्या हल कर दी।


@ लोब्सन, यह एक आकर्षण की तरह काम करता है! धन्यवाद, आपने मेरी तरफ से घंटों की निराशा को हल किया।
lmiguelvargasf

इससे यह मेरे लिए भी काम कर गया। मेरी ओर से भी एक महत्वपूर्ण बिंदु रूट में आधार_नाम की सही वर्तनी था!
मैगी

1
यहाँ कुंजी है नामस्थान उपसर्ग काम करने से रिवर्स रोकता है .....
नाविक

मुझे इस तरह की समस्या थी और इस जवाब ने मेरी समस्या को 3 घंटे की खोज के बाद ठीक कर दिया! @ बवेंसन
व्हेल 52Hz

या आप extra_kwargs का उपयोग कर सकते हैं क्योंकि drf अनुशंसा करता है:extra_kwargs = {'url': {'view_name': 'myapp:user-detail'}}
क्रिसरोब

19

शायद किसी को इस पर एक नज़र हो सकता है: http://www.django-rest-framework.org/api-guide/routers/

यदि हाइपरलिंक किए गए अनुक्रमकों के साथ नाम स्थान का उपयोग कर रहे हैं, तो आपको यह भी सुनिश्चित करना होगा कि नामांकनों पर कोई भी view_name पैरामीटर सही ढंग से नाम स्थान को प्रतिबिंबित करता है। उदाहरण के लिए:

urlpatterns = [
    url(r'^forgot-password/$', ForgotPasswordFormView.as_view()),
    url(r'^api/', include(router.urls, namespace='api')),
]

आपको view_name='api:user-detail'उपयोगकर्ता विवरण दृश्य के लिए हाइपरलिंक किए गए अनुक्रमिक फ़ील्ड जैसे पैरामीटर को शामिल करना होगा ।

class UserSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="api:user-detail")

class Meta:
    model = User
    fields = ('url', 'username')

1
संक्षेप में, अपने एपीआई को नाम स्थान देने से शीर्षक में त्रुटि होती है, आप संभवतः इसे तब तक नहीं करना चाहते जब तक आप इसे कई स्थानों पर बदलना नहीं चाहते।
मार्क

मेरे लिए काम किया! मेरे प्रोजेक्ट urls.pyमें मेरा डबल नेस्टेड था newsite: (1) newsite/urls.py(django द्वारा बनाया गया) (2) polls/urls.py(3) polls/api/v1/urls.py ............ मुझे नेस्टेड नेम का उपयोग करके उल्लेख करना हैurl = serializers.HyperlinkedIdentityField(view_name="polls:polls_api:user-detail")
Grijesh Chauhan

12

इस त्रुटि का कारण बनने वाली एक और गलत गलती का आधार_नाम है जो अनावश्यक रूप से आपकी urls.py में परिभाषित की गई है। उदाहरण के लिए:

router.register(r'{pathname}', views.{ViewName}ViewSet, base_name='pathname')

यह ऊपर उल्लिखित त्रुटि का कारण होगा। उस आधार_नाम को वहां से हटाएं और काम करने वाले एपीआई पर वापस जाएं। नीचे दिया गया कोड त्रुटि को ठीक करेगा। हुर्रे!

router.register(r'{pathname}', views.{ViewName}ViewSet)

हालाँकि, आपने शायद मनमाने ढंग से आधार_नाम नहीं जोड़ा था, हो सकता है कि आपने ऐसा किया हो क्योंकि आपने व्यू के लिए एक कस्टम डिफ गेट_क्वेटसेट () को परिभाषित किया था और इसलिए Django यह कहता है कि आप base_name जोड़ते हैं। इस मामले में आपको स्पष्ट रूप से 'url' को एक प्रश्न के रूप में क्रमिक के लिए HyperlinkedIdentityField के रूप में परिभाषित करना होगा। ध्यान दें कि हम इस हाइपरलिंकड ईडेंटिटीफिल्ड को उस दृश्य के सीरियल में परिभाषित कर रहे हैं जो त्रुटि को फेंक रहा है। यदि मेरी त्रुटि "अध्ययन-विवरण" नाम का उपयोग करके हाइपरलिंक किए गए संबंध के लिए URL को हल नहीं कर सका, तो आप अपने एपीआई में संबंधित मॉडल को शामिल करने में विफल हो सकते हैं, या गलत तरीके से lookup_fieldइस क्षेत्र पर विशेषता को कॉन्फ़िगर कर सकते हैं । " मैं इसे निम्नलिखित कोड के साथ ठीक कर सकता हूं।

मेरा ModelViewSet (कस्टम get_queryset इसलिए मुझे पहली बार रूटर_रजिस्ट्री में आधार_नाम जोड़ना पड़ा):

class StudyViewSet(viewsets.ModelViewSet):
    serializer_class = StudySerializer

    '''custom get_queryset'''
    def get_queryset(self):
        queryset = Study.objects.all()
        return queryset

Urls.py में इस ModelViewSet के लिए मेरा राउटर पंजीकरण:

router.register(r'studies', views.StudyViewSet, base_name='studies')

और यहाँ क्या पैसा है! तब मैं इसे हल कर सकता था:

class StudySerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="studies-detail")
    class Meta:
        model = Study
        fields = ('url', 'name', 'active', 'created',
              'time_zone', 'user', 'surveys')

हां। आपको स्पष्ट रूप से इस हाइपरलिंकड ईडेंटिटीफिल्ड को काम करने के लिए स्वयं पर परिभाषित करना होगा। और आपको यह सुनिश्चित करने की आवश्यकता है कि view_nameहाइपरलिंक्डइंडेंटिटीफिल्ड पर परिभाषित वही है जैसा आपने base_nameurls.py में परिभाषित किया था कि इसके बाद एक '-detail' जोड़ा गया था।


2
इसने मेरे लिए काम किया, हालाँकि मुझे पूरा रास्ता लगाना पड़ा <app_name>:studies-detail। उदाहरण के लिए अगर मेरा ऐप कहा जाता है tanks, तो पूरा रास्ता होगा HyperlinkedIdentityField(view_name="tanks:studies-detail")। यह जानने के लिए कि मैंने django-exensions show_urls कमांड का उपयोग किया है , पूरा मार्ग और राउटर जो स्वचालित रूप से बना रहा था, उसे देखने के लिए।
dtasev

10

इस कोड को भी काम करना चाहिए।

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

  class Meta:
    model = Bottle
    fields = ('url', 'wine', 'user')

3
वर्थ नोटिंग जिसे UserSerializerलागू किया जाना चाहिए (यह आयात करने के लिए तैयार नहीं है), जैसा कि django-rest-framework.org/api-guide/serializers
Caumons

यह मेरे लिए काम करता है, लेकिन इसे काम करने के लिए मुझे रूटर.register (r'bottles ', views.BottleViewSet, base_name =' बोतल ') को router.register (r'bottles', views) .BottleViewSet में बदलना पड़ा। मुझे नहीं पता कि इस बदलाव की आवश्यकता क्यों थी।
मैनपिकिन

4

मैं अपने url में नाम स्थान जोड़ने के बाद इस त्रुटि में भाग गया

 url('api/v2/', include('api.urls', namespace='v2')),

और मेरे urls.py में app_name जोड़ रहा है

मैंने अपने प्रोजेक्ट की सेटिंग थ्रीडी में अपने बाकी फ्रेमवर्क एप के लिए नेमस्पेस पेसिविंग निर्दिष्ट करके इसे हल किया

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.NamespaceVersioning'}

3

आज, मुझे वही त्रुटि मिली और नीचे के परिवर्तनों ने मुझे बचाया।

परिवर्तन

class BottleSerializer(serializers.HyperlinkedModelSerializer):

सेवा:

 class BottleSerializer(serializers.ModelSerializer):

2

एक ही त्रुटि, लेकिन अलग कारण:

मैं एक कस्टम उपयोगकर्ता मॉडल को परिभाषित करता हूं, कुछ भी नया क्षेत्र नहीं:

from django.contrib.auth.models import (AbstractUser)
class CustomUser(AbstractUser):
    """
    custom user, reference below example
    https://github.com/jonathanchu/django-custom-user-example/blob/master/customuser/accounts/models.py

    # original User class has all I need
    # Just add __str__, not rewrite other field
    - id
    - username
    - password
    - email
    - is_active
    - date_joined
    - method, email_user
    """

    def __str__(self):
        return self.username

यह मेरा देखने का कार्य है:

from rest_framework import permissions
from rest_framework import viewsets
from .models import (CustomUser)
class UserViewSet(viewsets.ModelViewSet):
    permission_classes = (permissions.AllowAny,)
    serializer_class = UserSerializer

    def get_queryset(self):
        queryset = CustomUser.objects.filter(id=self.request.user.id)
        if self.request.user.is_superuser:
            queryset = CustomUser.objects.all()
        return queryset

चूंकि मैंने querysetसीधे अंदर नहीं दिया था UserViewSet, मुझे base_nameइस विचार को पंजीकृत करते समय सेट करना होगा। यह वह जगह है जहाँ urls.pyफ़ाइल के कारण मेरा त्रुटि संदेश :

from myapp.views import (UserViewSet)
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet, base_name='customuser')  # <--base_name needs to be 'customuser' instead of 'user'

आप एक की जरूरत है base_nameअपने मॉडल नाम के समान - customuser


पुरानी पोस्ट, लेकिन आपकी टिप्पणी "# <- base_name 'यूजर' के बजाय 'कस्टमर' होने की जरूरत है" जो मेरे दिन को बचाता है। धन्यवाद!
हन्नान सेसर

1

यदि आप GenericViewSet और ListModelMixin कक्षाएं बढ़ा रहे हैं , और सूची दृश्य में url फ़ील्ड जोड़ते समय एक ही त्रुटि है , तो ऐसा इसलिए है क्योंकि आप विवरण दृश्य को परिभाषित नहीं कर रहे हैं। सुनिश्चित करें कि आप RetrieveModelMixin मिश्रण का विस्तार कर रहे हैं :

class UserViewSet (mixins.ListModelMixin,
                   mixins.RetrieveModelMixin,
                   viewsets.GenericViewSet):

1

ऐसा प्रतीत होता है कि HyperlinkedModelSerializerएक रास्ता होने से सहमत नहीं हैं namespace। अपने आवेदन में मैंने दो बदलाव किए।

# rootapp/urls.py
urlpatterns = [
    # path('api/', include('izzi.api.urls', namespace='api'))
    path('api/', include('izzi.api.urls')) # removed namespace
]

आयातित url फ़ाइल में

# app/urls.py
app_name = 'api' // removed the app_name

उम्मीद है की यह मदद करेगा।


0

जब मैं DRF क्विकस्टार्ट गाइड http://www.django-rest-framework.org/tutorial/quickstart/ का अनुसरण कर रहा था, तब मैं उसी त्रुटि में भाग गया था और / उपयोगकर्ताओं को ब्राउज़ करने का प्रयास कर रहा था । मैंने समस्याओं के बिना कई बार यह सेटअप किया है।

मेरा समाधान कोड में नहीं, बल्कि डेटाबेस को बदलने में था।

जब मैंने स्थानीय डेटाबेस बनाया था, तो इससे पहले और अन्य लोगों के बीच का अंतर था।

इस बार मैंने अपना दौड़ा लिया

./manage.py migrate
./manage.py createsuperuser

दौड़ने के तुरंत बाद

virtualenv venv
. venv/bin/activate
pip install django
pip install djangorestframework

गाइड में सूचीबद्ध सटीक क्रम के बजाय।

मुझे संदेह है कि डीबी में कुछ ठीक से नहीं बनाया गया था। मुझे अपने देव डीबी की परवाह नहीं थी इसलिए मैंने इसे हटा दिया और दौड़ा./manage.py migrate एक बार फिर कमांड को , एक सुपर उपयोगकर्ता बनाया, / उपयोगकर्ताओं को ब्राउज किया और त्रुटि हो गई।

संचालन के क्रम के साथ कुछ समस्याग्रस्त था जिसमें मैंने डीआरएफ और डीबी को कॉन्फ़िगर किया था।

यदि आप साइक्लाइट का उपयोग कर रहे हैं और एक ताज़ा डीबी में परिवर्तन का परीक्षण करने में सक्षम हैं, तो इससे पहले कि आप अपने सभी कोड को विच्छेदित करने से पहले एक प्रयास के लायक हो।


0

बोतल = धारावाहिक

read_only आपको मॉडल के किसी अन्य दृश्य से लिंक किए बिना फ़ील्ड का प्रतिनिधित्व करने की अनुमति देता है।


0

मुझे DRF 3.7.7 पर वह त्रुटि मिली जब डेटाबेस में एक स्लग वैल्यू खाली थी ('' के बराबर)।


0

मैं इसी मुद्दे पर भागा और generics.RetrieveAPIViewअपने विचार के आधार वर्ग के रूप में इसे हल किया ।


0

मैं लगभग 2 घंटे के लिए इस त्रुटि में फंस गया था:

अनुचित तरीके से / api_users / उपयोगकर्ताओं / 1 / पर अनुचित तरीके से "उपयोगकर्ता-विवरण" नाम का उपयोग करके हाइपरलिंक किए गए संबंध के लिए URL को हल नहीं किया जा सका। आप अपने एपीआई में संबंधित मॉडल को शामिल करने में विफल हो सकते हैं, या lookup_fieldइस क्षेत्र पर विशेषता को गलत तरीके से कॉन्फ़िगर कर सकते हैं ।

जब मुझे आखिर समाधान मिल जाता है, लेकिन मुझे समझ नहीं आता है, तो मेरा कोड है:

#models.py
class Users(models.Model):
    id          = models.AutoField(primary_key=True)
    name        = models.CharField(max_length=50, blank=False, null=False)
    email       = models.EmailField(null=False, blank=False) 
    class Meta:
        verbose_name = "Usuario"
        verbose_name_plural = "Usuarios"

    def __str__(self):
        return str(self.name)


#serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Users
        fields = (
            'id',
            'url',
            'name',        
            'email',       
            'description', 
            'active',      
            'age',         
            'some_date',   
            'timestamp',
            )
#views.py
class UserViewSet(viewsets.ModelViewSet):
    queryset = Users.objects.all()
    serializer_class = UserSerializer

#urls_api.py
router = routers.DefaultRouter()
router.register(r'users',UserViewSet, base_name='users')

urlpatterns = [ 
        url(r'^', include(router.urls)),
]

लेकिन मेरे मुख्य URL में यह था:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    #api users
    url(r'^api_users/', include('usersApi.users_urls', namespace='api')),

]

इसलिए अंत में मैं नाम स्थान को मिटाने वाली समस्या को हल करता हूं:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    #api users
    url(r'^api_users/', include('usersApi.users_urls')),

]

और मैं अंत में अपनी समस्या को हल करता हूं, इसलिए कोई भी मुझे बता सकता है कि क्यों, सबसे अच्छा।


0

यदि आप अपने अनुक्रमक से फ़ील्ड 'id' और 'url' छोड़ते हैं तो आपको कोई समस्या नहीं होगी। आप json ऑब्जेक्ट एनीवेज़ में दिए गए आईडी का उपयोग करके पदों तक पहुँच सकते हैं, जिससे यह आपके दृश्यपटल को लागू करना और भी आसान हो जाता है।


0

मुझे भी यही समस्या थी, मुझे लगता है कि आपको अपनी जाँच करनी चाहिए

get_absolute_url

ऑब्जेक्ट मॉडल की विधि इनपुट मूल्य (** kwargs) शीर्षक। और लुकअप_फ़ील्ड में सटीक फ़ील्ड नाम का उपयोग करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.