【问题标题】:How do I fetch a list of model objects by querying another related model in a many to many relationship in DRF如何通过在 DRF 中以多对多关系查询另一个相关模型来获取模型对象列表
【发布时间】:2020-01-22 06:49:03
【问题描述】:

models.py:

class OrderItem(models.Model):
      image_number = models.CharField(max_length=20)
      title = models.CharField(max_length=20)
      image_url = models.URLField(max_length=200,null=True,blank=True)
      image_size = models.CharField(max_length=50)
      file_type = models.CharField(max_length=20)
      price = models.CharField(max_length=50)

     def __str__(self):
         return self.title

class Order(models.Model):
      order_status = (
          ('created','created'), 
          ('processing','processing'),
          ('orderd','orderd')
        )
      user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, blank=True,null=True)
      items = models.ManyToManyField(OrderItem)
      order_status = models.CharField(choices=order_status,null=True,max_length=50)
      start_date = models.DateTimeField(auto_now_add=True)
      ordered_date = models.DateTimeField(auto_now_add=False,blank=True,null=True)

views.py:

class AddtocartView(generics.CreateAPIView):
      authentication_classes = []
      permission_classes = []
      pagination_class = None
      queryset = OrderItem.objects.all()
      serializer_class = AddtocartSerializers

    def perform_create(self,serializer):
        new_order_item = serializer.save()
        user=CustomUser.objects.filter(id=self.kwargs['customer_id']).first() 

        try:
           orders_list = Order.objects.get(user=user)            
           orders_list.items.add(new_order_item) 
        except Order.DoesNotExist: 
            order = Order.objects.create(user=user) 
            order.items.add(new_order_item)  


       def __str__(self):
           return str(self.user)

urls.py:

 path('customer/<int:customer_id>/addtocart/',views.AddtocartView.as_view(),name='addtocart'),
 path('customer/<int:customer_id>/cart/',views.CartView.as_view(),name='cart'),   

一切正常。当我运行perform_create API 时,它会检查是否存在现有的created 订单,如果有则将OrderItem 添加到items,否则它将创建一个订单。所以我的问题是当用户付款并且Order.status 更改为ordered 时,我将如何获取订购的商品和购物车商品。 所以我想我应该为每个OrderItem 创建一个订单,然后如果订单完成,它会将Order.status 更改为ordered,否则它将是created。这样我会将created 提取到购物车,将ordered 提取到Ordered page。有什么建议,关于我如何增强这种逻辑?

【问题讨论】:

    标签: django python-3.x django-rest-framework


    【解决方案1】:

    根据我在您的问题中的理解,您需要一个 API 来根据其相关的 Order 状态检索 OrderItems。 如果我弄错了,请在 cmets 中纠正我

    为了保持这个逻辑干净,

    我建议您放弃为每个 OrderItem 创建一个 Order 的想法

    我相信对你有用的是,为 OrderItems 创建一个 API,我们将其称为 OrdersItemsListViewAPIOrder,并基于 url 参数基于 Order.status 进行过滤例如:@987654328 @,这样你只会得到created 订单,或ordered 订单,..etc

    一个简单的例子

    class OrdersItemsListViewAPI(generics.ListAPIView):
        """
        Return a list of all the products that the authenticated
        user has ever purchased, with optional filtering.
        """
        serializer_class = OrderItemSerializer
    
        def get_queryset(self):
            # You are using a custom user, make sure you get the custom user to do the query below.
            user = self.request.user
            status = self.request.query_params.get('status', None)
            # To make sure you are getting user's orders
            orders = Order.objects.filter(user=user)
            if status:
                # Filtering user's orders to get specific status
                orders = orders.filter(order_status=status)
            # Now get All OrderItems that belong to fetched orders.
            return OrderItem.objects.filter(order__in=orders)
    

    更新:为了基于多个状态进行过滤,只需在查询参数?status=created,ordered 中传递以逗号分隔的状态,并将它们提取到您的get_queryset 方法中,如下所示。

    ...
        def get_queryset(self):
            # You are using a custom user, make sure you get the custom user to do the query below.
            user = self.request.user
            status = self.request.query_params.get('status', None)
            # To make sure you are getting user's orders
            orders = Order.objects.filter(user=user)
            if status:
                # Filtering user's orders to get specific status
                status = [s.strip() for s in status.split(',')]
                orders = orders.filter(order_status__in=status)
            # Now get All OrderItems that belong to fetched orders.
            return OrderItem.objects.filter(order__in=orders)
    

    通过这种方式,您可以通过对控制器稍作修改来保持模型结构良好。

    我已经在类似的场景中测试过这段代码,它运行良好。

    【讨论】:

    • 好吧,你是对的,但仍然有些混乱,假设状态已创建您正在获取已创建状态的订单,但为什么要在 orders_ids 中过滤 order_id,因为 orderitem 没有 order_id 字段
    • 因为一个订单可以有多个订单项,我如何根据订单模型的状态进行过滤
    • 对不起,我是作为 OneToMany 关系做的,我会稍后更新我的答案
    • 您正在过滤用户,然后是 order_status,但一个用户有一个包含多个订单项的订单
    • 如果我获得创建状态,请查看图像,它将显示属于用户的所有订单项
    猜你喜欢
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 2013-04-27
    相关资源
    最近更新 更多