[英]Django inlineformset_factory validators not working
Django version: 3.1.7 Django 版本:3.1.7
models.py模型.py
# custom validator
is_numeric = RegexValidator(r"^[0-9]*$", "Only numbers are allowed")
class Person(models.Model):
# all the boring fields
class PersonAddress(models.Model):
# all the boring fields
person = models.ForeignKey(
Person, null=True, on_delete=models.SET_NULL, related_name="person_address",
)
postcode = models.CharField(
blank=True, help_text="Include leading zero if exists",
max_length=10, validators=[is_numeric],
)
PersonAddress
will be the inlineformset of Person
as a Person can have multiple addresses PersonAddress
将是Person
的内联表单集,因为一个 Person 可以有多个地址
forms.py forms.py
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = "__all__"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
class PersonAddressForm(forms.ModelForm):
class Meta:
model = PersonAddress
fields = "__all__"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_method = "post"
PersonAddressFormSet = forms.models.inlineformset_factory(
Person, PersonAddress, form=PersonAddressForm, extra=1, can_delete=True,
)
# min_num, validate_min don't help even though I read from other stackoverflow solution
# PersonAddressFormSet = forms.models.inlineformset_factory(
# Person, PersonAddress, form=PersonAddressForm, extra=1, can_delete=True, min_num=1, validate_min=True,
# )
views.py视图.py
# Person CreateView
class PersonCreateView(SuccessMessageMixin, LoginRequiredMixin, CreateView):
model = Person
form_class = PersonForm
def get_context_data(self, **kwargs):
context = super(PersonCreateView, self).get_context_data(**kwargs)
if self.request.POST:
context["addresses"] = PersonAddressFormSet(self.request.POST, self.request.FILES)
else:
context["addresses"] = PersonAddressFormSet()
return context
# I think the problem is here, not 100% sure
def form_valid(self, form):
context = self.get_context_data()
addresses = context["addresses"]
self.object = form.save()
if addresses.is_valid():
addresses.instance = self.object
addresses.save()
# https://stackoverflow.com/questions/47476941/django-inlineformset-factory-error-messages-not-working
# my attempt, got this error
# TypeError: join() argument must be str, bytes, or os.PathLike object, not 'NoneType'
# else:
# return render(self.request, self.template_name, context)
return super(PersonCreateView, self).form_valid(form)
# PersonAddress CreateView
class PersonAddressCreateView(SuccessMessageMixin, LoginRequiredMixin, CreateView):
model = PersonAddress
form_class = PersonAddressForm
If I create a PersonAddress
object with postcode
that's non-numeric string, the PersonAddressCreateView
HTML form will return validation error.如果我使用非数字字符串的
postcode
创建PersonAddress
object,则PersonAddressCreateView
HTML 表单将返回验证错误。
But if I do the same thing in PersonCreateView
HTML form, there won't be any validation error.但是如果我在
PersonCreateView
HTML 表单中做同样的事情,就不会有任何验证错误。 Person
object will be created, PersonAddress
won't be created as the postcode
is invalid.将创建
Person
PersonAddress
,不会创建人员地址,因为postcode
无效。 What I am expecting is for the PersonCreateView
HTML form to show me the validation error instead of saving the form.我期待的是
PersonCreateView
HTML 表单向我显示验证错误而不是保存表单。
I think the solution should have something to do with the PersonCreateView
's form_valid
, but I am not sure.我认为解决方案应该与
PersonCreateView
的form_valid
,但我不确定。
Thanks in advance!提前致谢!
Indeed, the issue is in your form_valid
implementation.实际上,问题出在您的
form_valid
实现中。 To be exact, you are just doing nothing when the PersonAddressFormSet
is not valid.确切地说,当
PersonAddressFormSet
无效时,您什么也不做。 To fix that issue, try:要解决该问题,请尝试:
def form_valid(self, form):
context = self.get_context_data()
addresses = context["addresses"]
self.object = form.save()
if addresses.is_valid():
addresses.instance = self.object
addresses.save()
else:
return self.form_invalid(form)
return super(PersonCreateView, self).form_valid(form)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.