summaryrefslogtreecommitdiff
path: root/django/views/generic/create_update.py
diff options
context:
space:
mode:
authorJacob Kaplan-Moss <jacob@jacobian.org>2005-07-24 22:21:09 +0000
committerJacob Kaplan-Moss <jacob@jacobian.org>2005-07-24 22:21:09 +0000
commit371144f13401d8742876b77f5407011eb50f93d8 (patch)
treea758e92011ffacb412adb389f5d8aa6f8ec2e704 /django/views/generic/create_update.py
parent8bd30b01e401e7ed8ef87bf42bec2614e8d96570 (diff)
A bunch of generics: documentation of generic views; cleaned up existing generic views, and added create/update generic views.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@304 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/views/generic/create_update.py')
-rw-r--r--django/views/generic/create_update.py185
1 files changed, 185 insertions, 0 deletions
diff --git a/django/views/generic/create_update.py b/django/views/generic/create_update.py
new file mode 100644
index 0000000000..35ce31713d
--- /dev/null
+++ b/django/views/generic/create_update.py
@@ -0,0 +1,185 @@
+from django import models
+from django.core.xheaders import populate_xheaders
+from django.core import template_loader, formfields
+from django.views.auth.login import redirect_to_login
+from django.core.extensions import DjangoContext as Context
+from django.core.paginator import ObjectPaginator, InvalidPage
+from django.utils.httpwrappers import HttpResponse, HttpResponseRedirect
+from django.core.exceptions import Http404, ObjectDoesNotExist, ImproperlyConfigured
+
+def create_object(request, app_label, module_name, template_name=None,
+ extra_context=None, post_save_redirect=None, login_required=False):
+ """
+ Generic object-creation function.
+
+ Templates: ``<app_label>/<module_name>_form``
+ Context:
+ form
+ the form wrapper for the object
+ """
+ if login_required and request.user.is_anonymous():
+ return redirect_to_login(request)
+
+ mod = models.get_module(app_label, module_name)
+ manipulator = mod.AddManipulator()
+ if request.POST:
+ # If data was POSTed, we're trying to create a new object
+ new_data = request.POST.copy()
+
+ # Check for errors
+ errors = manipulator.get_validation_errors(new_data)
+
+ if not errors:
+ # No errors -- this means we can save the data!
+ manipulator.do_html2python(new_data)
+ new_object = manipulator.save(new_data)
+
+ if not request.user.is_anonymous():
+ request.user.add_message("The %s was created sucessfully." % mod.Klass._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 = {}
+
+ # Create the FormWrapper, template, context, response
+ form = formfields.FormWrapper(manipulator, new_data, errors)
+ if not template_name:
+ template_name = "%s/%s_form" % (app_label, module_name)
+ t = template_loader.get_template(template_name)
+ c = Context(request, {
+ 'form' : form,
+ })
+ if extra_context:
+ c.update(extra_context)
+ return HttpResponse(t.render(c))
+
+def update_object(request, app_label, module_name, object_id=None, slug=None,
+ slug_field=None, template_name=None, extra_lookup_kwargs={},
+ extra_context=None, post_save_redirect=None, login_required=False):
+ """
+ Generic object-update function.
+
+ Templates: ``<app_label>/<module_name>_form``
+ Context:
+ form
+ the form wrapper for the object
+ object
+ the original object being edited
+ """
+ if login_required and request.user.is_anonymous():
+ return redirect_to_login(request)
+
+ mod = models.get_module(app_label, module_name)
+
+ # Look up the object to be edited
+ lookup_kwargs = {}
+ if object_id:
+ lookup_kwargs['%s__exact' % mod.Klass._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")
+ lookup_kwargs.update(extra_lookup_kwargs)
+ try:
+ object = mod.get_object(**lookup_kwargs)
+ except ObjectDoesNotExist:
+ raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs))
+
+ manipulator = mod.ChangeManipulator(object.id)
+
+ if request.POST:
+ new_data = request.POST.copy()
+ errors = manipulator.get_validation_errors(new_data)
+ if not errors:
+ manipulator.do_html2python(new_data)
+ manipulator.save(new_data)
+
+ if not request.user.is_anonymous():
+ request.user.add_message("The %s was updated sucessfully." % mod.Klass._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 = object.__dict__
+
+ form = formfields.FormWrapper(manipulator, new_data, errors)
+ if not template_name:
+ template_name = "%s/%s_form" % (app_label, module_name)
+ t = template_loader.get_template(template_name)
+ c = Context(request, {
+ 'form' : form,
+ 'object' : object,
+ })
+ if extra_context:
+ c.update(extra_context)
+ response = HttpResponse(t.render(c))
+ populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name))
+ return response
+
+def delete_object(request, app_label, module_name, post_delete_redirect,
+ object_id=None, slug=None, slug_field=None, template_name=None,
+ extra_lookup_kwargs={}, extra_context=None, login_required=False):
+ """
+ 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>/<module_name>_confirm_delete``
+ Context:
+ object
+ the original object being deleted
+ """
+ if login_required and request.user.is_anonymous():
+ return redirect_to_login(request)
+
+ mod = models.get_module(app_label, module_name)
+
+ # Look up the object to be edited
+ lookup_kwargs = {}
+ if object_id:
+ lookup_kwargs['%s__exact' % mod.Klass._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")
+ lookup_kwargs.update(extra_lookup_kwargs)
+ try:
+ object = mod.get_object(**lookup_kwargs)
+ except ObjectDoesNotExist:
+ raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs))
+
+ if request.META['REQUEST_METHOD'] == 'POST':
+ object.delete()
+ if not request.user.is_anonymous():
+ request.user.add_message("The %s was deleted." % mod.Klass._meta.verbose_name)
+ return HttpResponseRedirect(post_delete_redirect)
+ else:
+ if not template_name:
+ template_name = "%s/%s_confirm_delete" % (app_label, module_name)
+ t = template_loader.get_template(template_name)
+ c = Context(request, {
+ 'object' : object,
+ })
+ if extra_context:
+ c.update(extra_context)
+ response = HttpResponse(t.render(c))
+ populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name))
+ return response
+