1
0
mirror of https://github.com/django/django.git synced 2025-06-05 03:29:12 +00:00

magic-removal: Got generic views working. Their info_dicts now take 'model' instead of 'app_label' and 'module_name'. Updated docs.

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1933 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-01-13 03:24:07 +00:00
parent 0e66c7adec
commit 6fb7423bb0
4 changed files with 87 additions and 104 deletions

View File

@ -1,4 +1,3 @@
from django import models
from django.core.xheaders import populate_xheaders from django.core.xheaders import populate_xheaders
from django.core.template import loader from django.core.template import loader
from django.core import formfields, meta from django.core import formfields, meta
@ -8,13 +7,13 @@ from django.core.paginator import ObjectPaginator, InvalidPage
from django.http import Http404, HttpResponse, HttpResponseRedirect from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
def create_object(request, app_label, module_name, template_name=None, def create_object(request, model, template_name=None,
template_loader=loader, extra_context={}, post_save_redirect=None, template_loader=loader, extra_context={}, post_save_redirect=None,
login_required=False, follow=None, context_processors=None): login_required=False, follow=None, context_processors=None):
""" """
Generic object-creation function. Generic object-creation function.
Templates: ``<app_label>/<module_name>_form`` Templates: ``<app_label>/<model_name>_form``
Context: Context:
form form
the form wrapper for the object the form wrapper for the object
@ -22,13 +21,12 @@ def create_object(request, app_label, module_name, template_name=None,
if login_required and request.user.is_anonymous(): if login_required and request.user.is_anonymous():
return redirect_to_login(request.path) return redirect_to_login(request.path)
mod = models.get_module(app_label, module_name) manipulator = model.AddManipulator(follow=follow)
manipulator = mod.AddManipulator(follow=follow)
if request.POST: if request.POST:
# If data was POSTed, we're trying to create a new object # If data was POSTed, we're trying to create a new object
new_data = request.POST.copy() new_data = request.POST.copy()
if mod.Klass._meta.has_field_type(meta.FileField): if model._meta.has_field_type(meta.FileField):
new_data.update(request.FILES) new_data.update(request.FILES)
# Check for errors # Check for errors
@ -40,7 +38,7 @@ def create_object(request, app_label, module_name, template_name=None,
new_object = manipulator.save(new_data) new_object = manipulator.save(new_data)
if not request.user.is_anonymous(): if not request.user.is_anonymous():
request.user.add_message("The %s was created sucessfully." % mod.Klass._meta.verbose_name) request.user.add_message("The %s was created sucessfully." % model._meta.verbose_name)
# Redirect to the new object: first by trying post_save_redirect, # Redirect to the new object: first by trying post_save_redirect,
# then by obj.get_absolute_url; fail if neither works. # then by obj.get_absolute_url; fail if neither works.
@ -58,7 +56,7 @@ def create_object(request, app_label, module_name, template_name=None,
# Create the FormWrapper, template, context, response # Create the FormWrapper, template, context, response
form = formfields.FormWrapper(manipulator, new_data, errors) form = formfields.FormWrapper(manipulator, new_data, errors)
if not template_name: if not template_name:
template_name = "%s/%s_form" % (app_label, module_name) template_name = "%s/%s_form" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name) t = template_loader.get_template(template_name)
c = DjangoContext(request, { c = DjangoContext(request, {
'form': form, 'form': form,
@ -70,14 +68,14 @@ def create_object(request, app_label, module_name, template_name=None,
c[key] = value c[key] = value
return HttpResponse(t.render(c)) return HttpResponse(t.render(c))
def update_object(request, app_label, module_name, object_id=None, slug=None, def update_object(request, model, object_id=None, slug=None,
slug_field=None, template_name=None, template_loader=loader, slug_field=None, template_name=None, template_loader=loader,
extra_lookup_kwargs={}, extra_context={}, post_save_redirect=None, extra_lookup_kwargs={}, extra_context={}, post_save_redirect=None,
login_required=False, follow=None, context_processors=None): login_required=False, follow=None, context_processors=None):
""" """
Generic object-update function. Generic object-update function.
Templates: ``<app_label>/<module_name>_form`` Templates: ``<app_label>/<model_name>_form``
Context: Context:
form form
the form wrapper for the object the form wrapper for the object
@ -87,23 +85,21 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
if login_required and request.user.is_anonymous(): if login_required and request.user.is_anonymous():
return redirect_to_login(request.path) return redirect_to_login(request.path)
mod = models.get_module(app_label, module_name)
# Look up the object to be edited # Look up the object to be edited
lookup_kwargs = {} lookup_kwargs = {}
if object_id: if object_id:
lookup_kwargs['%s__exact' % mod.Klass._meta.pk.name] = object_id lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
elif slug and slug_field: elif slug and slug_field:
lookup_kwargs['%s__exact' % slug_field] = slug lookup_kwargs['%s__exact' % slug_field] = slug
else: else:
raise AttributeError("Generic edit view must be called with either an object_id or a slug/slug_field") raise AttributeError("Generic edit view must be called with either an object_id or a slug/slug_field")
lookup_kwargs.update(extra_lookup_kwargs) lookup_kwargs.update(extra_lookup_kwargs)
try: try:
object = mod.get_object(**lookup_kwargs) object = model._default_manager.get_object(**lookup_kwargs)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs)) raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
manipulator = mod.ChangeManipulator(object.id, follow=follow) manipulator = model.ChangeManipulator(object.id, follow=follow)
if request.POST: if request.POST:
new_data = request.POST.copy() new_data = request.POST.copy()
@ -113,7 +109,7 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
manipulator.save(new_data) manipulator.save(new_data)
if not request.user.is_anonymous(): if not request.user.is_anonymous():
request.user.add_message("The %s was updated sucessfully." % mod.Klass._meta.verbose_name) request.user.add_message("The %s was updated sucessfully." % model._meta.verbose_name)
# Do a post-after-redirect so that reload works, etc. # Do a post-after-redirect so that reload works, etc.
if post_save_redirect: if post_save_redirect:
@ -129,7 +125,7 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
form = formfields.FormWrapper(manipulator, new_data, errors) form = formfields.FormWrapper(manipulator, new_data, errors)
if not template_name: if not template_name:
template_name = "%s/%s_form" % (app_label, module_name) template_name = "%s/%s_form" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name) t = template_loader.get_template(template_name)
c = DjangoContext(request, { c = DjangoContext(request, {
'form': form, 'form': form,
@ -141,10 +137,10 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
else: else:
c[key] = value c[key] = value
response = HttpResponse(t.render(c)) response = HttpResponse(t.render(c))
populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name)) populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
return response return response
def delete_object(request, app_label, module_name, post_delete_redirect, def delete_object(request, model, post_delete_redirect,
object_id=None, slug=None, slug_field=None, template_name=None, object_id=None, slug=None, slug_field=None, template_name=None,
template_loader=loader, extra_lookup_kwargs={}, extra_context={}, template_loader=loader, extra_lookup_kwargs={}, extra_context={},
login_required=False, context_processors=None): login_required=False, context_processors=None):
@ -155,7 +151,7 @@ def delete_object(request, app_label, module_name, post_delete_redirect,
fetched using GET; for safty, deletion will only be performed if this fetched using GET; for safty, deletion will only be performed if this
view is POSTed. view is POSTed.
Templates: ``<app_label>/<module_name>_confirm_delete`` Templates: ``<app_label>/<model_name>_confirm_delete``
Context: Context:
object object
the original object being deleted the original object being deleted
@ -163,30 +159,28 @@ def delete_object(request, app_label, module_name, post_delete_redirect,
if login_required and request.user.is_anonymous(): if login_required and request.user.is_anonymous():
return redirect_to_login(request.path) return redirect_to_login(request.path)
mod = models.get_module(app_label, module_name)
# Look up the object to be edited # Look up the object to be edited
lookup_kwargs = {} lookup_kwargs = {}
if object_id: if object_id:
lookup_kwargs['%s__exact' % mod.Klass._meta.pk.name] = object_id lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
elif slug and slug_field: elif slug and slug_field:
lookup_kwargs['%s__exact' % slug_field] = slug lookup_kwargs['%s__exact' % slug_field] = slug
else: else:
raise AttributeError("Generic delete view must be called with either an object_id or a slug/slug_field") raise AttributeError("Generic delete view must be called with either an object_id or a slug/slug_field")
lookup_kwargs.update(extra_lookup_kwargs) lookup_kwargs.update(extra_lookup_kwargs)
try: try:
object = mod.get_object(**lookup_kwargs) object = model._default_manager.get_object(**lookup_kwargs)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs)) raise Http404, "No %s found for %s" % (model._meta.app_label, lookup_kwargs)
if request.META['REQUEST_METHOD'] == 'POST': if request.META['REQUEST_METHOD'] == 'POST':
object.delete() object.delete()
if not request.user.is_anonymous(): if not request.user.is_anonymous():
request.user.add_message("The %s was deleted." % mod.Klass._meta.verbose_name) request.user.add_message("The %s was deleted." % model._meta.verbose_name)
return HttpResponseRedirect(post_delete_redirect) return HttpResponseRedirect(post_delete_redirect)
else: else:
if not template_name: if not template_name:
template_name = "%s/%s_confirm_delete" % (app_label, module_name) template_name = "%s/%s_confirm_delete" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name) t = template_loader.get_template(template_name)
c = DjangoContext(request, { c = DjangoContext(request, {
'object': object, 'object': object,
@ -197,5 +191,5 @@ def delete_object(request, app_label, module_name, post_delete_redirect,
else: else:
c[key] = value c[key] = value
response = HttpResponse(t.render(c)) response = HttpResponse(t.render(c))
populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name)) populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
return response return response

View File

@ -2,41 +2,39 @@ from django.core.template import loader
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.core.extensions import DjangoContext from django.core.extensions import DjangoContext
from django.core.xheaders import populate_xheaders from django.core.xheaders import populate_xheaders
from django.models import get_module
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
import datetime, time import datetime, time
def archive_index(request, app_label, module_name, date_field, num_latest=15, def archive_index(request, model, date_field, num_latest=15,
template_name=None, template_loader=loader, extra_lookup_kwargs={}, template_name=None, template_loader=loader, extra_lookup_kwargs={},
extra_context={}, allow_empty=False, context_processors=None): extra_context={}, allow_empty=False, context_processors=None):
""" """
Generic top-level archive of date-based objects. Generic top-level archive of date-based objects.
Templates: ``<app_label>/<module_name>_archive`` Templates: ``<app_label>/<model_name>_archive``
Context: Context:
date_list date_list
List of years List of years
latest latest
Latest N (defaults to 15) objects by date Latest N (defaults to 15) objects by date
""" """
mod = get_module(app_label, module_name)
lookup_kwargs = {'%s__lte' % date_field: datetime.datetime.now()} lookup_kwargs = {'%s__lte' % date_field: datetime.datetime.now()}
lookup_kwargs.update(extra_lookup_kwargs) lookup_kwargs.update(extra_lookup_kwargs)
date_list = getattr(mod, "get_%s_list" % date_field)('year', **lookup_kwargs)[::-1] date_list = getattr(model._default_manager, "get_%s_list" % date_field)('year', **lookup_kwargs)[::-1]
if not date_list and not allow_empty: if not date_list and not allow_empty:
raise Http404("No %s.%s available" % (app_label, module_name)) raise Http404, "No %s available" % model._meta.verbose_name
if date_list and num_latest: if date_list and num_latest:
lookup_kwargs.update({ lookup_kwargs.update({
'limit': num_latest, 'limit': num_latest,
'order_by': ('-' + date_field,), 'order_by': ('-' + date_field,),
}) })
latest = mod.get_list(**lookup_kwargs) latest = model._default_manager.get_list(**lookup_kwargs)
else: else:
latest = None latest = None
if not template_name: if not template_name:
template_name = "%s/%s_archive" % (app_label, module_name) template_name = "%s/%s_archive" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name) t = template_loader.get_template(template_name)
c = DjangoContext(request, { c = DjangoContext(request, {
'date_list' : date_list, 'date_list' : date_list,
@ -49,31 +47,30 @@ def archive_index(request, app_label, module_name, date_field, num_latest=15,
c[key] = value c[key] = value
return HttpResponse(t.render(c)) return HttpResponse(t.render(c))
def archive_year(request, year, app_label, module_name, date_field, def archive_year(request, year, model, date_field,
template_name=None, template_loader=loader, extra_lookup_kwargs={}, template_name=None, template_loader=loader, extra_lookup_kwargs={},
extra_context={}, context_processors=None): extra_context={}, context_processors=None):
""" """
Generic yearly archive view. Generic yearly archive view.
Templates: ``<app_label>/<module_name>_archive_year`` Templates: ``<app_label>/<model_name>_archive_year``
Context: Context:
date_list date_list
List of months in this year with objects List of months in this year with objects
year year
This year This year
""" """
mod = get_module(app_label, module_name)
now = datetime.datetime.now() now = datetime.datetime.now()
lookup_kwargs = {'%s__year' % date_field: year} lookup_kwargs = {'%s__year' % date_field: year}
# Only bother to check current date if the year isn't in the past. # Only bother to check current date if the year isn't in the past.
if int(year) >= now.year: if int(year) >= now.year:
lookup_kwargs['%s__lte' % date_field] = now lookup_kwargs['%s__lte' % date_field] = now
lookup_kwargs.update(extra_lookup_kwargs) lookup_kwargs.update(extra_lookup_kwargs)
date_list = getattr(mod, "get_%s_list" % date_field)('month', **lookup_kwargs) date_list = getattr(model._default_manager, "get_%s_list" % date_field)('month', **lookup_kwargs)
if not date_list: if not date_list:
raise Http404 raise Http404
if not template_name: if not template_name:
template_name = "%s/%s_archive_year" % (app_label, module_name) template_name = "%s/%s_archive_year" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name) t = template_loader.get_template(template_name)
c = DjangoContext(request, { c = DjangoContext(request, {
'date_list': date_list, 'date_list': date_list,
@ -86,13 +83,13 @@ def archive_year(request, year, app_label, module_name, date_field,
c[key] = value c[key] = value
return HttpResponse(t.render(c)) return HttpResponse(t.render(c))
def archive_month(request, year, month, app_label, module_name, date_field, def archive_month(request, year, month, model, date_field,
month_format='%b', template_name=None, template_loader=loader, month_format='%b', template_name=None, template_loader=loader,
extra_lookup_kwargs={}, extra_context={}, context_processors=None): extra_lookup_kwargs={}, extra_context={}, context_processors=None):
""" """
Generic monthly archive view. Generic monthly archive view.
Templates: ``<app_label>/<module_name>_archive_month`` Templates: ``<app_label>/<model_name>_archive_month``
Context: Context:
month: month:
this month this month
@ -104,7 +101,6 @@ def archive_month(request, year, month, app_label, module_name, date_field,
except ValueError: except ValueError:
raise Http404 raise Http404
mod = get_module(app_label, module_name)
now = datetime.datetime.now() now = datetime.datetime.now()
# Calculate first and last day of month, for use in a date-range lookup. # Calculate first and last day of month, for use in a date-range lookup.
first_day = date.replace(day=1) first_day = date.replace(day=1)
@ -117,11 +113,11 @@ def archive_month(request, year, month, app_label, module_name, date_field,
if last_day >= now.date(): if last_day >= now.date():
lookup_kwargs['%s__lte' % date_field] = now lookup_kwargs['%s__lte' % date_field] = now
lookup_kwargs.update(extra_lookup_kwargs) lookup_kwargs.update(extra_lookup_kwargs)
object_list = mod.get_list(**lookup_kwargs) object_list = model._default_manager.get_list(**lookup_kwargs)
if not object_list: if not object_list:
raise Http404 raise Http404
if not template_name: if not template_name:
template_name = "%s/%s_archive_month" % (app_label, module_name) template_name = "%s/%s_archive_month" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name) t = template_loader.get_template(template_name)
c = DjangoContext(request, { c = DjangoContext(request, {
'object_list': object_list, 'object_list': object_list,
@ -134,14 +130,14 @@ def archive_month(request, year, month, app_label, module_name, date_field,
c[key] = value c[key] = value
return HttpResponse(t.render(c)) return HttpResponse(t.render(c))
def archive_day(request, year, month, day, app_label, module_name, date_field, def archive_day(request, year, month, day, model, date_field,
month_format='%b', day_format='%d', template_name=None, month_format='%b', day_format='%d', template_name=None,
template_loader=loader, extra_lookup_kwargs={}, extra_context={}, template_loader=loader, extra_lookup_kwargs={}, extra_context={},
allow_empty=False, context_processors=None): allow_empty=False, context_processors=None):
""" """
Generic daily archive view. Generic daily archive view.
Templates: ``<app_label>/<module_name>_archive_day`` Templates: ``<app_label>/<model_name>_archive_day``
Context: Context:
object_list: object_list:
list of objects published that day list of objects published that day
@ -157,7 +153,6 @@ def archive_day(request, year, month, day, app_label, module_name, date_field,
except ValueError: except ValueError:
raise Http404 raise Http404
mod = get_module(app_label, module_name)
now = datetime.datetime.now() now = datetime.datetime.now()
lookup_kwargs = { lookup_kwargs = {
'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)), '%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
@ -166,11 +161,11 @@ def archive_day(request, year, month, day, app_label, module_name, date_field,
if date >= now.date(): if date >= now.date():
lookup_kwargs['%s__lte' % date_field] = now lookup_kwargs['%s__lte' % date_field] = now
lookup_kwargs.update(extra_lookup_kwargs) lookup_kwargs.update(extra_lookup_kwargs)
object_list = mod.get_list(**lookup_kwargs) object_list = model._default_manager.get_list(**lookup_kwargs)
if not allow_empty and not object_list: if not allow_empty and not object_list:
raise Http404 raise Http404
if not template_name: if not template_name:
template_name = "%s/%s_archive_day" % (app_label, module_name) template_name = "%s/%s_archive_day" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name) t = template_loader.get_template(template_name)
c = DjangoContext(request, { c = DjangoContext(request, {
'object_list': object_list, 'object_list': object_list,
@ -197,7 +192,7 @@ def archive_today(request, **kwargs):
}) })
return archive_day(request, **kwargs) return archive_day(request, **kwargs)
def object_detail(request, year, month, day, app_label, module_name, date_field, def object_detail(request, year, month, day, model, date_field,
month_format='%b', day_format='%d', object_id=None, slug=None, month_format='%b', day_format='%d', object_id=None, slug=None,
slug_field=None, template_name=None, template_name_field=None, slug_field=None, template_name=None, template_name_field=None,
template_loader=loader, extra_lookup_kwargs={}, extra_context={}, template_loader=loader, extra_lookup_kwargs={}, extra_context={},
@ -205,7 +200,7 @@ def object_detail(request, year, month, day, app_label, module_name, date_field,
""" """
Generic detail view from year/month/day/slug or year/month/day/id structure. Generic detail view from year/month/day/slug or year/month/day/id structure.
Templates: ``<app_label>/<module_name>_detail`` Templates: ``<app_label>/<model_name>_detail``
Context: Context:
object: object:
the object to be detailed the object to be detailed
@ -215,7 +210,6 @@ def object_detail(request, year, month, day, app_label, module_name, date_field,
except ValueError: except ValueError:
raise Http404 raise Http404
mod = get_module(app_label, module_name)
now = datetime.datetime.now() now = datetime.datetime.now()
lookup_kwargs = { lookup_kwargs = {
'%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)), '%s__range' % date_field: (datetime.datetime.combine(date, datetime.time.min), datetime.datetime.combine(date, datetime.time.max)),
@ -224,18 +218,18 @@ def object_detail(request, year, month, day, app_label, module_name, date_field,
if date >= now.date(): if date >= now.date():
lookup_kwargs['%s__lte' % date_field] = now lookup_kwargs['%s__lte' % date_field] = now
if object_id: if object_id:
lookup_kwargs['%s__exact' % mod.Klass._meta.pk.name] = object_id lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
elif slug and slug_field: elif slug and slug_field:
lookup_kwargs['%s__exact' % slug_field] = slug lookup_kwargs['%s__exact' % slug_field] = slug
else: else:
raise AttributeError("Generic detail view must be called with either an object_id or a slug/slugfield") raise AttributeError, "Generic detail view must be called with either an object_id or a slug/slugfield"
lookup_kwargs.update(extra_lookup_kwargs) lookup_kwargs.update(extra_lookup_kwargs)
try: try:
object = mod.get_object(**lookup_kwargs) object = model._default_manager.get_object(**lookup_kwargs)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs)) raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
if not template_name: if not template_name:
template_name = "%s/%s_detail" % (app_label, module_name) template_name = "%s/%s_detail" % (model._meta.app_label, model._meta.object_name.lower())
if template_name_field: if template_name_field:
template_name_list = [getattr(object, template_name_field), template_name] template_name_list = [getattr(object, template_name_field), template_name]
t = template_loader.select_template(template_name_list) t = template_loader.select_template(template_name_list)
@ -250,5 +244,5 @@ def object_detail(request, year, month, day, app_label, module_name, date_field,
else: else:
c[key] = value c[key] = value
response = HttpResponse(t.render(c)) response = HttpResponse(t.render(c))
populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name)) populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
return response return response

View File

@ -1,4 +1,3 @@
from django import models
from django.core.template import loader from django.core.template import loader
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
from django.core.xheaders import populate_xheaders from django.core.xheaders import populate_xheaders
@ -6,13 +5,13 @@ from django.core.extensions import DjangoContext
from django.core.paginator import ObjectPaginator, InvalidPage from django.core.paginator import ObjectPaginator, InvalidPage
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
def object_list(request, app_label, module_name, paginate_by=None, allow_empty=False, def object_list(request, model, paginate_by=None, allow_empty=False,
template_name=None, template_loader=loader, extra_lookup_kwargs={}, template_name=None, template_loader=loader, extra_lookup_kwargs={},
extra_context={}, context_processors=None): extra_context={}, context_processors=None):
""" """
Generic list of objects. Generic list of objects.
Templates: ``<app_label>/<module_name>_list`` Templates: ``<app_label>/<model_name>_list``
Context: Context:
object_list object_list
list of objects list of objects
@ -35,10 +34,9 @@ def object_list(request, app_label, module_name, paginate_by=None, allow_empty=F
hits hits
number of objects, total number of objects, total
""" """
mod = models.get_module(app_label, module_name)
lookup_kwargs = extra_lookup_kwargs.copy() lookup_kwargs = extra_lookup_kwargs.copy()
if paginate_by: if paginate_by:
paginator = ObjectPaginator(mod, lookup_kwargs, paginate_by) paginator = ObjectPaginator(model, lookup_kwargs, paginate_by)
page = request.GET.get('page', 0) page = request.GET.get('page', 0)
try: try:
object_list = paginator.get_page(page) object_list = paginator.get_page(page)
@ -61,7 +59,7 @@ def object_list(request, app_label, module_name, paginate_by=None, allow_empty=F
'hits' : paginator.hits, 'hits' : paginator.hits,
}, context_processors) }, context_processors)
else: else:
object_list = mod.get_list(**lookup_kwargs) object_list = model._default_manager.get_list(**lookup_kwargs)
c = DjangoContext(request, { c = DjangoContext(request, {
'object_list': object_list, 'object_list': object_list,
'is_paginated': False 'is_paginated': False
@ -74,37 +72,36 @@ def object_list(request, app_label, module_name, paginate_by=None, allow_empty=F
else: else:
c[key] = value c[key] = value
if not template_name: if not template_name:
template_name = "%s/%s_list" % (app_label, module_name) template_name = "%s/%s_list" % (model._meta.app_label, model._meta.object_name.lower())
t = template_loader.get_template(template_name) t = template_loader.get_template(template_name)
return HttpResponse(t.render(c)) return HttpResponse(t.render(c))
def object_detail(request, app_label, module_name, object_id=None, slug=None, def object_detail(request, model, object_id=None, slug=None,
slug_field=None, template_name=None, template_name_field=None, slug_field=None, template_name=None, template_name_field=None,
template_loader=loader, extra_lookup_kwargs={}, extra_context={}, template_loader=loader, extra_lookup_kwargs={}, extra_context={},
context_processors=None): context_processors=None):
""" """
Generic list of objects. Generic list of objects.
Templates: ``<app_label>/<module_name>_detail`` Templates: ``<app_label>/<model_name>_detail``
Context: Context:
object object
the object the object
""" """
mod = models.get_module(app_label, module_name)
lookup_kwargs = {} lookup_kwargs = {}
if object_id: if object_id:
lookup_kwargs['pk'] = object_id lookup_kwargs['pk'] = object_id
elif slug and slug_field: elif slug and slug_field:
lookup_kwargs['%s__exact' % slug_field] = slug lookup_kwargs['%s__exact' % slug_field] = slug
else: else:
raise AttributeError("Generic detail view must be called with either an object_id or a slug/slug_field") raise AttributeError, "Generic detail view must be called with either an object_id or a slug/slug_field."
lookup_kwargs.update(extra_lookup_kwargs) lookup_kwargs.update(extra_lookup_kwargs)
try: try:
object = mod.get_object(**lookup_kwargs) object = model._default_manager.get_object(**lookup_kwargs)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs)) raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
if not template_name: if not template_name:
template_name = "%s/%s_detail" % (app_label, module_name) template_name = "%s/%s_detail" % (model._meta.app_label, model._meta.object_name.lower())
if template_name_field: if template_name_field:
template_name_list = [getattr(object, template_name_field), template_name] template_name_list = [getattr(object, template_name_field), template_name]
t = template_loader.select_template(template_name_list) t = template_loader.select_template(template_name_list)
@ -119,5 +116,5 @@ def object_detail(request, app_label, module_name, object_id=None, slug=None,
else: else:
c[key] = value c[key] = value
response = HttpResponse(t.render(c)) response = HttpResponse(t.render(c))
populate_xheaders(request, response, app_label, module_name, getattr(object, object._meta.pk.name)) populate_xheaders(request, response, model, getattr(object, object._meta.pk.name))
return response return response

View File

@ -5,7 +5,7 @@ Using generic views
Writing Web applications can be monotonous, because we repeat certain patterns Writing Web applications can be monotonous, because we repeat certain patterns
again and again. In Django, the most common of these patterns have been again and again. In Django, the most common of these patterns have been
abstracted into "generic views" that let you quickly provide common views of abstracted into "generic views" that let you quickly provide common views of
an object without actually needing to write any views. an object without actually needing to write any Python code.
Django's generic views contain the following: Django's generic views contain the following:
@ -32,10 +32,10 @@ URLconf tuple. For example, here's the URLconf for the simple weblog app that
drives the blog on djangoproject.com:: drives the blog on djangoproject.com::
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
from django_website.apps.blog.models import Entry
info_dict = { info_dict = {
'app_label': 'blog', 'model': Entry,
'module_name': 'entries',
'date_field': 'pub_date', 'date_field': 'pub_date',
} }
@ -47,26 +47,18 @@ drives the blog on djangoproject.com::
(r'^/?$', 'archive_index', info_dict), (r'^/?$', 'archive_index', info_dict),
) )
As you can see, this URLconf defines a few options in ``info_dict`` that tell As you can see, this URLconf defines a few options in ``info_dict``. ``'model'``
the generic view which model to use (``blog.entries`` in this case), as well as tells the generic view which model to use (``Entry``, in this case), as well as
some extra information. some extra information.
Documentation of each generic view follows, along with a list of all keyword Documentation of each generic view follows, along with a list of all keyword
arguments that a generic view expects. Remember that as in the example above, arguments that a generic view expects. Remember that as in the example above,
arguments may either come from the URL pattern (as ``month``, ``day``, arguments may either come from the URL pattern (as ``month``, ``day``,
``year``, etc. do above) or from the additional-information dictionary (as for ``year``, etc. do above) or from the additional-information dictionary (as for
``app_label``, ``module_name``, etc.). ``model``, ``date_field``, etc.).
Most of the generic views that follow require the ``app_label`` and Most generic views require the ``model`` key, which is your model class (*not*
``module_name`` keys. These values are easiest to explain through example:: an instance of the class).
>>> from django.models.blog import entries
In the above line, ``blog`` is the ``app_label`` (the name of the file that
holds all your model definitions) and ``entries`` is the ``module_name``
(either a pluralized, lowercased version of the model class name, or the value
of the ``module_name`` option of your model). In the docs below, these keys
will not be repeated, but each generic view requires them.
Using "simple" generic views Using "simple" generic views
============================ ============================
@ -109,10 +101,9 @@ Using date-based generic views
============================== ==============================
Date-based generic views (in the module ``django.views.generic.date_based``) Date-based generic views (in the module ``django.views.generic.date_based``)
feature six functions for dealing with date-based data. Besides ``app_label`` feature six functions for dealing with date-based data. Besides ``model``, all
and ``module_name``, all date-based generic views require that the date-based generic views require the ``date_field`` argument. This is the name
``date_field`` argument be passed to them. This is the name of the field that of the field that stores the date the objects should key off of.
stores the date the objects should key off of.
Additionally, all date-based generic views have the following optional Additionally, all date-based generic views have the following optional
arguments: arguments:
@ -155,7 +146,14 @@ The date-based generic functions are:
an empty index page. ``False`` is default. an empty index page. ``False`` is default.
======================= ================================================= ======================= =================================================
Uses the template ``app_label/module_name_archive`` by default. Uses the template ``<app_label>/<model_name>_archive`` by default, where:
* ``<model_name>`` is your model's name in all lowercase. For a model
``StaffMember``, that'd be ``staffmember``.
* ``<app_label>`` is the right-most part of the full Python path to
your model's app. For example, if your model lives in
``apps/blog/models.py``, that'd be ``blog``.
Has the following template context: Has the following template context:
@ -168,7 +166,7 @@ The date-based generic functions are:
Yearly archive. Requires that the ``year`` argument be present in the URL Yearly archive. Requires that the ``year`` argument be present in the URL
pattern. pattern.
Uses the template ``app_label/module_name_archive_year`` by default. Uses the template ``<app_label>/<model_name>_archive_year`` by default.
Has the following template context: Has the following template context:
@ -187,7 +185,7 @@ The date-based generic functions are:
default, which is a three-letter month abbreviation. To change it to use default, which is a three-letter month abbreviation. To change it to use
numbers, use ``"%m"``. numbers, use ``"%m"``.
Uses the template ``app_label/module_name_archive_month`` by default. Uses the template ``<app_label>/<model_name>_archive_month`` by default.
Has the following template context: Has the following template context:
@ -204,7 +202,7 @@ The date-based generic functions are:
also pass ``day_format``, which defaults to ``"%d"`` (day of the month as a also pass ``day_format``, which defaults to ``"%d"`` (day of the month as a
decimal number, 1-31). decimal number, 1-31).
Uses the template ``app_label/module_name_archive_day`` by default. Uses the template ``<app_label>/<model_name>_archive_day`` by default.
Has the following template context: Has the following template context:
@ -274,7 +272,7 @@ Individual views are:
an empty index page. ``False`` is default. an empty index page. ``False`` is default.
======================= ================================================= ======================= =================================================
Uses the template ``app_label/module_name_list`` by default. Uses the template ``<app_label>/<model_name>_list`` by default.
Has the following template context: Has the following template context:
@ -327,7 +325,7 @@ The create/update/delete views are:
be interpolated against the object's field attributes. For example, you be interpolated against the object's field attributes. For example, you
could use ``post_save_redirect="/polls/%(slug)s/"``. could use ``post_save_redirect="/polls/%(slug)s/"``.
Uses the template ``app_label/module_name_form`` by default. This is the Uses the template ``<app_label>/<model_name>_form`` by default. This is the
same template as the ``update_object`` view below. Your template can tell same template as the ``update_object`` view below. Your template can tell
the different by the presence or absence of ``{{ object }}`` in the the different by the presence or absence of ``{{ object }}`` in the
context. context.
@ -349,7 +347,7 @@ The create/update/delete views are:
``list_detail.object_detail`` does (see above), and the same ``list_detail.object_detail`` does (see above), and the same
``post_save_redirect`` as ``create_object`` does. ``post_save_redirect`` as ``create_object`` does.
Uses the template ``app_label/module_name_form`` by default. Uses the template ``<app_label>/<model_name>_form`` by default.
Has the following template context: Has the following template context:
@ -368,7 +366,7 @@ The create/update/delete views are:
that the view knows where to go after the object is deleted. that the view knows where to go after the object is deleted.
If fetched with GET, it uses the template If fetched with GET, it uses the template
``app_label/module_name_confirm_delete`` by default. It uses no template ``<app_label>/<model_name>_confirm_delete`` by default. It uses no template
if POSTed -- it simply deletes the object and redirects. if POSTed -- it simply deletes the object and redirects.
Has the following template context: Has the following template context: