如何在Django 1.6中使用ModelForms避免“记录已存在”表单验证错误?

时间:2014-08-21 01:55:45

标签: python django forms django-forms

关注ModelForm文档并使用此模型:

class ShippingLabel(models.Model):
"""Record what shipping lables were printed list"""
class Meta:
    db_table = 'shipping_labels'
    ordering = ('client',)
    verbose_name = _('shipping label')
    verbose_name_plural = _('shipping labels')

LAYOUT_LASER_2x2 = "1"
LAYOUT_TICKET = "2"
LAYOUT_LASER_1x1 = "3"
LAYOUT_CHOICES = (
    ( LAYOUT_LASER_1x1, _("Laser (1x1 sheet)") ),
    ( LAYOUT_LASER_2x2, _("Laser (2x2 sheet)") ),
    ( LAYOUT_TICKET, _("Ticket (3-inch wide)") ),
)

client = models.ForeignKey(Company, blank=False, null=False, unique=True, help_text=_("Which Client to ship to?"), verbose_name=_("client") )
store = models.ForeignKey(Store, blank=False, null=False, help_text=_("What store info should be used? (address, logo, phone, etc)"), verbose_name=_("store") )
packages = models.CharField(_("Packages"), max_length=30, blank=False, null=False, help_text=_("Total number of packages. One label printed per package.") )
preprinted_form = models.BooleanField(_("Pre-Printed Form"), default=False, help_text=_("Are you using pre-printed shipping label stickers?"), )
layout = models.CharField(_("Record Type"), max_length=10, blank=False, null=False, choices=LAYOUT_CHOICES, default=LAYOUT_LASER_1x1, help_text=_("Print on large labels (4 per Letter page), Laser large labels (1 per page), or ticket printer?") )
added_by = models.CharField(_("Added By"), max_length=30, blank=True, null=True, help_text=_("The User that created this order.") )
date_added = models.DateTimeField(_('Date added'), auto_now_add=True)
date_modified = models.DateTimeField(_('Date modified'), auto_now=True)

def get_absolute_url(self):
    return reverse('shipping:printship', args=[str(self.id)])

def __unicode__(self):
    return unicode(self.client)

我按照他们的示例(manual_label.html)创建了此表单模板:

{% extends "admin/base_site.html" %}
{% load i18n %}
{% load staticfiles %}

{% block extrahead %}
    {{ block.super}}
    <script src="{{ STATIC_URL }}js/jquery-1.11.1.js"></script>
{% endblock %}

{% block content %}
<form id="manual_label" method="post" action="">
    {% csrf_token %}
    {% for hidden in form.hidden_fields %}
        {{ hidden }}
    {% endfor %}
    <table>
        {{ form.as_table }}
    </table>
    <input type="submit" value="generar etiquetas autoadhesivas"/>
</form>
<p>

</p>
{% endblock %}

我的应用urls.py:

from django.conf.urls import patterns, url

from shipping.views import printship, pcustomer, manual_label

urlpatterns = patterns('',
    url(r'pcust/', pcustomer, name='pcustomer'),
    url(r'mlabel/([0-9]+)/$', manual_label, name='manual_label'),
    url(r'printlabel/([0-9]+)/$', printship, name='printship'),
)

我的观点(包含大量诊断记录):

@login_required()
def manual_label(request, id):
    logger.debug("SHIPPING.VIEWS.manual_label")
    if request.method == 'POST':
        logger.debug("SHIPPING.VIEWS.manual_label: POST!")
        client = get_object_or_404(Company, pk=id)
        labelset = ShippingLabel.objects.filter(client=client)
        if len(labelset)>0:
            # Pre-existing label, update it:
            logger.debug("SHIPPING.VIEWS.manual_label.POST: Update a label!")
            label = labelset[0]
            form = ShipLabelForm(request.POST, instance=label)
        else:
            # New label:
            logger.debug("SHIPPING.VIEWS.manual_label.POST: Save New label!")
            form = ShipLabelForm(request.POST)
        if form.is_valid():
            logger.debug("SHIPPING.VIEWS.manual_label.POST: form is valid")
            label = form.save(commit=True)
            logger.debug("SHIPPING.VIEWS.manual_label.POST: label pk: " + str(label.id) )
            logger.debug("SHIPPING.VIEWS.manual_label.POST: label client name: " + str(label.client.name) )
            logger.debug("SHIPPING.VIEWS.manual_label: post return")
            return HttpResponseRedirect(reverse('shipping:printship', args=[str(label.id)]))
    else:
        logger.debug("SHIPPING.VIEWS.manual_label: GET!")
        client = get_object_or_404(Company, pk=id)
        labelset = ShippingLabel.objects.filter(client=client)
        if len(labelset)>0:
            # Pre-existing label, load it:
            logger.debug("SHIPPING.VIEWS.manual_label: Pre-Existing label, load it...")
            label = labelset[0]
            form = ShipLabelForm(instance=label)
        else:
            # New label:
            label = ShippingLabel(client=client,
                                store=request.user.employee.store,
                                added_by=request.user.get_username())
            form = ShipLabelForm(instance=label)
    logger.debug("SHIPPING.VIEWS.manual_label: get return")
    return render(request, 'shipping/manual_label.html', {
                                             'title': u"Creación de etiquetas Manual Envios",
                                             'form': form,
                                             })

我的forms.py定义:

class ShipLabelForm(ModelForm):
    class Meta:
        model = ShippingLabel
        localized_fields = '__all__'
        fields = '__all__'
        widgets = {
            'added_by': HiddenInput,
            'id': HiddenInput,
        }

我添加了 &#39; id&#39;:HiddenInput, 来尝试&#34;强制&#34;记录发送到表单的ID号,理论上我的错误发生是因为没有ID号,Django将验证&#34; ADD&#34;模式肯定会触发&#34; unique&#34;我在客户身上的旗帜。

manual_label 视图由客户选择表单调用,传入客户端ID。目标是在目前没有定义此客户的运输标签时生成ADD表单 - 这有效。

如果已经存在运输标签,我会预先加载表单及其数据。我认为表单系统会自动对现有记录进行更新。

在任何一种情况下,保存的运输标签记录都用于生成所需的运输标签。

这适用于管理视图(使用网站上的视图)。但我想给用户一个更简单的系统。这适用于 ADDing 新标签。但是,当我尝试编辑现有标签时,我收到表单验证错误&#34; 客户端已存在&#34; 。< / p>

这似乎很容易做到....

那么,我错过了什么错误?

1 个答案:

答案 0 :(得分:1)

在POST和GET块中初始化表单时,您应该使用instance参数。