Рекомендации по доступу к отправленным данным формы в django для использования перед сохранением в базе данных - PullRequest
0 голосов
/ 28 октября 2019

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

Models.py

class Invoice(models.Model):
    invoice_status_choices = [
        ('1', 'Pending'),
        ('2', 'Paid'),
        ('3', 'Cancelled')
    ]
    invoice_number = models.CharField(max_length = 500, default = increment_invoice_number, null = True, blank = True)
    description = models.CharField(max_length=100, blank=True)
    customer = models.ForeignKey(User, on_delete=models.CASCADE)
    payment_date = models.DateTimeField(blank=True, null=True)
    paid_amount = models.DecimalField(max_digits=15, decimal_places=2, default=0)
    invoice_status = models.IntegerField(choices=invoice_status_choices, default=1)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return str(self.invoice_number)


class InvoiceItem(models.Model):
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE)
    listing = models.ForeignKey('listings.Listing', on_delete=models.CASCADE)
    payment_type = models.ForeignKey('SubscriptionType', on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=6, decimal_places=2)
    quantity = models.IntegerField(default=1)

    def __str__(self):
        return f'{self.invoice.invoice_number} Items'


class SubscriptionType(models.Model):
    subscription_type = models.CharField(max_length=20)
    frequency = models.PositiveIntegerField()
    period = models.ForeignKey(PeriodNames, on_delete=models.CASCADE)
    rate = models.DecimalField(max_digits=6, decimal_places=2, default=0)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.subscription_type

Вот мнение, с которым мне нужна помощь. Обеспокоенность вызывает первая функция: get_invoice_item_amount. Функции полного представления:

view.py

def get_invoice_item_amount(payment_type):
    subscription_type = SubscriptionType.objects.get(id=payment_type)
    amount = subscription_type.rate
    return amount


@login_required
def create_invoice(request):
    """
    Allows a user to select list items.
    """
    user = request.user
    invoice_form = InvoiceForm()
    InvoiceItemFormset = inlineformset_factory(Invoice, InvoiceItem, form=InvoiceItemForm, extra=1)

    if request.method == 'POST':
        invoice_form = InvoiceForm(request.POST)
        formset = InvoiceItemFormset(request.POST, request.FILES)
        if invoice_form and formset.is_valid():
            # try:
            #     with transaction.atomic():
            #
            # except IntegrityError: #If the transaction failed
            #     messages.error(request, 'There was an error creating an invoice.')
                # return redirect(reverse('profile-settings'))
            # return redirect("my_property_detail", property.id)
            invoice = invoice_form.save(commit=False)
            invoice.customer = request.user
            invoice_data = invoice.save()

            for f in formset:
                # amount = get_invoice_item_amount(f.cleaned_data['payment_type'].id)
                invoice_item = InvoiceItem(
                                invoice=invoice,
                                listing=f.cleaned_data['listing'],
                                quantity=f.cleaned_data['quantity'],
                                payment_type=f.cleaned_data['payment_type'],
                                amount = get_invoice_item_amount(f.cleaned_data['payment_type'].id))
                invoice_item.save()
            print("Data saved successfully!")
        else:
            print("Failed to validate")

    else:
        form = InvoiceForm()
        formset = InvoiceItemFormset()
        for n in formset:
            n.fields['listing'].queryset = Listing.objects.filter(status=False, listing_owner=user)

    context = {
        'form': invoice_form,
        'formset': formset
    }

    return render(request, 'payments/create_invoice.html', context)

Я вызываю функцию внутри набора форм перед сохранением invoice_item. Это правильный путь? Или есть рекомендуемый способ сделать это.

1 Ответ

1 голос
/ 28 октября 2019

Это вполне допустимый вариант использования для cleaned_data. Доступ к cleaned_data не проблема вообще.

Имейте в виду, что если вы каким-либо образом измените значения внутри cleaned_data, это может привести к ошибкам при сохранении экземпляра на его основе.

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

...