Как добавить значение из поля ввода пользователя в библиотеке django imoirt-export?
У меня есть модель Product
и Calculator, который связан с каждым элементом в модели Product
.
Я пытаюсь добиться того, чтобы позволить пользователю вставить количество единиц товара и на основе этого количества рассчитать общую цену в файле Excel, который будет экспортирован, когда пользователь нажмет кнопку Calculate.
Вопросы:
- Как добавить значение, введенное пользователем в поле ввода, в файл
cost_calculator.xlsx
и на основе этого значения рассчитать общую цену? - Как я могу добавить
unit_hours
свойство изCostCalculator
модели в мой экспортированный файл? Я успешно добавил его на странице администратора, и оно показывает мне правильный результат, но когда я добавляю его к полям в модели ресурса, я получаюKeyError
. - Какой лучший подход для вычисления total_price и отображения его в Excel в моем случае? Формула выглядит следующим образом:
number_of_units * rate * margin = total_price
. Должен ли я поместить ее вform_valid
вProductDetailView
или вExportData
в представлении или, может быть, я не должен отделять кнопку экспорта в отдельное представление, а добавить ее вform_valid
. - Возможно ли объединить кнопки Send и Calculate в одну, чтобы если пользователь нажмет на 1 кнопку, она отправляла значение пользователя, рассчитывала и экспортировала единицы_часов и общую_цену?
Предположения
- Мне нужно иметь калькулятор затрат в DetailView.
- Компоненты услуг должны быть разделены, потому что будет много одинаковых компонентов, которые я буду подключать к продуктам.
Ниже приведен мой код:
models.py
class Product(models.Model):
title = models.CharField(max_length=400, default='')
class CalculatorServiceComponent(models.Model):
service = models.CharField(max_length=500, default='', blank=True)
product = models.ManyToManyField(Product, related_name='calculator_service_component_product', blank=True, default='-')
component = models.CharField(max_length=500, default='', blank=True)
class CostCalculator(models.Model):
related_product = models.ForeignKey(Product, on_delete=models.CASCADE, null=True, blank=True, related_name='related_product')
title_component = models.ForeignKey(CalculatorServiceComponent, on_delete=models.CASCADE, default=1)
weights = models.FloatField(default=0.0)
total_hours = models.IntegerField(default=0)
number_of_units = models.IntegerField(default=0) # this is the field that user will be adding and based on this value total_price will be calculated
rate = models.IntegerField(default=0)
margin = models.FloatField(default=0.0)
def _unit_h(self):
return self.weights * self.total_hours
unit_hours = property(_unit_h)
forms.py
class CalculatorForm(forms.ModelForm):
number_of_units = forms.IntegerField(help_text='Only numeric values are allowed.', min_value=0)
class Meta:
model = CostCalculator
fields = ('number_of_units',)
resources.py
class CostCalculatorResource(resources.ModelResource):
class Meta:
model = CostCalculator
fields = ('id', 'title_component__service', 'related_product__title', 'title_component__component', 'weights', 'weights', 'total_hours', 'unit_hours')
views.py
class ProductDetailView(LoginRequiredMixin, FormMixin, DetailView):
login_url = 'login'
redirect_field_name = 'login'
template_name = 'ProductDetailView.html'
model = Product
form_class = CalculatorForm
date_field = "publish"
month_format = "%m"
def get_context_data(self, **kwargs):
context = super(ProductDetailView, self).get_context_data(**kwargs)
form = CalculatorForm(initial={'obj': self.object})
context['form'] = form
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
title_component = CostCalculator.objects.filter(related_product__slug=self.kwargs['slug'])
unit_hours = form.cleaned_data['weights'] * form.cleaned_data['total_hours'] # how can I pass this to my ExportData class?
form.save()
return super(ProductDetailView, self).form_valid(form)
def get_success_url(self):
return reverse('product', kwargs={'slug': self.kwargs['slug']})
class ExportData(LoginRequiredMixin, View):
def get(self, _unit_h, *args, **kwargs ):
filter_qs = CostCalculator.objects.filter(related_product__slug=self.kwargs['slug'])
dataset = CostCalculatorResource().export(filter_qs)
response = HttpResponse(dataset.xlsx, content_type="xlsx")
response['Content-Disposition'] = 'attachment; filename=cost_calculator.xlsx'
return response
ProductDetailView.html
{% for component in calculator_components.all %}
<div class="collapse py-2" id="component{{component.id}}">
<h3 class="fw-bold">{{component.title_component}}:</h3>
<form method="post" enctype="multipart/form-data" class="w-25">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn bg-hubble">Send</button>
</form>
</div>
{% endfor %}
<a href="{% url 'export_calculator' product.slug %}"><button type="button" class="btn">Calculate</button></a>