Django: универсальный редактор справочников

Довольно часто при разработке приложений на Django необходимо реализовать редактирование данных по подобию админки.

Исходные данные: имеем модель, Street. Необходимо реализовать операции редактирования имеющихся сущностей, а так же операцию добавления новой сущности. Операцию удаления рассматривать не будем.

При этом решение должно быть универсальное, применимое для большого количества моделей.

Описываем представление table_edit:

def table_edit(request, object_id=None, Form=None, redirect_url=None):
    if request.method == 'POST':
        if object_id is None:
            edit_form = Form(request.POST)
        else:
            edit_form = Form(request.POST, instance=Form.Meta.model.objects.get(id=object_id))
    elif object_id is None:
        edit_form = Form()
    else:
        edit_form = Form(instance=Form.Meta.model.objects.get(id=object_id))
    if edit_form.is_valid():
        edit_form.save()
        if redirect_url is not None:
            return redirect(redirect_url)
    return render_to_response('simple_edit_form.html', {
        'edit_form': edit_form,
    })

Шаблон simple_edit_form.html в произвольном месте должен содержать строки:

    <form class='edit_form' method="POST">
        {.{ edit_form.as_p }}
        <input type="submit" class="btn btn-primary" value="Сохранить"/>
    </form>

необходимо убрать точку из {.{

Далее необходимо для каждой модели, которую мы хотели бы редактировать описать форму, которая будет отображаться на странице редактирования. В простейшем случае форма выглядит следующим образом:

class StreetForm(forms.ModelForm):
    class Meta:
        model = Street

Подробнее про формы Django можно почитать в документации Django здесь и здесь

Теперь необходимо добавить URL, по которым будет открываться редактор.

Добавляем в urls.py следующие строки:

    url(r'street_edit/$', table_edit, {'Form': StreetForm, 'redirect_url': '/street_list'}, name='street_edit_new'),
    url(r'street_edit/(\d+)/$', table_edit, {'Form': StreetForm, 'redirect_url': '/street_list'}, name='street_edit'),

Теперь по URL /street_edit/ будет открываться незаполненная форма редактирования записи, а по URL /street_edit/1/ - форма редактирования записи с ID = 1.