1

Я создаю генератор цитат в Django. Я хочу рассчитать общее количество всех предметов, вставить их в поле и сохранить.Как добавить поля из многоголовочного поля в django?

модели заключаются в следующем:

from django.db import models 
from django.core.urlresolvers import reverse 


class Product(models.Model): 
    product_name = models.CharField(max_length=50) 
    product_description = models.CharField(max_length=200) 
    product_price = models.IntegerField(max_length=4) 

    def __unicode__(self): 
     return self.product_name 

    class Meta: 
     ordering = ('product_name',) 


class Quote(models.Model): 
    quotee_name = models.CharField("Name", max_length=40) 
    quotee_email = models.EmailField("Email") 
    quotee_phone = models.IntegerField("Phone", max_length=10) 
    quotee_products = models.ManyToManyField(Product, verbose_name="Products") 
    quotee_total = models.IntegerField("Estimate", max_length=10, null=True, blank=True) 

    def __unicode__(self): 
     return self.quotee_email 

    class Meta: 
     ordering = ('quotee_email',) 

    def get_absolute_url(self): 
     return reverse('quote-detail', kwargs={'pk': self.pk, }) 

Я не использую это через администратора, так вот forms.py:

from django import forms 
from django.forms import CheckboxSelectMultiple 


from InternalDusettenet.apps.quotes.models import Quote 


class QuoteForm(forms.ModelForm): 

    class Meta: 
     model = Quote 
     fields = ('quotee_name', 'quotee_email', 'quotee_phone', 
        'quotee_products') 
     widgets = { 
      'quotee_products': CheckboxSelectMultiple(attrs={'size': 10}), 
     } 

А вот views.py файл. Я установил, чтобы он просто сохранил '1' в форме, чтобы он фактически сохранялся. Я хочу заменить «1» на функцию, которая возвращает значение «Product.product_price» для каждого, выбранного в «Quote.quotee_products». Когда я создаю цитату, я выбираю продукты, и это дает мне сумму всех выбранных полей «PRODUCT_PRICE», связанных с выбранными продуктами:

from django.views.generic.edit import CreateView, UpdateView, DeleteView 
from django.views.generic import ListView, DetailView 
from django.shortcuts import Http404, get_object_or_404 

from InternalDusettenet.apps.quotes.models import Quote 
from InternalDusettenet.apps.quotes.forms import QuoteForm 


class QuoteCreate(CreateView): 
    model = Quote 
    template_name = "quotes/quote_create_edit.html" 
    fields = ['quotee_name', 'quotee_email', 'quotee_phone', 
       'quotee_products'] 
    form_class = QuoteForm 

    def form_valid(self, form): 
     form.instance.quotee_total = 1 
     return super(QuoteCreate, self).form_valid(form) 


class QuoteList(ListView): 
    model = Quote 
    template_name = "quotes/quote_list.html" 


class QuoteDetail(DetailView): 
    model = Quote 
    template_name = "quotes/quote_detail.html" 


class QuoteUpdate(UpdateView): 
    model = Quote 
    template_name = "quotes/quote_create_edit.html" 
    fields = ['quotee_name', 'quotee_email', 'quotee_phone', 
       'quotee_products', 'quotee_total'] 
    form_class = QuoteForm 


class QuoteDelete(DeleteView): 
    model = Quote 
    success_url = '/' 
    template_name = "quotes/quote_delete.html" 

Я прочитал Джанго DOCS много раз, но я понятия не имею, как сделать это один простой предмет.

Я использую Django 1.7 и Python 2.7.

ответ

2

Нет причин, чтобы сохранить его в базе данных, просто сделать это метод или свойство Quote объекта:

class Quote(models.Model): 
    ... 
    def quotee_total(self): 
     return self.quotee_products.aggregate(total=models.Sum('product_price'))['total'] 

В случае необходимости, вы можете кэшировать значение и заполнить кэш на первоначальный запрос:

class Quote(models.Model): 
    ... 
    def quotee_total(self): 
     if not hasattr(self, '_quotee_total'): 
      self._quotee_total = self.quotee_products.aggregate(total=models.Sum('product_price'))['total'] 
     return self._quotee_total 

quotes = Quote.objects.annotate(_quotee_total=models.Sum('quotee_products__product_price')) 

Вы можете, конечно, сохранить это значение в базе данных, но есть небольшая причина. Если вы беспокоитесь о производительности, лучше всего использовать кеширование, чем при сохранении ценности в базе данных.

+0

Использование агрегата(), вероятно, немного более эффективно, чем я предлагал. NB: Функция Sum() не следует путать с встроенной функцией функции python sum(). Используйте 'from django.db.models import Sum' –

+1

@ HåkenLid Предназначен для написания' models.Sum', поскольку 'models' уже импортирован: P Это должно быть достаточно ясно, но спасибо за примечание. – knbk

+0

Ничего себе. Так много комментариев. Большое спасибо всем вам. Для этого единственная причина, по которой мне нужно видеть цитаты, находится в представлении. Его не нужно хранить в db. Мне просто нужна полная готовность, когда я запрашиваю эту конкретную цитату. Извините за то, что вы новичок, но если вы сделали такой способ, как в первом примере, как мне получить возможность называть это с помощью вида/шаблона? Снова. жаль, что не понял. лол. Я, как правило, ОЧЕНЬ хорошо разбираюсь в вещах, но это меня просто сбивает с толку. Благодарю. – RoninDusette

1

Я бы не вычислил общее количество в виде. Это имеет смысл как метод.

class Quote(models.Model): 

    def calculate_quotee_total(self): 
     return sum(product.product_price for product in self.quotee_products.all()) 

    def __save__(self): 
     self.quotee_total = self.calculate_quotee_total() 
     super(Quote, self).save() 

Quote.quotee_total также можно рассчитать по мере необходимости, вместо того, чтобы сохранить его в БД.

class Quote(models.Model): 

    @property 
    def quotee_total(self): 
     return sum(product.product_price for product in self.quotee_products.all()) 
Смежные вопросы