An idiom to use the same view function to create or edit an object?

Here is the skeleton of my (first!) Django app:

# models.py
description = models.CharField(max_length = 200)
...

# forms.py
class Meta:


I then created two views using AddTaskForm: one to create a new instance, the other to edit an existing one. I was able to refactor those two views (and the function they call) into one, but I'm not sure I got the best possible result...

# urls.py:
(r'^yata/add_task/$', 'yata.views.edit'), (r'^yata/(?P<task_id>\d+)/edit/$', 'yata.views.edit'),

# views.py
def edit(request, task_id = None):
if request.method == 'POST':
if form.is_valid():
form.save()
return HttpResponseRedirect('/yata/')
else:

# Either the form was not valid, or we've just created it
d = {'form': form}
# The template needs the id to decide if the form's action
d['id'] = t.id
return render_to_response('yata/edit.html', d,
context_instance=RequestContext(request))


And here is the corresponding part of the template:

# edit.html
{% if id %}
<form action="/yata/{{ id }}/edit/" method="post">
{% else %}
{% endif %}
{{ form.as_p }}
<input type="submit" value="Save!" />
</form>


Is there a better Django idiom to handle this 'add or create' issue? Or can this be considered a correct way?

I have looked at your code and I think that it actually looks pretty clean and straight forward. However, I would suggest that you make it more DRY by using reverse() to figure out what action to assign to the form.

views.py:

if task_id:
action = reverse(edit, args=[task_id])
else:
action = reverse(edit)
d['action'] = action


edit.html:

<form action="{{ action }}" method="post">
{{ form.as_p }}
<input type="submit" value="Save!" />
</form>

• And, additionally, it helps separating concerns: the view is not supposed to contain the application's logic... Great! Thanks. – Xavier Nodet Jan 29 '11 at 7:52

You don't need set "action" for form directly.

# views.py
def edit(request, task_id = None):