Django Rest Framework-ビュー名「user-detail」を使用してハイパーリンク関係のURLを解決できませんでした


108

私はDjango Rest Frameworkでプロジェクトを構築しています。このプロジェクトでは、ユーザーはログインしてワインセラーを表示できます。私のModelViewSetsは問題なく動作していましたが、突然、このイライラするエラーが発生しました。

ビュー名「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)),
    # ...

ユーザーの詳細ビューがなく、この問題の原因がどこにあるのかわかりません。何か案は?

ありがとう

回答:


96

それはHyperlinkedModelSerializerあなたのシリアライザーがUserあなたの上の関連のURLを解決しようとしているからBottleです。
ユーザーの詳細ビューがないため、これを行うことはできません。したがって例外です。

  1. UserViewSetルーターに登録するだけで問題が解決しませんか?
  2. のユーザーフィールドを定義して、URLを解決するのではなく、BottleSerializer明示的にを使用することができUserSerializerます。そのためのネストされたオブジェクトの処理に関するシリアライザのドキュメントを参照してください。

1
感謝します。ルーターのUserViewSetをコメントアウトして、解決しました。
bpipat 2013

5
THATS THE POINT ----明示的に行う---多くの魔法にとって、多くの時間を失うことになります。
アンディラブス2014

私のプロジェクトで間違って構成されているものを指摘していただけますか?
JJD 2015年

@GrijeshChauhan —ありがとう!修正されました。
カールトンギブソン

これが機能しなかった理由は、djangoがパラメーターUserの現在のビューにUserからの関連データを表示したかったためです。通常、使用可能な値のリストを取得します。UserViewSetが定義されていなかったため、詳細をプルしてWebページをレンダリングできませんでした。デフォルトルーターの下にUserViewSetとregiseteringを追加すると、すべてのコンポーネントのレンダリングが完了します。
Doogle

65

私もこのエラーに遭遇し、次のように解決しました:

その理由は、「**-detail」(view_name、例:user-detail)に名前空間を指定するのを忘れていたためです。そのため、Django Rest Frameworkはそのビューを見つけることができませんでした。

プロジェクトに1つのアプリがあります。プロジェクト名がmyprojectで、アプリ名がだとしmyappます。

urls.pyファイルは2つあり、1つは、もう1つは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')

そして、それは私の問題を解決しました。


@boveson、これは魅力のように機能します!私の側の何時間もの欲求不満を解決してくれてありがとう。
lmiguelvargasf

これも私にとってはうまくいきました。私の側での重要なポイントの1つは、ルートのbase_nameの正しいスペルでした!
マギー

1
ここで重要なのは、名前空間接頭辞の防止が.....作業から逆になっている
boatcoder

私はこのような問題を抱えていましたが、この答えは3時間の検索後に問題を解決しました!@bovenson
クジラ52Hz

:DRFが推奨するようまたはあなたがextra_kwargsを利用することができますextra_kwargs = {'url': {'view_name': 'myapp:user-detail'}}
ChrisRob

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
要約すると、APIに名前空間を与えると、タイトルにエラーが発生します。多くの場所で変更したくない限り、それを実行したくないでしょう。
マーク

私のために働いた!私urls.pynewsiteプロジェクトで二重にネストされていました:(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

このエラーを引き起こすもう1つの厄介な間違いは、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にカスタムdef get_queryset()を定義したため、Djangoがbase_nameを追加するように指示したため、そうした可能性があります。この場合、問題のシリアライザのHyperlinkedIdentityFieldとして「url」を明示的に定義する必要があります。エラーをスローしているビューのSERIALIZERでこのHyperlinkedIdentityFieldを定義していることに注意してください。エラーが「ビュー名 "study-detail"を使用してハイパーリンク関係のURLを解決できませんでした。APIに関連モデルを含めることができなかったかlookup_field、このフィールドの属性が正しく構成されていない可能性があります。」次のコードでこれを修正できます。

私の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

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

うん。このHyperlinkedIdentityFieldを機能させるには、それ自体を明示的に定義する必要があります。またview_name、HyperlinkedIdentityFieldで定義されたものbase_nameがurls.pyで定義されたものと同じであり、その後に「-detail」が追加されていることを確認する必要があります。


2
これは私にとってはうまくいきましたが、私は完全なルートを入れなければなりません<app_name>:studies-detailでした。たとえば、私のアプリが呼び出された場合、tanksフルパスは次のようになりますHyperlinkedIdentityField(view_name="tanks:studies-detail")django-exensions show_urlsコマンドを使用して、ルーターが自動的に作成した完全なルートとラベルを確認しました。
dtasev 2018年

10

このコードも動作するはずです。

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

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


これは私にとってはうまくいきましたが、うまくいくためにはrouter.register(r'bottles '、views.BottleViewSet、base_name =' bottles ')をrouter.register(r'bottles'、views.BottleViewSet)に変更する必要がありました。この変更が必要になった理由はわかりません。
マンピキン

4

私のURLに名前空間を追加した後、私はこのエラーに遭遇しました

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

app_nameをurls.pyに追加します

私のプロジェクトのsettings.pyで残りのフレームワークAPIにNamespaceVersioningを指定することでこれを解決しました

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直接指定しなかったためUserViewSetbase_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は 'user'ではなく 'customuser'である必要があります」というコメントが私の一日を救いました。ありがとう!
HannonCésar

1

GenericViewSetクラスとListModelMixinクラスを拡張していて、リストビューにurlフィールドを追加するときに同じエラーが発生するのは、詳細ビューを定義していないためです。RetrieveModelMixinミックスインを拡張していることを確認してください。

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

1

HyperlinkedModelSerializerパスを持つことに同意しないようですnamespace。私のアプリケーションでは、2つの変更を加えました。

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

インポートされたurlsファイル

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

お役に立てれば。


0

DRFクイックスタートガイド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で何かが適切に作成されていないと思われました。私は自分のdev dbを気にしていなかったので、それを削除して./manage.py migrateコマンドをもう一度実行し、スーパーユーザーを作成し、/ usersを参照しましたが、エラーは発生しませんでした。

DRFとdbを構成した操作の順序に問題がありました。

sqliteを使用していて、新しいDBへの変更をテストできる場合は、すべてのコードを分析する前に試してみる価値があります。


0

ボトル= serializers.PrimaryKeyRelatedField(read_only = True)

read_onlyを使用すると、モデルの別のビューにリンクしなくてもフィールドを表すことができます。


0

データベースでslug値が空( ''に等しい)のとき、DRF 3.7.7でそのエラーが発生しました。



0

私はほぼ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')),

]

そしてようやく問題を解決しましたので、だれでも理由を教えてください。


0

シリアライザからフィールド 'id'と 'url'を省略しても問題はありません。とにかくjsonオブジェクトで返されるIDを使用して投稿にアクセスできるため、フロントエンドの実装がさらに簡単になります。


0

私も同じ問題を抱えていました。

get_absolute_url

オブジェクトモデルのメソッド入力値(** kwargs)のタイトル。lookup_fieldで正確なフィールド名を使用する

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.