web-dev-qa-db-ja.com

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

ユーザーをログインしてワインセラーを表示できる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)),
    # ...

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

ありがとう

90
bpipat

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

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

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

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

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

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

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

54
bovenson

多分誰かがこれを見ることができます: 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')
18
JackPy

このコードも機能するはずです。

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

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

このエラーの原因となるもう1つの厄介な間違いは、base_nameがurls.pyで不必要に定義されていることです。例えば:

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」を明示的に定義する必要があります。エラーをスローしているビューのシリアライザでこの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を明示的に定義して、機能させる必要があります。また、HyperlinkedIdentityFieldで定義されたview_nameが、urls.pyのbase_nameで定義されたものと同じであり、その後に '-detail'が追加されていることを確認する必要があります。

9
Colton Hicks

同じエラーですが、異なる理由:

カスタムユーザーモデルを定義しますが、新しいフィールドはありません。

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

querysetUserViewSetを直接指定しなかったため、このビューセットを登録するときに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

2
Belter

GenericViewSetおよびListModelMixinクラスを拡張していて、リストビューにrlフィールドを追加するときに同じエラーが発生する場合は、 '詳細ビューを定義していません。 RetrieveModelMixin mixinを拡張していることを確認してください:

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

データベース内のスラッグ値が空( ''と等しい)の場合、DRF 3.7.7でそのエラーが発生しました。

0
mrmuggles

この同じ問題にぶつかり、generics.RetrieveAPIViewをビュークラスに基本クラスとして追加することで解決しました。

0
Jace Browning

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

私は同じ問題を抱えていたので、

get_absolute_url

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

0
hassanzadeh.sd

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
Ben Havilland

私はほぼ2時間このエラーで立ち往生しました:

ImpproperlyConfigured at/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
Cam T

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

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

0