私は次の状況で少し立ち往生しています。Django Rest Framework を使用してショッピング カート アプリ用の REST API を構築したいのですが、従来の要件により、ネストされた URL を操作する必要があります。
通常、AppUsers と Carts の 2 つのリソースがあります。どちらのリソースも、デフォルトの /appUsers/ および /carts/ エンドポイントで利用できます。次に、ネストされたルーターを使用して、特定のユーザーのカート詳細ビューを /carts/pk/ ではなく /appUsers/app_user_pk/cart/ としてアドレス指定できるようにしました。
これが私のセットアップです:
models.py
class AppUser(models.Model):
_id = models.AutoField(primary_key=True)
class Meta:
default_related_name = 'app_users'
class Cart(models.Model):
app_user = models.OneToOneField(
'AppUser',
on_delete=models.CASCADE,
related_query_name='cart',
)
class Meta:
default_related_name = 'carts'
def __str__(self):
return "{user} cart".format(user=self.app_user._id)
serializers.py
class AppUserSerializer(serializers.HyperlinkedModelSerializer):
cart = serializers.HyperlinkedIdentityField(view_name='cart-detail')
class Meta:
model = AppUser
fields = '__all__'
class CartSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Cart
fields = '__all__'
ビュー.py
class AppUserViewSet(viewsets.ModelViewSet):
"""
Model viewset for AppUser model
"""
queryset = AppUser.objects.all()
serializer_class = AppUserSerializer
class CartViewSet(viewsets.ModelViewSet):
"""
List all carts, or create new / edit existing product.
"""
queryset = Cart.objects.all()
serializer_class = CartSerializer
def get_queryset(self):
if 'app_user_pk' in self.kwargs:
return Cart.objects.filter(app_user=self.kwargs['app_user_pk'])
return Cart.objects.all()
urls.py
router = DefaultRouter()
router.register(r'appUsers', views.AppUserViewSet)
router.register(r'carts', views.CartViewSet)
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^appUsers/(?P<app_user_pk>[0-9]+)/cart/$', views.CartViewSet.as_view({'get': 'retrieve'}), name='cart-detail'),
]
ただし、何か新しいことを試みるたびに、別の問題に遭遇するため、それを機能させることはできません。だから、そのようなタスクを達成するための最良の方法は何だろうと思っていましたか?
基本的に、AppUser が /appUsers/app_user_pk/cart/ の下に持つことができる 1 つのショッピング カートのカート詳細ビューを表示したいだけです。
解決:
上記の問題に対処するために、受け入れられた回答を使用しました。さらに、/appUsers/app_user_pk/cart/products に別の ModelViewSet を配置し、drf-nested-routers の NestedDefaultRouter を使って以下のように cart/products に登録しました。
cart_products_router = routers.NestedDefaultRouter(router, r'appUsers', lookup='app_user')
cart_products_router.register(r'cart/products', views.CartProductViewSet, base_name='cartproduct')