Reputation: 6832
Consider a model:
class MyModel(models.Model):
token = models.CharField(unique=True, db_index=True, max_length...)
name = models.CharField(...)
...
(Aside: The purpose of the token is to be an alternative to displaying and using the ID in URLs; it is not the primary key.)
And its form:
class MyForm(forms.ModelForm):
...
class Meta:
model = models.MyModel
fields = '__all__' # Django 1.6
And its template:
...
<form action={% url 'create_or_edit_mymodel' %} ...>{% csrf_token %}
{{ form.token.as_hidden }}
<label for="id_name">Name:</label>
{{ form.name }}
...
And, finally, its view:
def create_or_edit_mymodel(request, token=None):
# [A] Entering via a hyperlink with the token, editing existing model
if token:
m = models.MyModel.objects.filter(token=token).first()
form = forms.MyForm(instance=m)
# [B] Postback from form
elif request.POST:
form = forms.MyForm(request.POST)
# [C] Entering via a hyperlink without the token, creating new model
else:
m = create_new_mymodel(...) # somewhere else
form = forms.MyForm(instance=m)
if request.method == 'POST' and form.is_valid():
saved = form.save()
# Determine if 'Save' or 'Save & Close' was clicked... assume 'Save'...
form = forms.MyForm(instance=saved)
return shortcuts.render(request, '...', { 'form': form }, context_instance=RequestContext(request))
This doesn't work. The problem is that the model's ID doesn't seem to be available to Django, so entering the view at [A] populates the form with everything as expected, but clicking 'Save' and entering the view at [B] attempts to save a model with no ID, and the unique constraint on the 'token' field fires.
I tried adding the id field to the form:
{{ form.id.as_hidden }} # or...
{{ form.pk.as_hidden }}
But nothing gets rendered.
That view looks pretty uncomfortable to me, so I'm hoping I'm making this harder than it needs to be.
Upvotes: 1
Views: 121
Reputation: 22561
Here you should pass both request.POST
and instance to form init:
# [B] Postback from form
elif request.POST:
form = forms.MyForm(request.POST, instance=instance)
Upvotes: 2