Reputation: 723
Following the ModelForm docs and using this model:
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)
I made this form template following their example (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 %}
My app 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'),
)
My view (with lots of diagnostic logging):
@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,
})
My forms.py definition:
class ShipLabelForm(ModelForm):
class Meta:
model = ShippingLabel
localized_fields = '__all__'
fields = '__all__'
widgets = {
'added_by': HiddenInput,
'id': HiddenInput,
}
I added 'id': HiddenInput, to try and "force" record ID number to get sent out to the form, in the theory that my error occurs because without the ID number, Django will validate in "ADD" mode which will certainly trigger the "unique" flag I have on clients.
The manual_label view is called by a customer selection form, passing in the client id. The goal is to generate an ADD form if there is currently no shipping label for this client defined - which works.
And if a shipping label already exists, I pre-load the form with its data. The idea being I thought the form system would automatically do an UPDATE on the existing record.
In either case, the saved shipping label record is used to generate the shipping labels desired.
This works in the admin view (using view on site). But I wanted to give the users a simpler system. This works fine for ADDing new labels. But when I try to EDIT an existing label, I get a form validation error "client already exists".
It seemed like such an easy thing to do....
So, what am I missing tor doing wrong?
Upvotes: 2
Views: 1537
Reputation: 599778
You should be using the instance
argument when initializing the form, both in the POST and GET blocks.
Upvotes: 2