Python 视图集和其他检索URL
我有一个django模型Python 视图集和其他检索URL,python,django,rest,django-rest-framework,Python,Django,Rest,Django Rest Framework,我有一个django模型捐赠,我将其公开为一个视图集。现在,我想向第二个模型Shop添加一个额外的URL,其中可以通过参数order\u id检索捐赠的相关实例,并且可以执行自定义操作 # models.py class Donation(models.Model): id = models.AutoField(primary_key=True) order_id = models.StringField(help_text='Only unique in combination wit
捐赠
,我将其公开为一个视图集。现在,我想向第二个模型Shop
添加一个额外的URL,其中可以通过参数order\u 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)
#models.py
班级捐赠(models.Model):
id=models.AutoField(主键=True)
order\u id=models.StringField(help\u text='仅在与字段'origin'组合时唯一〕
origin=模型。ForeignKey('Shop',on_delete=模型。PROTECT)
类别商店(型号.型号):
id=models.AutoField(主键=True)
#views.py
类DonationViewSet(mixin.CreateModelMixin,
mixin.RetrieveModelMixin,
mixin.ListModelMixin,
ViewSet.GenericViewSet):
def检索(self、request、*args、**kwargs):
如果kwargs['pk'].isdigit():
返回super(DonationViewSet,self)。检索(请求,*args,**kwargs)
其他:
shop\u id=self.request.query\u params.get('shop\u id',None)
order\u id=self.request.query\u params.get('order\u id',None)
如果店铺id不是None,订单id不是None:
实例=捐赠.objects.filter(origin=shop\u id,order\u id=order\u id).first()
如果实例为“无”:
返回响应(status=status.HTTP\u 404\u未找到)
返回响应(self.get\u序列化程序(实例).data)
返回响应(status=status.HTTP\u 404\u未找到)
@操作(方法=['post'],细节=True)
def自定义_操作(自我、请求、*args、**kwargs):
通过
类ShopViewSet(ViewSet.ModelViewSet):
通过
#url.py
路由器=路由器。默认路由器()
路由器.寄存器(r'捐赠',捐赠视图集)
路由器.注册表(r'shops',ShopViewSet)
路由器.注册(r'shops/(?P[0-9]+)/捐赠/(?P[0-9]+)”,捐赠视图集)
我的目标是http://localhost:8000/donations 指向整个DonationViewSet。另外,我想通过shop\u id
和order\u id
的组合查找个人捐赠,如下所示http://localhost:8000/shops/123/donations/1337/ 并执行如下自定义操作http://localhost:8000/shops/123/donations/1337/custom_action/. 我遇到的问题是,第二个url返回一个完整的查询集,而不仅仅是模型的一个实例。您需要
- 从
GenericViewSet
派生,因为您仍在使用模型
- 使用自定义查找逻辑替代
get\u object()
:
这应该让你做
mymodels/
要列出模型
mymodels/123/
通过PK获取模型
mymodels/kasjdfg/
要通过第三方服务id获取模型
mymodels/123/custom_action/
通过PK在模型上运行custom_action
mymodels/kasjdfg/custom_action/
按服务id在模型上运行custom_action
您只需在配置中添加路由器的URL即可添加URL,如下所示。如果您只想从一个视图中为一个特定的url添加一个操作,并且不需要视图集的所有操作/url
#url.py
URL模式=[
路径('some_path',my_lookup_view)),
]#典型的django url约定
urlpatterns+=router.url
#views.py
@api_视图(['POST'])
定义my_loup_视图(请求、店铺id、订单id):
#…一些查找。。。
通过
您也可以使用,它将有如下内容:
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
您要注册同一个视图集两次,这没有意义。使用DRF,您不需要单独注册唯一的URL,路由器会在后台注册。谢谢@AKX。我怀疑这可能是真的,因为我真的觉得我是在和DRF作对。DRF的做法是什么?普通视图
s,而不是视图集
s?是否要在您的店铺页面中按订单id搜索??是吗?@boyenec是的,但不是:D我想通过订单id
搜索一家商店的捐赠,然后更改它们。我使用此路径,以便商店可以更新捐赠,而无需首先检索其id
。我将缺少的mixin添加到示例代码中,在简化实际代码时,我忘记了这一点。你的答案看起来和我想要的差不多,但是我希望URL不是mymodels/kasjdfg/custom\u action/
,而是myothermodel/kasjdfg/custom\u action/
。使用DRF可以吗?如果能让我更好地控制这些事情,那么我可以选择放弃这个类的ViewSet
。这确实是我的应用程序的中心模型。为什么要使用两个URL访问相同的模型?因为第三方服务id
与myThermodel
相关,而不是mymodel
。更糟糕的是,它只保证对于给定的myothermodel
是唯一的。我简化了我的示例,因为我不认为它会增加我的问题,但真正的URL必须是myThermodels/123/mymodels/kasdfg/custom_action
。我知道我可以通过两个请求轻松解决这个问题,但这是一条每天会被调用数千次的路线,因此如果可能的话,我想将流量减少一半。你以前没有提到myothermodel
?很抱歉,我在第一次尝试时错过了另一个模型,因为我想提供一个非常通用的问题。我已经修改了我的问题,以更好地反映我的实际模型,并希望新的模型名称有助于更好地理解它们之间的关系。这似乎是我想要的,今晚我将尝试这个。
donations/
donations/1337/
shops/123/donations/1337/
shops/123/donations/1337/custom_action