Permalink
Browse files

A bunch of generics: documentation of generic views; cleaned up exist…

…ing generic views, and added create/update generic views.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@304 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 8bd30b0 commit 371144f13401d8742876b77f5407011eb50f93d8 @jacobian jacobian committed Jul 24, 2005
@@ -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
+
@@ -6,7 +6,8 @@
from django.utils.httpwrappers import HttpResponse
import datetime, time
-def archive_index(request, app_label, module_name, date_field, num_latest=15, template_name=None, extra_lookup_kwargs={}, extra_context=None):
+def archive_index(request, app_label, module_name, date_field, num_latest=15,
+ template_name=None, extra_lookup_kwargs={}, extra_context=None):
"""
Generic top-level archive of date-based objects.
@@ -44,7 +45,8 @@ def archive_index(request, app_label, module_name, date_field, num_latest=15, te
c.update(extra_context)
return HttpResponse(t.render(c))
-def archive_year(request, year, app_label, module_name, date_field, template_name=None, extra_lookup_kwargs={}, extra_context=None):
+def archive_year(request, year, app_label, module_name, date_field,
+ template_name=None, extra_lookup_kwargs={}, extra_context=None):
"""
Generic yearly archive view.
@@ -76,7 +78,8 @@ def archive_year(request, year, app_label, module_name, date_field, template_nam
c.update(extra_context)
return HttpResponse(t.render(c))
-def archive_month(request, year, month, app_label, module_name, date_field, template_name=None, extra_lookup_kwargs={}, extra_context=None):
+def archive_month(request, year, month, app_label, module_name, date_field,
+ template_name=None, extra_lookup_kwargs={}, extra_context=None):
"""
Generic monthly archive view.
@@ -122,7 +125,9 @@ def archive_month(request, year, month, app_label, module_name, date_field, temp
c.update(extra_context)
return HttpResponse(t.render(c))
-def archive_day(request, year, month, day, app_label, module_name, date_field, template_name=None, extra_lookup_kwargs={}, extra_context=None, allow_empty=False):
+def archive_day(request, year, month, day, app_label, module_name, date_field,
+ template_name=None, extra_lookup_kwargs={}, extra_context=None,
+ allow_empty=False):
"""
Generic daily archive view.
@@ -178,7 +183,9 @@ def archive_today(request, **kwargs):
})
return archive_day(request, **kwargs)
-def object_detail(request, year, month, day, app_label, module_name, date_field, object_id=None, slug=None, slug_field=None, template_name=None, extra_lookup_kwargs={}, extra_context=None):
+def object_detail(request, year, month, day, app_label, module_name, date_field,
+ object_id=None, slug=None, slug_field=None, template_name=None,
+ template_name_field=None, extra_lookup_kwargs={}, extra_context=None):
"""
Generic detail view from year/month/day/slug or year/month/day/id structure.
@@ -212,7 +219,11 @@ def object_detail(request, year, month, day, app_label, module_name, date_field,
raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs))
if not template_name:
template_name = "%s/%s_detail" % (app_label, module_name)
- t = template_loader.get_template(template_name)
+ if template_name_field:
+ template_name_list = [getattr(object, template_name_field), template_name]
+ t = template_loader.select_template(template_name_list)
+ else:
+ t = template_loader.get_template(template_name)
c = Context(request, {
'object': object,
})
@@ -6,7 +6,8 @@
from django.core.paginator import ObjectPaginator, InvalidPage
from django.core.exceptions import Http404, ObjectDoesNotExist
-def object_list(request, app_label, module_name, paginate_by=None, allow_empty=False, template_name=None, extra_lookup_kwargs={}, extra_context=None):
+def object_list(request, app_label, module_name, paginate_by=None, allow_empty=False,
+ template_name=None, extra_lookup_kwargs={}, extra_context=None):
"""
Generic list of objects.
@@ -67,7 +68,9 @@ def object_list(request, app_label, module_name, paginate_by=None, allow_empty=F
t = template_loader.get_template(template_name)
return HttpResponse(t.render(c))
-def object_detail(request, app_label, module_name, object_id=None, slug=None, slug_field=None, template_name=None, template_name_field=None, extra_lookup_kwargs={}, extra_context=None):
+def object_detail(request, app_label, module_name, object_id=None, slug=None,
+ slug_field=None, template_name=None, template_name_field=None,
+ extra_lookup_kwargs={}, extra_context=None):
"""
Generic list of objects.
Oops, something went wrong. Retry.

0 comments on commit 371144f

Please sign in to comment.