You can get rid of half of the code easily.
You missed modelforms and generic views.
You could just have such urls:
from django.views import generic
urlpatterns = patterns('test_app.views',
url(r'link/create/$', generic.CreateView.as_view(model=Link),
name='link_create'),
url(r'link/(?P<pk>\d+)/update/$', generic.UpdateView.as_view(model=Link),
name='link_update'),
url(r'link/(?P<pk>\d+)/delete/$', generic.DeleteView.as_view(model=Link),
name='link_delete'),
# bonus:
url(r'link/$', generic.ListView.as_view(model=Link), name='link_list'),
url(r'link/(?P<pk>\d+)/$', generic.DetailView.as_view(model=Link),
name='link_detail'),
)
But it doesn't support AJAX like you by default - however you could extend CreateView
UpdateView
and DeleteView
and do the little overrides needed to support your javascript. For example, I have this in a project:
class AjaxDeleteView(generic.DeleteView):
# now that I think of it, this could just be a DetailView ... oh well
http_method_names = ['post']
def post(self, *args, **kwargs):
self.get_object().delete()
return http.HttpResponse('', status=204)
class AjaxFormMixin(object):
def form_valid(self, form):
if form.instance.pk:
status = 204
else:
status = 201
self.object = form.save()
return http.HttpResponse(self.object.pk, status=status)
Some other examples of extending Django generic views:
class PkUrlKwarg(SingleObjectMixin):
"""
Take the pk from request.GET and sets it to kwargs, useful to avoid
reversing urls from javascript
"""
def get_object(self, queryset=None):
self.kwargs[self.pk_url_kwarg] = self.request.REQUEST['pk']
return super(PkUrlKwarg, self).get_object(queryset)
class WidgetFormMixin(object):
def get_form(self, form_class):
# [snip] ok there's quite a lot (11 SLOCs) going on here in my case, since Widget* views are
# supposed to deal with any subclass of Widget
return self.object.configuration_form_instance(self.request)
def get_template_names(self):
widget_name = self.object.__class__.__name__
return [
'form_designer/widget_forms/%s.html' % widget_name,
'form_designer/widget_form.html',
]
class WidgetSecurity(object):
"""
Return a queryset of Widget that have a tab in a form which author is
request.user. For security.
"""
def get_queryset(self):
return Widget.objects.filter(tab__form__author=self.request.user)
Finnaly, my CRUD views, have quite a lot non default and more or less complex logic, but still, with very few lines of code:
class WidgetCreateView(WidgetFormMixin, AjaxFormMixin, generic.CreateView):
form_class = WidgetForm # overridden by WidgetFormMixin.get_form, but make django happy
class WidgetUpdateView(PkUrlKwarg, WidgetSecurity, WidgetFormMixin, AjaxFormMixin, generic.UpdateView):
form_class = WidgetForm # overridden by WidgetFormMixin.get_form
class WidgetDeleteView(PkUrlKwarg, WidgetSecurity, AjaxDeleteView):
pass
This may not be the best answer, but it should definitively put you on the right track, and inspire you.
Also note that you should also define get_absolute_url() in your model.
For the record, urls:
url(r'widget/create/$',
login_required(WidgetCreateView.as_view()),
name='form_designer_widget_create'),
# the following views accept 'pk' as URL/GET argument
# this avoids reversing urls from javascript at the cost of a 4-liner mixin
url(r'widget/update/$',
login_required(WidgetUpdateView.as_view()),
name='form_designer_widget_update'),
url(r'widget/delete/$',
login_required(WidgetDeleteView.as_view()),
name='form_designer_widget_delete'),