Saya mencoba membuat serial model dalam proyek DRF saya. Model berisi 2 bidang kunci asing dan beberapa bidang tipe data sederhana. Salah satu bidang kunci asing adalah model CustomUser saya dan bidang ini muncul sebagai hyperlink di keluaran API saya yang diharapkan. Bidang kunci asing lainnya adalah untuk model yang berbeda (ditunjukkan di bawah). Saya telah mengalami beberapa kesalahan yang sama selama beberapa jam terakhir karena saya telah mencoba berbagai solusi yang direkomendasikan di utas StackOverflow lainnya.

Dapatkah seseorang menunjukkan kepada saya cara menampilkan kunci asing kedua ini sebagai tautan di keluaran API saya?

Ketika file kode saya muncul seperti di bawah ini, saya mendapatkan kesalahan ini ketika mencoba mengakses URL localhost:8000/trade/create/ dan localhost:8000/trader-accounts/:

django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "traderaccount-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.

Tentu saja, saya mencari pesan kesalahan ini dan bagian-bagiannya di Google beberapa kali, dan mencoba beberapa lubang kelinci DRF mencoba berbagai hal.

trades/models.py

class Trade(models.Model):
    trade_owner = models.ForeignKey(CustomUser, related_name='owners', on_delete=models.RESTRICT)
    trade_account = models.ForeignKey(TraderAccount, related_name='trades', on_delete=models.RESTRICT)

trader_account/models.py

class TraderAccount(models.Model):

    account_owner = models.ForeignKey(
        CustomUser, on_delete=models.CASCADE,
    )
    account_name = models.CharField(
        max_length=200, blank=True, verbose_name='Account Name'
    )

api/serializers.py

class TraderAccountSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = TraderAccount
        fields = ['account_owner', 'account_name',]


class TradeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Trade
        fields = ['trade_owner', 'trade_account', 'magic_number',]

api/views.py

class TraderAccountView(generics.ListCreateAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = TraderAccount.objects.all()
    serializer_class = TraderAccountSerializer


class TradeCreateView(generics.ListCreateAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = Trade.objects.all()
    serializer_class = TradeSerializer

api/urls.py


router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('trader-accounts/', views.TraderAccountView.as_view(), name='trader-accounts'),
    path('trade/create/', views.TradeCreateView.as_view(), name='trade-create'),

Ketika saya menghapus 'trader_account' dari api.serializers.TradeSerializer.Meta.fields, saya berhasil mengakses titik akhir localhost:8000/trade/create/ dan titik akhir localhost:8000/trader-accounts/.

api/serializers.py

# Omit TraderAccountSerializer class for brevity in this example


class TradeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Trade
        fields = ['trade_owner', 'magic_number',]  # Removed 'trader_account'

Saya telah melihat ini begitu lama sekarang saya tidak dapat menemukan kesalahan. Sangat menghargai bantuannya!

0
allardbrain 14 Desember 2020, 06:56

3 jawaban

Jawaban Terbaik

Terima kasih banyak kepada Gabbeh karena telah mengarahkan saya ke arah yang benar.

Saya mengganti nama TraderAccountView(generics.ListCreateAPIView) menjadi TraderAccountList(viewsets.ModelViewSet) dan menambahkan tampilan ini ke api/views.py:

class TraderAccountDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = TraderAccount.objects.all()
    serializer_class = TraderAccountSerializer

File api/urls.py sekarang:

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
router.register(r'trader-accounts', views.TraderAccountList)

Dan semuanya bekerja!

-1
allardbrain 10 Januari 2021, 01:05

Berdasarkan api/views.py ini Anda memiliki TraderAccountView(generics.ListCreateAPIView). Anda harus mengganti namanya menjadi TraderAccountList(generics.ListCreateAPIView) dan kemudian menambahkan tampilan tambahan untuk detailnya; TraderAccountDetail(generics.RetrieveUpdateDestroyAPIView)

Api/views.py sekarang:

class TraderAccountList(generics.ListCreateAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = TraderAccount.objects.all()
    serializer_class = TraderAccountSerializer

class TraderAccountDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (IsAuthenticated,)
    queryset = TraderAccount.objects.all()
    serializer_class = TraderAccountSerializer

Pola url Anda sekarang seharusnya

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('trader-accounts/', views.TraderAccountList.as_view(), name='trader-accounts'),
    path('trader-accounts/<int:pk>/', views.TraderAccountDetail.as_view()),
]

Dan hapus TradeCreate. Saat Anda sedang membangun RESTful API. untuk membuat perdagangan Anda melakukan permintaan POST ke tampilan daftar untuk membuat perdagangan baru.

Pada tampilan daftar, Anda dapat melakukan GET untuk mendapatkan daftar semua perdagangan, atau POST untuk membuat perdagangan baru. Pada tampilan detail, Anda dapat melakukan GET untuk mendapatkan perdagangan tertentu, atau PUT atau PATCH untuk memperbarui, atau DELETE untuk menghapus perdagangan.

1
Gabbeh 14 Desember 2020, 04:56

Sudahkah Anda mencoba membuat rute untuk account dengan cara yang sama seperti user?

Pesan kesalahan yang Anda sertakan mengatakan bahwa tidak ada rute dengan nama yang diharapkan.

Menurut dokumentasi di https: //www.django-rest-framework.org/api-guide/serializers/#how-hyperlinked-views-are-determined, agar pemetaan otomatis berfungsi, Anda memerlukan tampilan dengan nama account-detail yang mengambil 1 parameter rute integer.

Serializer hyperlink adalah fiddly, seperti yang mereka katakan, jadi perhatikan baik-baik dokumen. Jika Anda mengubah nama tampilan, Anda dapat menimpanya di serializer.

account = serializers.HyperlinkedRelatedField(
    view_name='account-detail', # or whatever name you give it
    ...
)
0
Andrew Backer 14 Desember 2020, 15:17