简体   繁体   English

如何使用相同模型的其他字段的值在Django模型中创建一个字段?

[英]How to create a field in django model using values of other fields of same model?

I wants to create a field name: total which have the total price of all the products*quqantity. 我想创建一个字段名称: total ,其中包含所有产品的总价格*数量。 What I want is how can I do total = price*quantity in django model. 我想要的是如何在Django模型中total = price*quantity As you can see there can be more than one products. 如您所见,可能有不止一种产品。
I have join the OderItem model with Order through tabularinline. 我通过tabularinline将OderItem模型与Order一起加入。

在此处输入图片说明

 class OrderItemInline(admin.TabularInline): model = OrderItem raw_id_fields = ['product'] class OrderAdmin(admin.ModelAdmin): list_display = ['id','name', 'mobile_no','address','status', 'created'] list_editable = ['status'] list_per_page = 15 list_filter = ['status'] search_fields = ('id',) inlines = [OrderItemInline] admin.site.register(Order, OrderAdmin) 
 class Order(models.Model): name = models.CharField(max_length=60) email = models.EmailField(max_length=60,default=None, blank=True) mobile_no = models.CharField(max_length=13, default=None) address = models.CharField(max_length=150) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) status_choices = ( ('In Queue', 'In Queue'), ('Processing', 'Processing'), ('Ready', 'Ready'), ('Delivered', 'Delivered'), ('Paid', 'Paid'), ('Cancelled', 'Cancelled'), ) status = models.CharField(max_length=15, choices=status_choices, default=status_choices[0][0]) class Meta: ordering = ('created', ) def __str__(self): return 'Order {}'.format(self.id) def get_total_cost(self): return sum(item.get_cost() for item in self.items.all()) class OrderItem(models.Model): order = models.ForeignKey(Order, related_name='items', on_delete=models.CASCADE) product = models.ForeignKey(MenuVariant, related_name='order_items', on_delete=models.CASCADE, default=None) size = models.CharField(max_length=20, default=None) price = models.DecimalField(max_digits=10, decimal_places=2) quantity = models.PositiveIntegerField(default=1) # total = models.DecimalField(max_digits=10, decimal_places=2,default=0) def __str__(self): return '{}'.format(self.id) def get_cost(self): return self.price * self.quantity 

You can get the total price for an Order directly with a database query, so there's no need to save it in the database: 您可以直接通过数据库查询获取Order的总价,因此无需将其保存在数据库中:

from django.db.models import Sum, F, FloatField
orders = Order.objects.annotate(total=Sum(F('items__quantity')*F('items__price'), output_field=FloatField()))

This adds a total field to each result of the query. 这将向每个查询结果添加一个total字段。 So then: 因此:

price_of_first_order = orders.first().total

And if you want to display the total for an order in the admin, subclass the ModelAdmin and add get_total_cost to the readonly_fields , as explained here : 如果你想显示的总的order在管理,子类ModelAdmin并添加get_total_costreadonly_fields ,为解释在这里

A read-only field can not only display data from a model's field, it can also display the output of a model's method or a method of the ModelAdmin class itself. 只读字段不仅可以显示模型字段中的数据,还可以显示模型方法的输出或ModelAdmin类本身的方法。 This is very similar to the way ModelAdmin.list_display behaves. 这与ModelAdmin.list_display的行为非常相似。

While I, like dirkgroten don't quite see the point of saving the value in a model field, you could add a field total=models.IntegerField(null=True, blank=True) to your Order model and use a post_save to update the value. 虽然像dirkgroten一样,我不太明白将值保存在模型字段中的意义,但是您可以在Order模型中添加字段total=models.IntegerField(null=True, blank=True)并使用post_save更新价值。

So, since you already have a get_total_cost() we can do something like: 因此,由于您已经拥有get_total_cost()我们可以执行以下操作:

def order_pre_save(sender, instance, **kwargs):
    instance.total_cost = instance.get_total_cost()

pre_save.connect(order_pre_save, sender=Order)

EDIT: As dirkgroten points out you'll need the post_save on the OrderItem : 编辑:正如dirkgroten指出的那样,您需要在OrderItempost_save

def order_item_pre_save(sender, instance, **kwargs):
    instance.order.total_cost = instance.order.get_total_cost()
    instance.order.save()

post_save.connect(order_item_pre_save, sender=OrderItem)

And you'd also need to update the value on delete: 而且您还需要在delete时更新值:

def order_item_pre_delete(sender, instance, **kwargs):
    instance.order.total_cost = instance.order.get_total_cost() - instance.get_cost()
    instance.order.save()

post_delete.connect(order_item_pre_delete, sender=OrderItem)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用其他字段的值在 Django 模型中创建一个字段? - How to create a field in django model using values of other fields? 如何为 JSONField 创建一个 django 模型,该模型从同一个表中的其他字段中获取值? - How to create a django model for JSONField that takes values from other fields from the same table? 如何使用 model 中的其他字段初始化 Django 模型中的字段 - How to initialise a field in Django models using other fields in the model Django,根据在同一 model 中的其他字段中输入的值,将复合值分配给一个字段? - Django, assigning a composite value to one field depending upon values entered in other fields in same model? 更新模型字段和Django中的任何其他字段 - Update model field and any other fields in django 从其他字段计算的 Django 模型字段 - Django Model field calculated from other fields Django-模型字段为其他字段的总和 - Django - Model field to be the sum of other fields Django-如何在同一模型中基于另一个字段创建字段 - Django-How to create a field based on another field in the same model Django模型字段限制从其他模型字段中选择 - django model field limit choice from other model fields 如何使用第一个字段作为标签从具有3个字段的模型中创建Django表单,其余的作为无线电检查? - How can I create a Django form out of a Model with 3 fields using the first field as the label, the rest as radio checks?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM