python - ViewSet 和额外的检索 URL
问题描述
我有一个Donation
作为 ViewSet 公开的 django 模型。现在我想向第二个模型添加一个额外的 URL,在该模型中,可以通过参数检索Shop
相关实例,并且可以执行自定义操作。Donation
order_id
# models.py
class Donation(models.Model):
id = models.AutoField(primary_key=True)
order_id = models.StringField(help_text='Only unique in combination with field `origin`')
origin = models.ForeignKey('Shop', on_delete=models.PROTECT)
class Shop(models.Model):
id = models.AutoField(primary_key=True)
# views.py
class DonationViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet):
def retrieve(self, request, *args, **kwargs):
if kwargs['pk'].isdigit():
return super(DonationViewSet, self).retrieve(request, *args, **kwargs)
else:
shop_id = self.request.query_params.get('shop_id', None)
order_id = self.request.query_params.get('order_id', None)
if shop_id is not None and order_id is not None:
instance = Donations.objects.filter(origin=shop_id, order_id=order_id).first()
if instance is None:
return Response(status=status.HTTP_404_NOT_FOUND)
return Response(self.get_serializer(instance).data)
return Response(status=status.HTTP_404_NOT_FOUND)
@action(methods=['post'], detail=True)
def custom_action(self, request, *args, **kwargs):
pass
class ShopViewSet(viewsets.ModelViewSet):
pass
# urls.py
router = routers.DefaultRouter()
router.register(r'donations', DonationViewSet)
router.register(r'shops', ShopViewSet)
router.register(r'shops/(?P<shop_id>[0-9]+)/donations/(?P<order_id>[0-9]+)', DonationViewSet)
我的目标是让 http://localhost:8000/donations 指向整个 DonationViewSet。我还想查找个人捐赠,通过它的组合shop_id
和order_id
类似 http://localhost:8000/shops/123/donations/1337/ 并执行自定义操作,如 http://localhost:8000/shops /123/donations/1337/custom_action/。我遇到的问题是第二个 url 返回整个查询集,而不仅仅是模型的单个实例。
解决方案
您还可以使用drf-nested-routers,它将具有以下内容:
from rest_framework_nested import routers
from django.conf.urls import url
# urls.py
router = routers.SimpleRouter()
router.register(r'donations', DonationViewSet, basename='donations')
router.register(r'shops', ShopViewSet, basename='shops')
shop_donations_router = routers.NestedSimpleRouter(router, r'', lookup='shops')
shop_donations_router.register(
r'donations', ShopViewSet, basename='shop-donations'
)
# views.py
class ShopViewSet(viewsets.ModelViewSet):
def retrieve(self, request, pk=None, donations_pk=None):
# pk for shops, donations_pk for donations
@action(detail=True, methods=['PUT'])
def custom_action(self, request, pk=None, donations_pk=None):
# pk for shops, donations_pk for donations
这个没有测试!但除了你已经拥有的,这将支持:
donations/
donations/1337/
shops/123/donations/1337/
shops/123/donations/1337/custom_action
推荐阅读
- opencv - 如何提高护照的识别度?
- php - 为什么 opcache 缓存字节码而不是机器码?
- c# - 如何在字符串上获取特定的主站点文本
- javascript - 如何在画布中调整使用 fillText() 添加的文本大小?
- python - “如何使用 argparse 模块并从命令行调用函数?”
- postgresql - Postgres 减、除列和排序,DESC
- html - 如何解决背景图像未在 CSS 中显示的问题
- xaml - Xamarin XAML 预览器设计数据绑定
- android - 如何在Android中的元素开头从ArrayList中删除空间
- php - 将多个系统登录合并为 1