--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/views/generic/create_update.py Fri Jul 18 18:22:23 2008 +0000
@@ -0,0 +1,200 @@
+from django.core.xheaders import populate_xheaders
+from django.template import loader
+from django import oldforms
+from django.db.models import FileField
+from django.contrib.auth.views import redirect_to_login
+from django.template import RequestContext
+from django.http import Http404, HttpResponse, HttpResponseRedirect
+from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
+from django.utils.translation import ugettext
+
+def create_object(request, model, template_name=None,
+ template_loader=loader, extra_context=None, post_save_redirect=None,
+ login_required=False, follow=None, context_processors=None):
+ """
+ Generic object-creation function.
+
+ Templates: ``<app_label>/<model_name>_form.html``
+ Context:
+ form
+ the form wrapper for the object
+ """
+ if extra_context is None: extra_context = {}
+ if login_required and not request.user.is_authenticated():
+ return redirect_to_login(request.path)
+
+ manipulator = model.AddManipulator(follow=follow)
+ if request.POST:
+ # If data was POSTed, we're trying to create a new object
+ new_data = request.POST.copy()
+
+ if model._meta.has_field_type(FileField):
+ new_data.update(request.FILES)
+
+ # Check for errors
+ errors = manipulator.get_validation_errors(new_data)
+ manipulator.do_html2python(new_data)
+
+ if not errors:
+ # No errors -- this means we can save the data!
+ new_object = manipulator.save(new_data)
+
+ if request.user.is_authenticated():
+ request.user.message_set.create(message=ugettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name})
+
+ # Redirect to the new object: first by trying post_save_redirect,
+ # then by obj.get_absolute_url; fail if neither works.
+ if post_save_redirect:
+ return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
+ elif hasattr(new_object, 'get_absolute_url'):
+ return HttpResponseRedirect(new_object.get_absolute_url())
+ else:
+ raise ImproperlyConfigured("No URL to redirect to from generic create view.")
+ else:
+ # No POST, so we want a brand new form without any data or errors
+ errors = {}
+ new_data = manipulator.flatten_data()
+
+ # Create the FormWrapper, template, context, response
+ form = oldforms.FormWrapper(manipulator, new_data, errors)
+ if not template_name:
+ template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower())
+ t = template_loader.get_template(template_name)
+ c = RequestContext(request, {
+ 'form': form,
+ }, context_processors)
+ for key, value in extra_context.items():
+ if callable(value):
+ c[key] = value()
+ else:
+ c[key] = value
+ return HttpResponse(t.render(c))
+
+def update_object(request, model, object_id=None, slug=None,
+ slug_field='slug', template_name=None, template_loader=loader,
+ extra_context=None, post_save_redirect=None,
+ login_required=False, follow=None, context_processors=None,
+ template_object_name='object'):
+ """
+ Generic object-update function.
+
+ Templates: ``<app_label>/<model_name>_form.html``
+ Context:
+ form
+ the form wrapper for the object
+ object
+ the original object being edited
+ """
+ if extra_context is None: extra_context = {}
+ if login_required and not request.user.is_authenticated():
+ return redirect_to_login(request.path)
+
+ # Look up the object to be edited
+ 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("Generic edit view must be called with either an object_id or a slug/slug_field")
+ try:
+ object = model.objects.get(**lookup_kwargs)
+ except ObjectDoesNotExist:
+ raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
+
+ manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.attname), follow=follow)
+
+ if request.POST:
+ new_data = request.POST.copy()
+ if model._meta.has_field_type(FileField):
+ new_data.update(request.FILES)
+ errors = manipulator.get_validation_errors(new_data)
+ manipulator.do_html2python(new_data)
+ if not errors:
+ object = manipulator.save(new_data)
+
+ if request.user.is_authenticated():
+ request.user.message_set.create(message=ugettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name})
+
+ # Do a post-after-redirect so that reload works, etc.
+ if post_save_redirect:
+ return HttpResponseRedirect(post_save_redirect % object.__dict__)
+ elif hasattr(object, 'get_absolute_url'):
+ return HttpResponseRedirect(object.get_absolute_url())
+ else:
+ raise ImproperlyConfigured("No URL to redirect to from generic create view.")
+ else:
+ errors = {}
+ # This makes sure the form acurate represents the fields of the place.
+ new_data = manipulator.flatten_data()
+
+ form = oldforms.FormWrapper(manipulator, new_data, errors)
+ if not template_name:
+ template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower())
+ t = template_loader.get_template(template_name)
+ c = RequestContext(request, {
+ 'form': form,
+ template_object_name: object,
+ }, context_processors)
+ for key, value in extra_context.items():
+ if callable(value):
+ c[key] = value()
+ else:
+ c[key] = value
+ response = HttpResponse(t.render(c))
+ populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
+ return response
+
+def delete_object(request, model, post_delete_redirect,
+ object_id=None, slug=None, slug_field='slug', template_name=None,
+ template_loader=loader, extra_context=None,
+ login_required=False, context_processors=None, template_object_name='object'):
+ """
+ Generic object-delete function.
+
+ The given template will be used to confirm deletetion if this view is
+ fetched using GET; for safty, deletion will only be performed if this
+ view is POSTed.
+
+ Templates: ``<app_label>/<model_name>_confirm_delete.html``
+ Context:
+ object
+ the original object being deleted
+ """
+ if extra_context is None: extra_context = {}
+ if login_required and not request.user.is_authenticated():
+ return redirect_to_login(request.path)
+
+ # Look up the object to be edited
+ 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("Generic delete view must be called with either an object_id or a slug/slug_field")
+ try:
+ object = model._default_manager.get(**lookup_kwargs)
+ except ObjectDoesNotExist:
+ raise Http404, "No %s found for %s" % (model._meta.app_label, lookup_kwargs)
+
+ if request.method == 'POST':
+ object.delete()
+ if request.user.is_authenticated():
+ request.user.message_set.create(message=ugettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name})
+ return HttpResponseRedirect(post_delete_redirect)
+ else:
+ if not template_name:
+ template_name = "%s/%s_confirm_delete.html" % (model._meta.app_label, model._meta.object_name.lower())
+ t = template_loader.get_template(template_name)
+ c = RequestContext(request, {
+ template_object_name: object,
+ }, context_processors)
+ for key, value in extra_context.items():
+ if callable(value):
+ c[key] = value()
+ else:
+ c[key] = value
+ response = HttpResponse(t.render(c))
+ populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
+ return response