Можно ли наложить ограничение на форму, чтобы пользователь не мог вводить больше, чем значение в БД в django - PullRequest
0 голосов
/ 27 апреля 2019

У меня есть форма, созданная в django, и я хочу наложить на нее ограничение, так что сумма_проданности должна быть> 0 или

Форма продажи HTML ниже

<div>
    <form method="POST">
        {% csrf_token %}
        <fieldset class ="form-group">
            <legend class="border-bottom mb-4">Enter Sale</legend>
            {{ form|crispy }}
        </fieldset>
        <div class="form-group">
            <button class ="btn btn-outline-info" type="submit">Enter</button>
        </div>
    </form>
</div>

Форма продажи модели ниже

class SaleForm(forms.ModelForm):

    amount_sold = forms.IntegerField()
    total_price_sold = forms.DecimalField()
    date_sold = forms.DateField(
        widget=forms.TextInput(
            attrs={'type': 'date'}
        )
    )
    note = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Keep a Note?'}))

    class Meta:
        fields = ['date_sold', 'amount_sold', 'total_price_sold', 'note']
        model = Sale

Продажа модели ниже


class Sale(models.Model):
    amount_sold = models.IntegerField()
    total_price_sold = models.DecimalField(max_digits=8, decimal_places=2)
    date_sold = models.DateTimeField(default=timezone.now)
    note = models.TextField(default="")
    transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE, related_name="sales")
    amount_per_coin_sold = models.DecimalField(max_digits=8, decimal_places=2, editable=False)

    def __str__(self):
        return str(self.pk)+','+str(self.amount_sold) + ', '+self.note

    def save(self, *args, **kwargs):
        self.amount_per_coin_sold = self.total_price_sold / self.amount_sold
        super(Sale, self).save(*args, **kwargs)

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

    @property
    def profit_loss(self):
        return (self.amount_per_coin_sold - self.transaction.amount_per_coin) * self.amount_sold

    @property
    def profit_loss_percent(self):
        value = ((self.total_price_sold - (self.transaction.amount_per_coin * self.amount_sold))/self.total_price_sold) * 100
        return round(value, 1)    

Модель транзакции ниже / где я получаю значение coins_remaining от

class Transaction(models.Model):
    currency = models.CharField(max_length=20)
    amount = models.IntegerField()
    total_price = models.DecimalField(max_digits=8, decimal_places=2)
    date_purchased = models.DateTimeField()
    note = models.TextField(default="")
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    amount_per_coin = models.DecimalField(max_digits=8, decimal_places=2, editable=False)

    def save(self, *args, **kwargs):
        self.amount_per_coin = self.total_price / self.amount
        super(Transaction, self).save(*args, **kwargs)

    def __str__(self):
        return str(self.pk)+','+self.currency + ', '+str(self.amount)

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

    @property
    def coins_remaining(self):
        return self.amount - sum(self.sales.all().values_list('amount_sold', flat=True))

    @property
    def coin_value(self):
        return get_currency_price(self.currency)

    @property
    def total_value(self):
        value = self.coin_value * self.amount
        return round(value, 2)

    @property
    def profit_loss(self):
        value = float(self.total_value) - float(self.total_price)
        return round(value, 2)

    @property
    def profit_loss_percent(self):
        value = ((float(self.total_value) - float(self.total_price))/self.total_value)*100
        return round(value, 1)    

1 Ответ

0 голосов
/ 29 апреля 2019

Использование метода last () вернет последний объект в наборе запросов. Если порядок не указан, то порядок по умолчанию будет выполняться на основе идентификатора. Я предполагаю, что вы хотите amount_sold < last_transaction.coins_remaining

Для проверки определенного поля в форме django вам нужно написать собственный метод. Соглашение - для любого поля формы field1 имя метода будет clean_field1

В вашем случае ваша форма должна выглядеть следующим образом для удовлетворения желаемой проверки -

class SaleForm(forms.ModelForm):

    amount_sold = forms.IntegerField()
    total_price_sold = forms.DecimalField()
    date_sold = forms.DateField(widget=forms.TextInput(
        attrs={'type': 'date'}))
    note = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Keep  a Note?'}))

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')
        super(SaleForm, self).__init__(*args, **kwargs)

    class Meta:
        fields = ['date_sold', 'amount_sold', 'total_price_sold', 'note']
        model = Sale

    def clean_amount_sold(self):
        data = self.cleaned_data['amount_sold']

        if data <= 0:
            raise forms.ValidationError('Invalid Value')

        transaction = Transaction.objects.filter(owner=self.user).last()
        if data >= transaction.coins_remaining:
            raise forms.ValidationError('Invalid Value')

        return data

По вашему мнению, создайте экземпляр формы следующим образом -

if request.method == 'POST':
    form = SaleForm(request.POST, user=request.user)
else:
    form = SaleForm(user=request.user)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...