This is a ModelForms-based rewrite of the create_object and update_object generic views, with a few added features. The views now accept a "form_class" argument optionally in place of the "model" argument, so you can create and tweak your own ModelForm to pass in. They also accept a "pre_save" callback that can make any additional changes to the created or updated instance (based on request.user, for instance) before it is saved to the DB.
Usage: just save the code in a file anywhere on the PythonPath and use the create_object and update_object functions as views in your urls.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | from django.template import RequestContext
from django.http import HttpResponseRedirect, Http404
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import render_to_response
from django import newforms as forms
def update_object (request, model=None, form_class=None,
object_id=None, slug=None, slug_field='slug',
template_name=None,
pre_save=None, extra_context=None,
post_save_redirect=None):
"""
Generic view to update instances of a model.
Arguments:
model: Model type to create
form_class: ModelForm subclass to use (either this or model must
be provided)
object_id: id of object to update (must provide either this or
slug/slug_field)
slug: slug of object to update (must provide either this or object_id)
slug_field: field to look up slug in (defaults to 'slug')
template_name: name of template to use, or list of templates -
defaults to <app_label>/<model_name>_form.html
pre_save: callback function to modify object after form data is
cleaned and applied and before instance save. Function should
take request and updated instance as arguments and return modified
instance ready for save.
extra_context: dictionary of items and/or callables to add to
template context.
post_save_redirect: URL to redirect to after successful object save -
defaults to instance.get_absolute_url, or "/" if not defined.
"""
model, form_class = _resolve_model_form(model, form_class)
lookup_kwargs = {}
if object_id:
lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
elif slug and slug_field:
lookup_kwargs['%s__exact' % slug_field] = slug
else:
raise AttributeError("update_object view must be called with either an object_id or a slug/slug_field")
try:
instance = model.objects.get(**lookup_kwargs)
except ObjectDoesNotExist:
raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
return _create_update(request, model, form_class, instance,
template_name, pre_save, extra_context,
post_save_redirect)
def create_object (request, model=None, form_class=None,
template_name=None,
pre_save=None, extra_context=None,
post_save_redirect=None):
"""
Generic view to create instances of a model.
Arguments:
model: Model type to create
form_class: ModelForm subclass to use (either this or model must
be provided)
template_name: name of template to use, or list of templates -
defaults to <app_label>/<model_name>_form.html
pre_save: callback function to modify object after form data is
cleaned and applied and before instance save. Function should
take request and instance as arguments and return modified
instance ready for save.
extra_context: dictionary of items and/or callables to add to
template context.
post_save_redirect: URL to redirect to after successful object save -
defaults to instance.get_absolute_url, or "/" if not defined.
"""
model, form_class = _resolve_model_form(model, form_class)
return _create_update(request, model, form_class, None,
template_name, pre_save, extra_context,
post_save_redirect)
def _resolve_model_form (_model=None, form_class=None):
if _model is None:
try:
_model = form_class._meta.model
except AttributeError:
raise AttributeError("create_object view requires either model or form_class (ModelForm subclass)")
if form_class is None:
class TempForm (forms.ModelForm):
class Meta:
model = _model
form_class = TempForm
return (_model, form_class)
def _create_update (request, model, form_class, instance,
template_name, pre_save, extra_context,
post_save_redirect):
extra_context = extra_context or {}
template_name = template_name or "%s/%s_form.html" % (
model._meta.app_label, model._meta.object_name.lower())
if request.method is 'POST':
form = form_class(request.POST, instance=instance)
if not form.errors:
obj = form.save(commit=False)
if callable(pre_save):
obj = pre_save(request, obj)
obj.save()
if post_save_redirect is None:
if hasattr(obj, 'get_absolute_url'):
post_save_redirect = obj.get_absolute_url()
else:
post_save_redirect = "/"
return HttpResponseRedirect(post_save_redirect)
else:
form = form_class(instance=instance)
c = {}
for key, value in extra_context.items():
if callable(value):
c[key] = value()
else:
c[key] = value
c['form'] = form
return render_to_response(template_name, c,
RequestContext(request))
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
And... it was checked in to trunk today. Never mind this snippet.
#
Please login first before commenting.