如何在 Django 3.1 ModelForm 中动态设置内置 MinValueValidator 的 limit_value
How to dynamically set the limit_value of the build-in MinValueValidator inside a Django 3.1 ModelForm
我正在尝试在 Django 3.1 ModelForm 中动态设置内置 MinValueValidator 的 limit_value。下面的代码适用于固定的 limit_value 10(参见 views.py 中的第 21 行)。
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="bids")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="bids")
bid = models.DecimalField(decimal_places=2, max_digits=9)
views.py
from django.contrib.auth import authenticate, login, logout
from django.db import IntegrityError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django import forms
from .models import User, Listing, Category, Bid
from django.db.models import Max
from decimal import Decimal, DecimalException
from django.core.validators import MaxValueValidator, MinValueValidator
from django.core.exceptions import ValidationError
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
widgets = {
'user': forms.HiddenInput(),
'listing': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['user'].show_hidden_initial=True
self.fields['listing'].show_hidden_initial=True
self.fields['bid'].validators=[MinValueValidator(10)]
def clean(self):
if 'user' in self.changed_data or 'listing' in self.changed_data:
raise forms.ValidationError('Non editable field have changed!')
return self.cleaned_data
def index(request):
listings = Listing.objects.all()
return render(request, "auctions/index.html", {
"listings" : listings,
})
def listing(request, listing_id):
if request.method == 'POST':
data = request.POST
form = NewBidForm(data)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
form = NewBidForm(initial={'listing':listing,'user':request.user})
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
然而,当我在 ModelForm 实例化期间尝试通过 'my_arg' 将变量传递给 NewBidForm 的 init 方法时,我收到以下错误消息:
- 按键错误:'my_arg'
- 列表项 AttributeError:'NewBidForm' 对象没有属性“_errors”
下面是views.py
中修改后的代码
views.py
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
widgets = {
'user': forms.HiddenInput(),
'listing': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
my_arg = kwargs.pop('my_arg')
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['user'].show_hidden_initial=True
self.fields['listing'].show_hidden_initial=True
self.fields['bid'].validators=[MinValueValidator(my_arg)]
def clean(self):
if 'user' in self.changed_data or 'listing' in self.changed_data:
raise forms.ValidationError('Non editable field have changed!')
return self.cleaned_data
def index(request):
listings = Listing.objects.all()
return render(request, "auctions/index.html", {
"listings" : listings,
})
def listing(request, listing_id):
if request.method == 'POST':
data = request.POST
form = NewBidForm(data)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
form = NewBidForm(initial={'listing':listing,'user':request.user}, my_arg=12)
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
谁能告诉我如何在实例化期间将变量传递给 ModelForm 中的 init 方法?
在运行时更改 MinValueValidator 中构建的 limit_value 的替代解决方案也是可以接受的。但是,我不喜欢在 ModelForm 中重新定义 fromfields。
BR,康拉德
下面的代码示例显示了我的问题的答案。
模型形式class
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
def __init__(self, *args, **kwargs):
my_arg = kwargs.pop('my_arg')
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['bid'].validators=[MinValueValidator(my_arg)]
然后每次实例化表单对象时,请确保像这样传入 my_variable
:
form = NewBidForm(my_arg=my_variable)
我的错误是在我的代码中的两个位置实例化了表单,但只在其中一个实例中传递了参数。
我
我正在尝试在 Django 3.1 ModelForm 中动态设置内置 MinValueValidator 的 limit_value。下面的代码适用于固定的 limit_value 10(参见 views.py 中的第 21 行)。
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="bids")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="bids")
bid = models.DecimalField(decimal_places=2, max_digits=9)
views.py
from django.contrib.auth import authenticate, login, logout
from django.db import IntegrityError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django import forms
from .models import User, Listing, Category, Bid
from django.db.models import Max
from decimal import Decimal, DecimalException
from django.core.validators import MaxValueValidator, MinValueValidator
from django.core.exceptions import ValidationError
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
widgets = {
'user': forms.HiddenInput(),
'listing': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['user'].show_hidden_initial=True
self.fields['listing'].show_hidden_initial=True
self.fields['bid'].validators=[MinValueValidator(10)]
def clean(self):
if 'user' in self.changed_data or 'listing' in self.changed_data:
raise forms.ValidationError('Non editable field have changed!')
return self.cleaned_data
def index(request):
listings = Listing.objects.all()
return render(request, "auctions/index.html", {
"listings" : listings,
})
def listing(request, listing_id):
if request.method == 'POST':
data = request.POST
form = NewBidForm(data)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
form = NewBidForm(initial={'listing':listing,'user':request.user})
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
然而,当我在 ModelForm 实例化期间尝试通过 'my_arg' 将变量传递给 NewBidForm 的 init 方法时,我收到以下错误消息:
- 按键错误:'my_arg'
- 列表项 AttributeError:'NewBidForm' 对象没有属性“_errors”
下面是views.py
中修改后的代码views.py
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
widgets = {
'user': forms.HiddenInput(),
'listing': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
my_arg = kwargs.pop('my_arg')
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['user'].show_hidden_initial=True
self.fields['listing'].show_hidden_initial=True
self.fields['bid'].validators=[MinValueValidator(my_arg)]
def clean(self):
if 'user' in self.changed_data or 'listing' in self.changed_data:
raise forms.ValidationError('Non editable field have changed!')
return self.cleaned_data
def index(request):
listings = Listing.objects.all()
return render(request, "auctions/index.html", {
"listings" : listings,
})
def listing(request, listing_id):
if request.method == 'POST':
data = request.POST
form = NewBidForm(data)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
form = NewBidForm(initial={'listing':listing,'user':request.user}, my_arg=12)
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
谁能告诉我如何在实例化期间将变量传递给 ModelForm 中的 init 方法? 在运行时更改 MinValueValidator 中构建的 limit_value 的替代解决方案也是可以接受的。但是,我不喜欢在 ModelForm 中重新定义 fromfields。
BR,康拉德
下面的代码示例显示了我的问题的答案。
模型形式class
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
def __init__(self, *args, **kwargs):
my_arg = kwargs.pop('my_arg')
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['bid'].validators=[MinValueValidator(my_arg)]
然后每次实例化表单对象时,请确保像这样传入 my_variable
:
form = NewBidForm(my_arg=my_variable)
我的错误是在我的代码中的两个位置实例化了表单,但只在其中一个实例中传递了参数。 我