Django Rest Framework - "Kullanıcı ayrıntısı" görünüm adı kullanılarak köprülenmiş ilişki için URL çözülemedi


108

Django Rest Framework'te kullanıcıların şarap mahzenlerini görüntülemek için oturum açabilecekleri bir proje oluşturuyorum. ModelViewSets'im gayet iyi çalışıyordu ve birdenbire bu sinir bozucu hatayı alıyorum:

Görünüm adı "kullanıcı ayrıntısı" kullanılarak köprü bağlantılı ilişki için URL çözülemedi. API'nize ilgili modeli dahil edememiş veya lookup_fieldbu alandaki özelliği yanlış yapılandırmış olabilirsiniz .

İzleme şunları gösterir:

    [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.

Özel bir e-posta kullanıcı modelim var ve models.py'deki şişe modeli:

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

Serileştiricilerim:

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

Görüşlerim:

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

ve son olarak url:

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

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

Kullanıcı ayrıntıları görünümüm yok ve bu sorunun nereden gelebileceğini göremiyorum. Herhangi bir fikir?

Teşekkürler

Yanıtlar:


96

Bir Çünkü HyperlinkedModelSerializersenin serileştirici ilgili URL'sini çözümlemeye çalışıyor UserAşağıdaki yerlerde de Bottle.
Kullanıcı ayrıntı görünümüne sahip olmadığınız için bunu yapamaz. Bu nedenle istisna.

  1. Yalnızca UserViewSetyönlendiriciye kaydolmak sorununuzu çözmez mi?
  2. URL'yi çözmeye çalışmak yerine BottleSerializer, açık bir şekilde kullanmak için kullanıcı alanını tanımlayabilirsiniz UserSerializer. Bunun için yuvalanmış nesnelerle ilgili serileştirici belgelerine bakın .

1
Çok teşekkürler, yönlendiricilerimde UserViewSet'i yorumladım, bu sorunu çözdü!
bpipat

5
NOKTA BU - açıkça yapın - sihir çok fazla zaman kaybetmektir.
andilabs

Üzerinde yanlış yapılandırmadığınızdan ne işaret misiniz projemde ?
JJD

@ GrijeshChauhan— Teşekkürler! Şimdi düzeltildi.
Carlton Gibson

Çalışmamasının nedeni, django'nun Kullanıcı'dan ilgili verileri Kullanıcı parametresi için geçerli görünümünüzde göstermek istemesiydi. Genellikle mevcut değerlerin bir listesini alır. UserViewSet tanımlanmadığından, web sayfasını işlemek için ayrıntıları çekemedi. Varsayılan yönlendirici altında UserViewSet ve regisetering eklemek, tüm bileşenleri işlemek için işi tamamlar.
Doogle

66

Ben de bu hatayla karşılaştım ve şu şekilde çözdüm:

Bunun nedeni "** - ayrıntı" (görünüm_adı, örneğin: kullanıcı ayrıntısı) bir ad alanı vermeyi unutmuş olmam. Yani, Django Rest Framework bu görünümü bulamadı.

Projemde bir uygulama var, farz edin ki proje adımı myprojectve uygulama adı myapp.

İki urls.py dosyası var, biri myproject/urls.pyve diğeri myapp/urls.py. Uygulamaya myproject/urls.pyşunun gibi bir ad alanı veriyorum :

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

Geri kalan çerçeve yönlendiricilerini kaydettim myapp/urls.pyve sonra bu hatayı aldım.

Çözümüm, url'ye açıkça ad alanı sağlamaktı:

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

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

Ve sorunumu çözdü.


@boveson, bu bir cazibe gibi çalışıyor! Benim tarafımdan saatlerce süren hayal kırıklığını çözdün.
lmiguelvargasf

Bu da benim için çalışmasını sağladı. Benim tarafımdaki önemli bir nokta da, Rotadaki base_name'nin doğru yazılışıydı!
maggie

1
Buradaki anahtar, ad alanı ön ekinin
tersin

Böyle bir sorun yaşadım ve bu cevap 3 saatlik aramadan sonra sorunumu çözdü! @bovenson
Whale 52Hz

: DRF önerir olarak veya extra_kwargs yararlanabilirlerextra_kwargs = {'url': {'view_name': 'myapp:user-detail'}}
ChrisRob

19

Belki birisi şuna bakabilir: http://www.django-rest-framework.org/api-guide/routers/

Köprülü serileştiricilerle ad alanı kullanıyorsanız, serileştiricilerdeki tüm görünüm_adı parametrelerinin ad alanını doğru şekilde yansıttığından emin olmanız gerekir. Örneğin:

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

view_name='api:user-detail'kullanıcı ayrıntı görünümüne köprülenmiş serileştirici alanları gibi bir parametre eklemeniz gerekir .

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

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

1
Özetle, api'nize bir ad alanı vermek başlıkta hataya neden olur, birçok yerde değiştirmek istemediğiniz sürece muhtemelen yapmak istemezsiniz.
Mark

benim için çalıştı! Benim urls.pyçift benim de iç içe olan newsiteprojede: (1) newsite/urls.py(django tarafından oluşturulan) (2) polls/urls.py(3) polls/api/v1/urls.py ............ kullanıyorum iç içe adını bahsetmek zorundaurl = serializers.HyperlinkedIdentityField(view_name="polls:polls_api:user-detail")
Grijesh Chauhan

12

Bu hataya neden olan başka bir kötü hata da base_name'in urls.py'nizde gereksiz şekilde tanımlanmış olmasıdır. Örneğin:

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

Bu, yukarıda belirtilen hataya neden olacaktır. Bu base_name oradan alın ve çalışan bir API'ye geri dönün. Aşağıdaki kod hatayı düzeltir. Yaşasın!

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

Bununla birlikte, muhtemelen temel_adı rastgele eklemediniz, bunu Görünüm için özel bir def get_queryset () tanımladığınız için yapmış olabilirsiniz ve böylece Django, base_name eklemenizi zorunlu kılar. Bu durumda, 'url'yi söz konusu serileştirici için bir HyperlinkedIdentityField olarak açıkça tanımlamanız gerekir. Bu HyperlinkedIdentityField'ı, hatayı atan görünümün SERIALIZER ÜZERİNDE tanımladığımıza dikkat edin. Benim hatam "Görünüm adı kullanılarak köprülü ilişki için URL çözülemedi" "çalışma detayı" ise. İlgili modeli API'nize dahil edememiş veya lookup_fieldbu alanda özelliği yanlış yapılandırmış olabilirsiniz . " Bunu aşağıdaki kodla düzeltebilirim.

My ModelViewSet (özel get_queryset, base_name'i yönlendirici.register () 'a ilk etapta eklememin nedenidir):

class StudyViewSet(viewsets.ModelViewSet):
    serializer_class = StudySerializer

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

Urls.py'deki bu ModelViewSet için yönlendirici kaydım:

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

VE BURADA PARA NEREDE! O zaman bunu şu şekilde çözebilirim:

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

Evet. Çalışması için bu HyperlinkedIdentityField'ı kendi üzerinde açıkça tanımlamanız gerekir. Ve view_nameHyperlinkedIdentityField'da tanımlananın base_nameurls.py'de tanımladığınızla aynı olduğundan ve arkasına '-detail' eklendiğinden emin olmanız gerekir.


2
Bu benim için çalıştı, ancak tüm yolu belirlemem gerekiyordu <app_name>:studies-detail. Örneğin tanks, uygulamam çağrılırsa , tam yol olacaktır HyperlinkedIdentityField(view_name="tanks:studies-detail"). Bunu anlamak için django-exensions show_urls komutunu kullandım , tam yolu ve yönlendiricinin otomatik olarak yaptığı etiketi görmek için.
dtasev

10

Bu kod da çalışmalıdır.

class BottleSerializer(serializers.HyperlinkedModelSerializer):

  user = UserSerializer()

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


Bu benim için çalıştı, ancak çalışması için router.register'ı (r'bottles ', views.BottleViewSet, base_name =' bottle ') router.register (r'bottles', views.BottleViewSet) olarak değiştirmek zorunda kaldım. Bu değişikliğin neden gerekli olduğunu bilmiyorum.
2019

4

URL'ime ad alanı ekledikten sonra bu hatayla karşılaştım

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

ve url'lerime app_name ekliyor

Bunu, projemin settings.py dosyasında kalan çerçeve API'm için NamespaceVersioning belirterek çözdüm

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

3

Bugün aynı hatayı aldım ve aşağıdaki değişiklikler beni kurtarıyor.

Değişiklik

class BottleSerializer(serializers.HyperlinkedModelSerializer):

to:

 class BottleSerializer(serializers.ModelSerializer):

2

Aynı Hata, ancak farklı neden:

Özel bir kullanıcı modeli tanımlıyorum, yeni alan yok:

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

Bu benim görüş işlevim:

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

querysetDoğrudan teslim olmadığım için UserViewSet, base_namebu görünüm kümesini ne zaman kaydettireceğimi ayarlamam gerekiyor. Hata mesajımın urls.pydosya neden olduğu yer burası :

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'

Bir ihtiyaç base_namemodeliniz adıyla aynı - customuser.


Eski gönderi, ancak "# <- base_name" kullanıcı "yerine" özel kullanıcı "yorumunuz günümü kurtardı. Teşekkürler!
Hannon César

1

GenericViewSet ve ListModelMixin sınıflarını genişletiyorsanız ve url alanını liste görünümüne eklerken aynı hatayı alıyorsanız , bunun nedeni ayrıntı görünümünü tanımlamamanızdır. RetrieveModelMixin karışımını genişlettiğinizden emin olun :

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

1

Görünüşe HyperlinkedModelSerializergöre bir yola sahip olmakla uyuşmuyor namespace. Başvurumda iki değişiklik yaptım.

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

İçe aktarılan urls dosyasında

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

Bu yardımcı olur umarım.


0

DRF hızlı başlangıç ​​kılavuzunu http://www.django-rest-framework.org/tutorial/quickstart/ takip ederken ve ardından / users'a göz atmaya çalışırken aynı hatayla karşılaştım . Bu kurulumu daha önce birçok kez sorunsuz bir şekilde yaptım.

Benim çözümüm kodda değil, veritabanını değiştirmekti.

Bu kurulum ile diğer kurulumlar arasındaki fark, yerel veritabanını oluşturduğum zamandı.

Bu sefer koştum

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

koştuktan hemen sonra

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

Kılavuzda listelenen tam sıra yerine.

DB'de bir şeyin doğru şekilde yaratılmadığından şüphelendim. Dev veritabanı umrumda değildi, bu yüzden onu sildim ve./manage.py migrate komutu bir kez daha bir süper kullanıcı oluşturdum, / users'a göz ve hata gitti.

DRF ve db'yi yapılandırdığım işlemlerin sırasına ilişkin bir sorun vardı.

Sqlite kullanıyorsanız ve yeni bir DB'ye geçmeyi test edebiliyorsanız, tüm kodunuzu incelemeye başlamadan önce denemeye değer.


0

Şişe = serializers.PrimaryKeyRelatedField (read_only = True)

read_only, alanı modelin başka bir görünümüne bağlamanıza gerek kalmadan temsil etmenize olanak sağlar.


0

Bu hatayı DRF 3.7.7'de veritabanında bir bilgi değeri boş olduğunda ('' değerine eşittir) aldım.


0

Aynı sorunla karşılaştım ve generics.RetrieveAPIViewgörünüm kümeme temel sınıf olarak ekleyerek çözdüm.


0

Neredeyse 2 saattir bu hataya takılıp kaldım:

/ Api_users / users / 1 konumunda yanlış yapılandırıldı / "users-detail" görünüm adı kullanılarak köprülü ilişki için URL çözülemedi. API'nize ilgili modeli dahil edememiş veya lookup_fieldbu alandaki özelliği yanlış yapılandırmış olabilirsiniz .

Çözümü nihayet aldığımda ama nedenini anlamıyorum, bu yüzden kodum:

#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)),
]

ancak ana URL'lerimde şunlardı:

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

]

Sonunda ad alanını silme sorununu çözmek için:

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

]

Ve sonunda sorunumu çözüyorum, böylece herhangi biri bana nedenini en iyi şekilde bildirebilir.


0

Serileştiricinizden 'id' ve 'url' alanlarını çıkarırsanız herhangi bir sorun yaşamazsınız. Her durumda json nesnesinde döndürülen kimliği kullanarak gönderilere erişebilirsiniz, bu da ön ucunuzu uygulamayı daha da kolaylaştırır.


0

Ben de aynı sorunu yaşadım, bence kontrol etmelisin

get_absolute_url

nesne modelinin yöntem girdi değeri (** kwargs) başlığı. ve aranan_ alanında tam alan adını kullanın

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.