source

Django Rest Framework - 보기 이름 "user-detail"을 사용하여 하이퍼링크된 관계의 URL을 확인할 수 없습니다.

lovecheck 2023. 7. 16. 13:41
반응형

Django Rest Framework - 보기 이름 "user-detail"을 사용하여 하이퍼링크된 관계의 URL을 확인할 수 없습니다.

저는 장고레스트 프레임워크에서 사용자가 로그인하여 와인 저장실을 볼 수 있는 프로젝트를 구축하고 있습니다.내 모델 보기세트가 제대로 작동했는데 갑자기 다음과 같은 답답한 오류가 발생했습니다.

보기 이름 "user-detail"을 사용하여 하이퍼링크 관계의 URL을 확인할 수 없습니다. API를 했을 수 .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.

사용자 지정 이메일 사용자 모델이 있으며 models.py 의 병 모델은 다음과 같습니다.

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

그리고 마지막으로 URL:

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

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

사용자 세부 정보 보기가 없고 이 문제의 원인을 알 수 없습니다.아이디어 있어요?

감사해요.

왜냐하면 그것은.HyperlinkedModelSerializer.User의 신의에Bottle.
사용자 세부 정보 보기가 없으므로 이 작업을 수행할 수 없습니다.따라서 예외입니다.

  1. 등록만 하지는 않을 것입니다.UserViewSet라우터로 당신의 문제를 해결합니까?
  2. 는 에서사정있수다에서 할 수 .BottleSerializer명적으사위해기용하로를 명시적으로 UserSerializerURL을 해결하려고 하는 것보다.에 대한 자세한 내용은 중첩된 개체 처리에 대한 직렬화 도구 설명서를 참조하십시오.

저도 이 오류를 발견하고 다음과 같이 해결했습니다.

그 이유는 "**-detail"(view_name, 예: user-detail)에 네임스페이스를 지정하는 것을 잊었기 때문입니다.그래서 장고 레스트 프레임워크는 그 뷰를 찾을 수 없었습니다.

내 프로젝트에 앱이 하나 있는데, 내 프로젝트 이름이myproject 앱 은 고앱이름은그리은이▁name입니다.myapp.

개의.py 파일이 , 는 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')

그리고 그것은 제 문제를 해결했습니다.

아마도 누군가 이것을 볼 수 있을 것입니다: 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'사용자 세부 정보 보기에 하이퍼링크된 serializer 필드입니다.

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

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

이 오류를 발생시키는 또 다른 심각한 실수는 urls.py 에 base_name이 불필요하게 정의되어 있다는 것입니다.예:

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

이로 인해 위에서 언급한 오류가 발생합니다.base_name을(를) 제거하고 작동하는 API로 돌아갑니다.아래 코드는 오류를 수정할 수 있습니다.만세!

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

그러나 base_name을 임의로 추가한 것이 아니라 View에 대한 사용자 정의 defet_queryset()을 정의했기 때문에 그렇게 했을 수 있습니다. 따라서 Django는 base_name을 추가해야 합니다.이 경우 'url'을 해당 직렬화 프로그램의 하이퍼링크된 ID 필드로 명시적으로 정의해야 합니다.오류를 발생시키는 뷰의 직렬화 프로그램에서 이 하이퍼링크된 ID 필드를 정의하고 있습니다. 제 가 "name "study-detail"을 할 수 ."였다면 API를 했을 수 .lookup_field i성."속이▁"의▁code▁following▁.' 다음 코드로 .저는 다음 코드로 이것을 고칠 수 있습니다.

My ModelViewSet(사용자 지정 get_queryset 때문에 처음에 base_name을 router.register()에 추가해야 했습니다):

class StudyViewSet(viewsets.ModelViewSet):
    serializer_class = StudySerializer

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

이 모델 뷰에 대한 라우터 등록URL로 설정합니다.py:

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')

이를 그 합니다. 이 하 링 ID 정 퍼 야 작 해 니 합그리고 당신은 확실히 해야 합니다.view_name은 HyperlinkedIdentityField에 된 내용과 .base_name뒤에 '-'자가 추가된 urls.py .

이 코드도 작동해야 합니다.

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

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

오늘도 같은 오류가 발생했고 아래의 변경 사항이 나를 구해줍니다.

바꾸다

class BottleSerializer(serializers.HyperlinkedModelSerializer):

대상:

 class BottleSerializer(serializers.ModelSerializer):

URL에 네임스페이스를 추가한 후 이 오류가 발생했습니다.

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

그리고 내 urls.py 에 app_name을 추가합니다.

프로젝트의 settings.py 에서 나머지 프레임워크 API에 대해 네임스페이스 버전을 지정하여 이 문제를 해결했습니다.

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

TL;DR: 라우터 기본 이름에서 후행 's'를 제거하는 것만큼 간단할 수 있습니다.직렬화기에서 URL 필드를 정의할 필요가 없습니다.

원본 포스터의 경우 상단 답변에 제시된 대로 UserViewSet 등록만으로 문제가 해결되었습니다.

그러나 ViewSet을 모두 등록했는데도 다른 사용자가 이 문제를 겪고 있다면 무엇이 잘못되고 있는지 파악한 것 같습니다. 그리고 여기 있는 다른 사용자보다 더 깨끗한 솔루션을 찾았습니다.

제 경우 사용자 지정 get_queryset() 함수를 사용하여 ViewSet을 생성하려고 시도한 후 이 문제가 발생했습니다.ViewSet의 queryset 필드를 사용자 지정 get_queryset() 함수로 바꾸었을 때 다음 오류가 발생했습니다.

AssertionError: 'basename' 인수가 지정되지 않았으며 '.queryset' 특성이 없기 때문에 뷰 세트에서 이름을 자동으로 확인할 수 없습니다.

그래서 당연히 저는 urls.py 에 가서 다음과 같은 기본 이름을 포함하도록 등록을 수정했습니다.

router.register(r'messages', MessageViewSet, basename='messages')

하지만 그 후 저는 다음과 같은 오류를 겪었습니다(원래 게시물에서 볼 수 있음).

보기 이름 "message-detail"을 사용하여 하이퍼링크 관계의 URL을 확인할 수 없습니다.API에 관련 모델을 포함하지 못했거나 이 필드에서 'lookup_field' 특성을 잘못 구성했을 수 있습니다.

라우터에서 DRF 문서를 읽은 후 라우터가 자동으로 두 개의 URL 패턴을 생성한다는 것을 알게 되었습니다. 이 패턴은 다음과 같습니다.

  1. 'basname-list'
  2. 'basname-interval'

기본 이름='syslog'(마지막에 's' 참고)를 설정했기 때문에 URL 패턴의 이름은 다음과 같습니다.

  1. '선택 목록'
  2. '1989-1989'

DRF가 'message-detail'이라는 URL 패턴을 찾고 있었기 때문에(여기에는 's'가 없음을 참고하십시오), 단순히기본 이름에서 뒤에 오는 's'제거하면 다음과 같이 이 문제를 해결할 수 있다는 것을 깨달았습니다.

router.register(r'messages', MessageViewSet, basename='message')

최종 serializer 및 ViewSet 구현은 이렇게 간단했습니다!

class MessageSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Message
        fields = ['url', 'message', 'timestamp', 'sender', ...]

class MessageViewSet(viewsets.ModelViewSet):
    serializer_class = MessageSerializer

    def get_queryset(self):
        return Message.objects.filter(...)

는 것 같습니다.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

이게 도움이 되길 바랍니다.

오류는 같지만 이유는 다릅니다.

사용자 지정 사용자 모델을 정의합니다. 새 필드는 없습니다.

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

내가주않때았문에기지때문▁i에'▁givet▁since▁didn기았내.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.

일반 보기를 확장하는 경우클래스에서 모델 믹스를 설정하고 목록 보기에 URL 필드를 추가할 때 동일한 오류가 발생합니다. 이는 세부 보기를 정의하지 않기 때문입니다.RetrieveModelMixin 믹스를 다음에서 확장해야 합니다.

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

3에서는 조금늦만장지 3서는에상이.include하지 namespaceapp_name에서 "" " " " " 를 하는 중입니다.include는 그 .

if namespaces and not app_name:
    ....

선택되어 있습니다.그리고 여전히 소스 코드에서 app_name은 다음과 같습니다.

urlconf_module, app_name = arg

arg의 첫 입니다.include이것은 우리에게, 우리의include는 " " "로 정의되어야 합니다.

include((app.urls, app_name), namespace='...')

프로젝트가 있다고 가정합니다.myproject 그고앱 도 있습니다.myapp그런 다음 주소를 설정하려고 합니다.와 같이 .

나의 앱.앱

router.register('address', exampleviewset, basename='address')

나의 프로젝트.

path('api/v1/', include(('myapp.urls', 'myapp'), namespace='myapp')),

serializers.py

class AddressSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="myapp:address-detail")
    class Meta:
        model = Address
        fields = ('url',...)

보아하니, 우리는 사용할 수 없습니다.fields='__all__'우리는 포함해야 합니다.url필요한 나머지 필드를 명시적으로 나열합니다.

DRF Quickstart Guide http://www.django-rest-framework.org/tutorial/quickstart/ 을 팔로우하고 /users를 검색하는 동안 동일한 오류가 발생했습니다.나는 이전에도 이 설정을 여러 번 문제없이 수행했습니다.

제 해결책은 코드가 아니라 데이터베이스를 교체하는 것이었습니다.

이 설치와 이전 설치의 차이점은 로컬 데이터베이스를 만들 때입니다.

이번엔 내가 실행했습니다.

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

달리기 직후에

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

가이드에 나열된 정확한 순서 대신.

DB에 무언가가 제대로 만들어지지 않은 것으로 의심했습니다.나는 내 devdb를 신경쓰지 않아서 삭제하고 실행했습니다../manage.py migrate명령을 다시 한 번 실행하고, 슈퍼 사용자를 생성하고, /users를 검색하고, 오류가 사라졌습니다.

DRF와 DB를 구성하는 작업 순서에 문제가 있었습니다.

만약 당신이 sqlite를 사용하고 있고 새로운 DB로 변경하는 것을 테스트할 수 있다면, 당신의 모든 코드를 해부하기 전에 시도해 볼 가치가 있습니다.

병 = 직렬화기.기본 키 관련 필드(read_only=True)

read_only를 사용하면 모델의 다른 뷰에 연결하지 않고도 필드를 나타낼 수 있습니다.

데이터베이스에서 슬러그 값이 비어 있을 때(''와 동일) DRF 3.7.7에서 오류가 발생했습니다.

나는 이 같은 문제에 부딪혔고 추가하여 해결했습니다.generics.RetrieveAPIView내 견해에 대한 기본 클래스로.

저는 거의 2시간 동안 이 오류에 갇혀 있었습니다.

/ 이름 api_users/users/1/ ""/ "users-detail"을 된 관계의 URL을 확인할 수 없습니다. API를 했을 수 .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')),

]

그리고 저는 마침내 제 문제를 해결했습니다. 그래서 누구나 그 이유를 알 수 있습니다. 최선을 다하죠.

serializer에서 'id'와 'url' 필드를 생략해도 문제가 없습니다.어차피 json 객체에 반환된 id를 사용하여 게시물에 액세스할 수 있기 때문에 프론트엔드 구현이 훨씬 쉬워집니다.

저도 같은 문제가 있었습니다. 당신이 확인해야 할 것 같습니다.

get_absolute_url

개체 모델의 메서드 입력 값(**kwargs) 제목입니다.lookup_field에서 정확한 필드 이름을 사용합니다.

주의할 점은 만약 당신이 다음을 만든다면.action와 함께detail=False(이합니다. (typo?)로 그러면 이 오류가 발생합니다. 다음으로 대체합니다.detail=True:

@action(detail=True)
...

모든 것을 즉시 사용할 수 있도록 유지하고 싶어서 사용자 직렬화 도구를 추가했습니다.

class UserSerializer(serializers.HyperlinkedModelSerializer):

class Meta:
    model = User
    fields = ['id', 'username']

보기 집합:

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

URL에 추가되었습니다.

router.register(r'users', UserViewSet)

DRF 문서에서:

drf 문서 노트 원본

참고: 하이퍼링크된 직렬화 프로그램에서 네임스페이스를 사용하는 경우 직렬화 프로그램의 view_name 매개 변수가 네임스페이스를 올바르게 반영하는지 확인해야 합니다.위의 예에서는 사용자 세부 정보 보기에 하이퍼링크된 직렬화 도구 필드에 view_name='app_name:user-properties'와 같은 매개 변수를 포함해야 합니다.

자동 view_name 생성은 %(model_name)-detail과 같은 패턴을 사용합니다.모델 이름이 실제로 충돌하지 않는 한 하이퍼링크된 직렬화 프로그램을 사용할 때 장고 REST Framework 보기의 이름 간격을 지정하지 않는 것이 좋습니다.

해결책

view_name 설정 예제

from rest_framework import serializers
from myapp.models import Post
from django.contrib.auth.models import User


class PostSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(view_name="api:post-detail")
    author = serializers.HyperlinkedRelatedField(view_name="api:user-detail", read_only=True)
    viewers = serializers.HyperlinkedRelatedField(view_name="api:user-detail", read_only=True, many=True)

    class Meta:
        model = Post
        fields = ('id', 'title', 'url', 'author', 'viewers')


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = "__all__"

언급URL : https://stackoverflow.com/questions/20550598/django-rest-framework-could-not-resolve-url-for-hyperlinked-relationship-using

반응형