模型上的自定义clean()错误和inlineformset_factory的non_field_errors

时间:2011-04-28 05:13:02

标签: django

我有一个像这样的地址模型;

class Address(models.Model):
    user = models.ForeignKey(Profile)
    type = models.IntegerField(choices=Address_Type, default=1, editable=False)
    street = models.CharField(max_length=128, blank=True, null=True)
    city = models.CharField(max_length=128, blank=True, null=True)
    pcode = models.CharField(max_length=128, blank=True, null=True)
    state = models.CharField(max_length=128, blank=True, null=True)
    country = models.CharField(max_length=128, default="AU", editable=False)

    def __unicode__(self):
       return '%s' % (self.user)

    def clean(self):
        if self.id:
            if self.type == 1 and self.street == '':
                raise ValidationError({NON_FIELD_ERRORS: ["Contact Address street must not me empty"]})

    class Meta:
        verbose_name = 'Address'
        verbose_name_plural = 'Addresses'

并使用以下内容;

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        profile, new = Profile.objects.get_or_create(user=instance)
        addr, new = Address.objects.get_or_create(user=profile,type=1)
        addr, new = Address.objects.get_or_create(user=profile,type=2)

为用户创建个人资料和2个空白地址记录。

在我的forms.py中,我有;

AddressFormSet = inlineformset_factory(Profile, Address, can_delete=False, extra=0)

和我的观点;

def CustomerProfileView(request):
    if not request.user.is_authenticated():
        return redirect('customer_login_view')

    template_name='customers/customer_detail.html'
    profile = get_object_or_404(Profile, user=request.user)

    if request.method == "POST":
        form = CustomerForm(request.POST, instance=profile, prefix='customer')
        addr_set = AddressFormSet(request.POST, request.FILES, instance=profile)
        if form.is_valid() and addr_set.is_valid():
            form.save()
            addr_set.save()
            return HttpResponseRedirect('summary_details')

    form = CustomerForm(instance=profile, prefix='customer')
    addr_set = CustomerFormSet(instance=profile)
    ctx = {'form': form, 'addr_set': addr_set}
    return render_to_response(template_name, ctx, context_instance=RequestContext(request))

和我模板中的一个片段;

{% for form in addr_set.forms %}
                {{ form.non_field_errors }}
                {% if forloop.first %}<h3>Contact Address</h3>{% else %}<h3>Shipping Address</h3><p><i>If different form contact address.</i></p>{% endif %}
                <table border="0">
                    {% for field in form %}
                        {% if not field.is_hidden %}
                            <tr>
                                <td>{{ field.label_tag }}:</td>
                                <td>
                                    {{ field }}<br />{{ form.non_field_errors }}
                                    {% for error in field.errors %}{{ error }}{% endfor %}
                                </td>
                            </tr>
                        {% else %}<td valign="bottom">{{ field }}</td>{% endif %}
                    {% endfor %}
                </table>
            {% endfor %}

我想要的是在用户注册时自动创建2个地址记录,但只能在某个类型的地址上进行验证,并且仅在UPDATE,在这种情况下是用户正常的联系地址,另一种类型是用于运输并且是可选的。我想我可以将表格弄平或将不同的类型分成他们自己的模型,但我决定沿着这条路走下去。

Address模型中的clean()函数正在工作,只要它引发错误但我无法使用non_field_errors在我的模板中显示该错误。

1 个答案:

答案 0 :(得分:0)

我建议对Single Responsibility Principle进行一些考虑。联系地址和发货地址是两个不同的问题,可能需要不同的处理,甚至可能根据您的业务需求不同的持久性架构。在这个系统中,你将它们集中在同一个模型中。这是'类型'字段,为我提出了红旗。您可能还有两个模型,无需在同一模型中处理不同的验证要求,这就是您提出问题的原因。此时还有其他address validation concerns to consider ...

顺便说一下,我为地址验证公司SmartyStreets开发软件。如果您有任何其他问题或意见,请与我们联系。