我有这两个 Django 模型:
class Listing(models.Model):
...
price = models.DecimalField(
decimal_places=2,
max_digits=20,
default=0,
validators=[MinValueValidator(Decimal('0.01'))]
)
class Bid(models.Model):
...
listing = models.ForeignKey(Listing, default=None, on_delete=models.CASCADE)
amount = models.DecimalField(
decimal_places=2,
max_digits=20,
default=0
validators=[MinValueValidator(Decimal(listing.price))]
)
我想验证一下
Bid.amount > Bid.listing.price
。
当我尝试在
MinValueValidator
的 django.core.validators
的帮助下执行此操作时,我收到此错误:
validators=[MinValueValidator(Decimal(listing.price))])
^^^^^^^^^^^^^
AttributeError: 'ForeignKey' object has no attribute 'price'
我还尝试使用
listing.price
属性引用 self
并收到以下错误:
validators=[MinValueValidator(Decimal(self.listing.price))])
^^^^
NameError: name 'self' is not defined
我知道一旦提交了 Model.Form,我就可以在“views.py”中检查上述条件,但我想知道是否有一种方法可以使用 Django Validators 来验证它。
如有任何帮助,我们将不胜感激!
我通过在
forms.py
中创建自定义验证器来解决这个问题:
from .models import Listing, Bid
from django.forms import ModelForm
from decimal import Decimal
from django.core.exceptions import ValidationError
class BidForm(ModelForm):
class Meta():
model = Bid
fields = ["amount"]
def clean_amount(self):
amount = self.cleaned_data["amount"]
if Decimal(amount) <= Decimal(self.instance.listing.price):
raise ValidationError("The Bid must exceed the Price")
return amount
然后,在
views.py
:
from django.http import HttpResponseRedirect
from .models import Listing
from .forms import BidForm
from decimal import Decimal
def listing(request, listing_id):
listing = Listing.objects.get(pk=listing_id)
if request.method == "POST":
form = BidForm(request.POST)
form.instance.holder, form.instance.listing = request.user, listing
if form.is_valid():
form.save()
Listing.objects.filter(pk=listing_id).update(price=Decimal(request.POST["amount"]))
return HttpResponseRedirect(f"/listing/{listing_id}", {"form":form, "listing":listing})
else:
form = BidForm()
return render(request, "auctions/listing.html", {"form": form, "listing": listing})
我没有验证 Django Model 的字段,而是借助
clean_amount()
方法验证 ModelForm 提交。根据 Django 文档:
此方法执行特定于该特定属性的任何清理,与它所属的字段类型无关。
我希望这个答案能帮助别人。