diff -r 57b4279d8c4e -r 03e267d67478 app/django/views/generic/create_update.py --- /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: ``/_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: ``/_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: ``/_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