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 /_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 /_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))