diff options
| author | Jacob Kaplan-Moss <jacob@jacobian.org> | 2005-07-24 22:21:09 +0000 |
|---|---|---|
| committer | Jacob Kaplan-Moss <jacob@jacobian.org> | 2005-07-24 22:21:09 +0000 |
| commit | 371144f13401d8742876b77f5407011eb50f93d8 (patch) | |
| tree | a758e92011ffacb412adb389f5d8aa6f8ec2e704 /django/views/generic/create_update.py | |
| parent | 8bd30b01e401e7ed8ef87bf42bec2614e8d96570 (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.py | 185 |
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 + |
