Как создать поле в модели django, используя значения других полей?

У меня есть эта модель под названием Заказ, которая сохраняет информацию о пользователе, и другая модель под названием ЗаказатьЭлемент, которая сохраняет продукты, заказанные пользователем. Я присоединился к модели OrderItem с помощью Order, используя Tabular Inline. Теперь я хочу рассчитать общую цену, умножив цену и количество продукта (которые являются полями модели ЗаказатьЭлемент) и сохранить общую цену в модели Заказ, как показано на рисунке. Как создать поле в модели django, используя значения других полей?

Я задавал этот вопрос раньше, но не получил удовлетворительного ответа.

from django.contrib import admin
from .models import Order, OrderItem
from pizza_app.models import UserTypes
from django.db.models.signals import pre_save
from django.db.models import Sum, F, FloatField

class OrderItemInline(admin.TabularInline):
    model = OrderItem


class OrderAdmin(admin.ModelAdmin):
    list_display = ['id','name','total' ,'mobile_no','address','status', 'created']
    list_editable = ['status']
    list_per_page = 10
    list_filter = ['status']
    readonly_fields= ['total']
    search_fields = ('id','mobile_no','name',)
    inlines = [OrderItemInline]
   


    def get_form(self, request, obj=None, **kwargs):
        form = super(OrderAdmin,self).get_form(request, obj,**kwargs)
        form.base_fields['Assigned_to'].queryset = form.base_fields['Assigned_to'].queryset.filter(staff_status='Delivery Boy')
        return form

admin.site.register(Order, OrderAdmin)
from django.db import models
from pizza_app.models import MenuVariant
from django.urls import reverse
from django.db.models import Sum, F, FloatField
from pizza_app.models import UserTypes
# from django.contrib.auth.models import User
from django.db.models.signals import pre_save,post_save

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])
    
    total = models.DecimalField(max_digits=10,decimal_places=2,default=0)

    Assigned_to = models.OneToOneField(UserTypes, on_delete=models.CASCADE,default=None, blank=True, null=True)


    class Meta:
        ordering = ('created', )

    def __str__(self):
        return 'Order {}'.format(self.id)


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)
    size = models.CharField(max_length=20, default=None)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    quantity = models.PositiveIntegerField(default=1)


    def __str__(self):
        return '{}'.format(self.id)

@dirkgroten Я упомянул, что этот вопрос уже задавался мной, я не получил удовлетворительного ответа, я помню, что вы ответили на этот вопрос, но я не понял решение, которое вы дали. Я попросил объяснить, но ты не ответил

M_FarhanZia 09.04.2019 12:47

Я обновил свой ответ, сказав вам добавить поле только для чтения в ваш ModelAdmin. Это то же самое, что и ответ, данный ниже @ruddra. Ваш вопрос просит нас написать код для вас, что не является целью SO. Вы должны хотя бы показать нам, что вы пытались отобразить в админке, чтобы мы могли понять, почему это не работает.

dirkgroten 09.04.2019 12:56
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
1 173
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вместо того, чтобы создавать поле модели, вы можете создать метод внутри OrderAdmin для генерации итогов во время выполнения. Потом показать в админке. Так:

from django.db.models import Sum, F, ExpressionWrapper, DecimalField


class OrderAdmin(admin.ModelAdmin):
    list_display = ['id','name','order_total' ,'mobile_no','address','status', 'created']
    list_editable = ['status']
    list_per_page = 10
    list_filter = ['status']
    readonly_fields= ['order_total']
    search_fields = ('id','mobile_no','name',)
    inlines = [OrderItemInline]

    def order_total(self, obj):
         return obj.items.annotate(price_per_item=ExpressionWrapper(F('quantity')*F('price'), output_field=DecimalField())).aggregate(sum_total=Sum('price_per_item')).get('sum_total')

В методе total_order в OrderAdmin я вычисляю общую сумму этого заказа, используя агрегация. Затем я добавил total_order к fields и readonly_fields в OrderAdmin.

он дает эту ошибку Объект ExpressionWrapper не имеет атрибута "агрегат"

M_FarhanZia 09.04.2019 13:29

@M_FarhanZia Я пропустил скобку. Обновлен ответ

ruddra 09.04.2019 13:31

согласно dirkgroten, если я добавлю get_total в поля только для чтения, он покажет итог в администраторе. get_total - это функция в модели заказа, которая вычисляет итог. Но когда я добавляю get_total в поле только для чтения, он показывает пустое поле. Можете ли вы сказать, почему?

M_FarhanZia 09.04.2019 13:43

Я не уверен, что сказал @dirkgroten, но, возможно, вам нужно обновить набор запросов в OrderAdmin. Вероятно, что-то вроде этого: stackoverflow.com/a/12354293/2696165. Но я вырвался из контекста, так что это может быть что-то другое, я не уверен.

ruddra 09.04.2019 14:11

Другие вопросы по теме