【问题标题】:price() missing 1 required positional argument: 'self' while trying to calculate the price in Django Rest Frameworkprice() 缺少 1 个必需的位置参数:“self”,同时尝试在 Django Rest Framework 中计算价格
【发布时间】:2021-06-30 11:01:30
【问题描述】:

我正在尝试创建一个案例,当我调用 order create api 时,价格将自行计算并保存在数据库中,但我在邮递员中收到此错误。

错误:price() 缺少 1 个必需的位置参数:'self

我的模型:

class Order(models.Model):
    
    user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)   
    ordered_date = models.DateTimeField(auto_now_add=True)
    ordered = models.BooleanField(default=False)
    total_price = models.CharField(max_length=50,blank=True,null=True)
    #billing_details = models.OneToOneField('BillingDetails',on_delete=models.CASCADE,null=True,blank=True,related_name="order")

    def __str__(self):
        return self.user.email
  
def price(self):
    total_item_price = self.quantity * self.item.varaints.price
    return total_item_price

class OrderItem(models.Model):
    #user = models.ForeignKey(User,on_delete=models.CASCADE, blank=True
    #orderItem_ID = models.UUIDField(max_length=12, editable=False,default=str(uuid.uuid4()))
    orderItem_ID = models.CharField(max_length=12, editable=False, default=id_generator)
    order = models.ForeignKey(Order,on_delete=models.CASCADE, blank=True,null=True,related_name='order_items')
    item = models.ForeignKey(Product, on_delete=models.CASCADE,blank=True, null=True)
    order_variants = models.ForeignKey(Variants, on_delete=models.CASCADE,blank=True,null=True)
    quantity = models.IntegerField(default=1)

    total_item_price = models.PositiveIntegerField(blank=True,null=True,default=price())

    ORDER_STATUS = (
        ('To_Ship', 'To Ship',),
        ('Shipped', 'Shipped',),
        ('Delivered', 'Delivered',),
        ('Cancelled', 'Cancelled',),
    )
    order_item_status = models.CharField(max_length=50,choices=ORDER_STATUS,default='To_Ship')

这里的数量字段存在于 OrderItem 模型本身中,但价格存在于与 Product 模型相关的 Variant 模型中。

我尝试过的事情:

  1. 我尝试删除价格中的括号 (),但得到了同样的错误。
  2. 如果我尝试将 price 函数放入类模型中的 total_itel_price 字段之前,它会说 self 是必须在 price 括号内的,如果我放入 self,= 是必需的,我不知道放入 price(self=??)

其他型号:

Class Variants(models.Model):
    ...#other fields    
    price = models.DecimalField(decimal_places=2, max_digits=20,default=500)

Class Product(models.Model):
    ...#other fields
    variants = models.ManyToManyField(Variants,related_name='products')

我的序列化器:

class OrderSerializer(serializers.ModelSerializer):

    billing_details = BillingDetailsSerializer()
    order_items = OrderItemSerializer(many=True)
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
    class Meta:
        model = Order
        fields = ['id','user','ordered_date','order_status', 'ordered', 'order_items', 'total_price','billing_details']
        # depth = 1   

    def create(self, validated_data):
        user = self.context['request'].user
        if not user.is_seller:
            order_items = validated_data.pop('order_items')
            billing_details = validated_data.pop('billing_details')
            order = Order.objects.create(user=user,**validated_data)
            BillingDetails.objects.create(user=user,order=order,**billing_details)
            for order_items in order_items:
                OrderItem.objects.create(order=order,**order_items)
            
        else:
            raise serializers.ValidationError("This is not a customer account.Please login as customer.")

更新代码:

class OrderItem(models.Model):   
    
 #total_item_price = models.PositiveIntegerField(blank=True,null=True,default=0) #commented out this field other fields are same as above


order_item_status = models.CharField(max_length=50,choices=ORDER_STATUS,default='To_Ship')

@property
def price(self):
    return self.quantity * self.item.varaints.price

class OrderItemSerializer(serializers.ModelSerializer):    
    order = serializers.PrimaryKeyRelatedField(read_only=True)
    price = serializers.ReadOnlyField()
    class Meta:
        model = OrderItem
        fields = ['id','order','orderItem_ID','item','order_variants', 'quantity','order_item_status','price']
        # depth = 1

Order Serializer 就像上面一样。它包括 OrderItemSerializer,如图所示:

class OrderSerializer(serializers.ModelSerializer):

    billing_details = BillingDetailsSerializer()
    order_items = OrderItemSerializer(many=True)
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
    class Meta:
        model = Order
        fields = ['id','user','ordered_date','order_status', 'ordered', 'order_items', 'total_price','billing_details']

订单总价计算更新。

这是我为 total_price 计算所做的,但我没有在 api 响应中得到 total_price 字段,但没有错误。

class Order(models.Model):     
.....#same fields as above

    @property
    def total_order_price(self):
        return sum([_.price for _ in self.order_items_set.all()])

我在 OrderItem 模型中使用了价格函数,我的 OrderItem 实例是 order_items。什么问题??

【问题讨论】:

  • 将订单类中的价格函数定义为类方法。
  • 我已经用我尝试过的东西更新了我的问题。我已经将函数放在 Model 类中,但它说要从函数调用中传递 self 。我也必须把self = somthing。但我不知道该放什么。
  • 在你的问题中,你已经在类之外定义了价格函数。
  • 是的,但我尝试将其放入类中并得到相同的错误。
  • 您的 price(self) 方法应该在 OrderItem 类中。由于该方法位于类之外,因此它期望传递 self 参数。并且还将OrderItem类中属性total_item_price 的参数default=price()更改为default=price

标签: django api django-rest-framework save postman


【解决方案1】:

试试这个

class Order(models.Model):
    """Stores the details of the order"""

    user: User = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
    ordered_date = models.DateTimeField(auto_now_add=True)
    ordered = models.BooleanField(default=False)
    # billing_details = models.OneToOneField('BillingDetails',on_delete=models.CASCADE,null=True,blank=True,related_name="order")

    def __str__(self) -> str:
        return self.user.email

    @property
    def total_price(self) -> int:
        """
        Dropped the total price field and created it as property
        This is not the best practice, I am leaving that as practice for you :)
        """
        return sum([_.total_item_price for _ in self.orderitem_set.all()])


class OrderItem(models.Model):
    """Order Item stores the details of the each order item"""

    orderItem_ID: str = models.CharField(
        max_length=12, editable=False, default=id_generator
    )
    order: Order = models.ForeignKey(
        Order,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
        related_name="order_items",
    )
    item: Product = models.ForeignKey(
        Product, on_delete=models.CASCADE, blank=True, null=True
    )
    order_variants: Variants = models.ForeignKey(
        Variants, on_delete=models.CASCADE, blank=True, null=True
    )
    quantity: int = models.IntegerField(default=1)
    price = models.PositiveIntegerField()

    @property
    def total_item_price(self):
        """
        Calculates total item price for the item
        Here you can also add additional logics such as
        taxes per item etc

        """

        return self.price * self.quantity

    ORDER_STATUS = (
        ("To_Ship", "To Ship"),
        ("Shipped", "Shipped"),
        ("Delivered", "Delivered"),
        ("Cancelled", "Cancelled"),
    )
    order_item_status = models.CharField(
        max_length=50, choices=ORDER_STATUS, default="To_Ship"
    )

【讨论】:

  • 您不认为price 方法应该在OrderItem 类中,因为Order 类没有quantityitem 中需要的属性@987654327 @方法。
  • 啊。 @Kishore,很好,我没有通过代码。让我更新答案。
  • 你好@VJMagar我累了你的代码,但它是我的post call api,我得到的结果是price = 0。虽然没有错误,订单已创建。我查了一下商品价格,是500。
  • 所以,total_item_price 不需要保存在数据库中??不同的产品来自不同的供应商,所以我想我将来也需要total_item_price。
  • 另外,我看到你也从 Order 模型中删除了 total_price。
【解决方案2】:

这段代码终于为 OrderItem 价格计算工作了:

class OrderItem(models.Model): 
.....#fields same as above
    #total_item_price = models.PositiveIntegerField(blank=True,null=True,default=0)

    ORDER_STATUS = (
        ('To_Ship', 'To Ship',),
        ('Shipped', 'Shipped',),
        ('Delivered', 'Delivered',),
        ('Cancelled', 'Cancelled',),
    )
    order_item_status = models.CharField(max_length=50,choices=ORDER_STATUS,default='To_Ship')

    @property
    def price(self):
        total_item_price = self.quantity * self.order_variants.price
        return total_item_price

变体中有错字。另外,我应该使用 order_variants 而不是 item.variants,因为 item 有很多变体,但用户只选择了一个具有唯一价格的变体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-06
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 2023-02-06
    • 1970-01-01
    相关资源
    最近更新 更多