Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 视图集和其他检索URL_Python_Django_Rest_Django Rest Framework - Fatal编程技术网

Python 视图集和其他检索URL

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

我有一个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 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