ユーザーをログインしてワインセラーを表示できる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)),
# ...
ユーザー詳細ビューがなく、この問題の原因がわかりません。何か案は?
ありがとう
HyperlinkedModelSerializer
であるため、シリアライザーはUser
の関連Bottle
のURLを解決しようとしています。
ユーザー詳細ビューがないため、これはできません。したがって、例外。
UserViewSet
をルーターに登録するだけで問題が解決しませんか?BottleSerializer
のユーザーフィールドを定義して、UserSerializer
を明示的に使用できます。 そのためのネストされたオブジェクトの処理に関するシリアライザのドキュメント を参照してください。私もこのエラーに遭遇し、次のように解決しました:
その理由は、「**-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')
そしてそれは私の問題を解決しました。
多分誰かがこれを見ることができます: 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')
このコードも機能するはずです。
class BottleSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
class Meta:
model = Bottle
fields = ('url', 'wine', 'user')
このエラーの原因となるもう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'が追加されていることを確認する必要があります。
同じエラーですが、異なる理由:
カスタムユーザーモデルを定義しますが、新しいフィールドはありません。
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
。
GenericViewSetおよびListModelMixinクラスを拡張していて、リストビューにrlフィールドを追加するときに同じエラーが発生する場合は、 '詳細ビューを定義していません。 RetrieveModelMixin mixinを拡張していることを確認してください:
class UserViewSet (mixins.ListModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet):
データベース内のスラッグ値が空( ''と等しい)の場合、DRF 3.7.7でそのエラーが発生しました。
この同じ問題にぶつかり、generics.RetrieveAPIView
をビュークラスに基本クラスとして追加することで解決しました。
シリアライザーからフィールド「id」と「url」を省略しても問題はありません。とにかくjsonオブジェクトで返されるIDを使用して投稿にアクセスできます。これにより、フロントエンドの実装がさらに簡単になります。
私は同じ問題を抱えていたので、
get_absolute_url
オブジェクトモデルのメソッド入力値(** kwargs)タイトル。 lookup_fieldで正確なフィールド名を使用します
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への変更をテストできる場合は、すべてのコードを分析する前に試してみる価値があります。
私はほぼ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')),
]
そして、私は最終的に私の問題を解決するので、誰もが最高の理由を教えてくれます。
ボトル= serializers.PrimaryKeyRelatedField(read_only = True)
read_onlyを使用すると、フィールドをモデルの別のビューにリンクすることなくフィールドを表すことができます。