mirror of
https://github.com/django/django.git
synced 2025-06-07 12:39:12 +00:00
magic-removal: The start of changes to admin code. Moved views/changelist to views/main. Refactored URLs to use old-style app_label/model_name. Removed a lot of cruft that was necessary due to non-app_label/model name URLs.
git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2062 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
8a140005ff
commit
71e2df77d3
@ -2,7 +2,7 @@
|
|||||||
{% load adminmedia admin_list i18n breadcrumbs %}
|
{% load adminmedia admin_list i18n breadcrumbs %}
|
||||||
{% block bodyclass %}change-list{% endblock %}
|
{% block bodyclass %}change-list{% endblock %}
|
||||||
{% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / <a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
{% block userlinks %}<a href="../../doc/">{% trans 'Documentation' %}</a> / <a href="../../password_change/">{% trans 'Change password' %}</a> / <a href="../../logout/">{% trans 'Log out' %}</a>{% endblock %}
|
||||||
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs">{% path_breadcrumbs path "Home" "1" "0" %}</div>{% endblock %}{% endif %}
|
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs">BREADCRUMBS</div>{% endblock %}{% endif %}
|
||||||
{% block coltype %}flex{% endblock %}
|
{% block coltype %}flex{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="content-main">
|
<div id="content-main">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from django.contrib.admin.views.changelist import MAX_SHOW_ALL_ALLOWED, DEFAULT_RESULTS_PER_PAGE, ALL_VAR
|
|
||||||
from django.contrib.admin.views.changelist import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR
|
|
||||||
from django.contrib.admin.views.changelist import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE, MONTHS
|
|
||||||
from django import template
|
from django import template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, DEFAULT_RESULTS_PER_PAGE, ALL_VAR
|
||||||
|
from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR
|
||||||
|
from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE, MONTHS
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import dateformat
|
from django.utils import dateformat
|
||||||
|
@ -22,9 +22,9 @@ urlpatterns = patterns('',
|
|||||||
('^doc/templates/(?P<template>.*)/$', 'django.contrib.admin.views.doc.template_detail'),
|
('^doc/templates/(?P<template>.*)/$', 'django.contrib.admin.views.doc.template_detail'),
|
||||||
|
|
||||||
# Add/change/delete/history
|
# Add/change/delete/history
|
||||||
('^((?:[^/]+/)+?)add/$', 'django.contrib.admin.views.main.add_stage'),
|
('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'),
|
||||||
('^((?:[^/]+/)+?)([^/]+)/history/$', 'django.contrib.admin.views.main.history'),
|
('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
|
||||||
('^((?:[^/]+/)+?)([^/]+)/delete/$', 'django.contrib.admin.views.main.delete_stage'),
|
('^([^/]+)/([^/]+)/(.+)/history/$', 'django.contrib.admin.views.main.history'),
|
||||||
('^((?:[^/]+/)+?)([^/]+)/change/$', 'django.contrib.admin.views.main.change_stage'),
|
('^([^/]+)/([^/]+)/(.+)/delete/$', 'django.contrib.admin.views.main.delete_stage'),
|
||||||
('^((?:[^/]+/)+?)$', 'django.contrib.admin.views.changelist.change_list'),
|
('^([^/]+)/([^/]+)/(.+)/$', 'django.contrib.admin.views.main.change_stage'),
|
||||||
)
|
)
|
||||||
|
@ -1,226 +0,0 @@
|
|||||||
from django.contrib.admin.views.decorators import staff_member_required
|
|
||||||
from django.contrib.admin.views.main import get_model_and_app
|
|
||||||
from django.contrib.admin.filterspecs import FilterSpec
|
|
||||||
from django.db import models
|
|
||||||
from django.db.models.query import handle_legacy_orderlist
|
|
||||||
from django.http import HttpResponse, HttpResponseRedirect
|
|
||||||
from django.core.paginator import ObjectPaginator, InvalidPage
|
|
||||||
from django.template import RequestContext as Context
|
|
||||||
from django.shortcuts import render_to_response
|
|
||||||
from django.utils.dates import MONTHS
|
|
||||||
|
|
||||||
# The system will display a "Show all" link only if the total result count
|
|
||||||
# is less than or equal to this setting.
|
|
||||||
MAX_SHOW_ALL_ALLOWED = 200
|
|
||||||
|
|
||||||
DEFAULT_RESULTS_PER_PAGE = 100
|
|
||||||
|
|
||||||
ALL_VAR = 'all'
|
|
||||||
ORDER_VAR = 'o'
|
|
||||||
ORDER_TYPE_VAR = 'ot'
|
|
||||||
PAGE_VAR = 'p'
|
|
||||||
SEARCH_VAR = 'q'
|
|
||||||
IS_POPUP_VAR = 'pop'
|
|
||||||
|
|
||||||
# Text to display within changelist table cells if the value is blank.
|
|
||||||
EMPTY_CHANGELIST_VALUE = '(None)'
|
|
||||||
|
|
||||||
class IncorrectLookupParameters(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class ChangeList(object):
|
|
||||||
def __init__(self, request, path):
|
|
||||||
self.resolve_model(path, request)
|
|
||||||
self.get_search_parameters(request)
|
|
||||||
self.get_ordering()
|
|
||||||
self.query = request.GET.get(SEARCH_VAR, '')
|
|
||||||
self.get_lookup_params()
|
|
||||||
self.get_results(request)
|
|
||||||
self.title = (self.is_popup
|
|
||||||
and _('Select %s') % self.opts.verbose_name
|
|
||||||
or _('Select %s to change') % self.opts.verbose_name)
|
|
||||||
self.get_filters(request)
|
|
||||||
self.pk_attname = self.lookup_opts.pk.attname
|
|
||||||
|
|
||||||
def get_filters(self, request):
|
|
||||||
self.filter_specs = []
|
|
||||||
if self.lookup_opts.admin.list_filter and not self.opts.one_to_one_field:
|
|
||||||
filter_fields = [self.lookup_opts.get_field(field_name) \
|
|
||||||
for field_name in self.lookup_opts.admin.list_filter]
|
|
||||||
for f in filter_fields:
|
|
||||||
spec = FilterSpec.create(f, request, self.params)
|
|
||||||
if spec and spec.has_output():
|
|
||||||
self.filter_specs.append(spec)
|
|
||||||
self.has_filters = bool(self.filter_specs)
|
|
||||||
|
|
||||||
def get_query_string(self, new_params={}, remove=[]):
|
|
||||||
p = self.params.copy()
|
|
||||||
for r in remove:
|
|
||||||
for k in p.keys():
|
|
||||||
if k.startswith(r):
|
|
||||||
del p[k]
|
|
||||||
for k, v in new_params.items():
|
|
||||||
if p.has_key(k) and v is None:
|
|
||||||
del p[k]
|
|
||||||
elif v is not None:
|
|
||||||
p[k] = v
|
|
||||||
return '?' + '&'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
|
|
||||||
|
|
||||||
def resolve_model(self, path, request):
|
|
||||||
self.model, self.app_label = get_model_and_app(path)
|
|
||||||
self.opts = self.model._meta
|
|
||||||
|
|
||||||
if not request.user.has_perm(self.app_label + '.' + self.opts.get_change_permission()):
|
|
||||||
raise PermissionDenied
|
|
||||||
|
|
||||||
self.lookup_opts = self.opts
|
|
||||||
self.manager = self.model._default_manager
|
|
||||||
|
|
||||||
def get_search_parameters(self, request):
|
|
||||||
# Get search parameters from the query string.
|
|
||||||
try:
|
|
||||||
self.page_num = int(request.GET.get(PAGE_VAR, 0))
|
|
||||||
except ValueError:
|
|
||||||
self.page_num = 0
|
|
||||||
self.show_all = request.GET.has_key(ALL_VAR)
|
|
||||||
self.is_popup = request.GET.has_key(IS_POPUP_VAR)
|
|
||||||
self.params = dict(request.GET.items())
|
|
||||||
if self.params.has_key(PAGE_VAR):
|
|
||||||
del self.params[PAGE_VAR]
|
|
||||||
|
|
||||||
def get_results(self, request):
|
|
||||||
manager, lookup_params, show_all, page_num = \
|
|
||||||
self.manager, self.lookup_params, self.show_all, self.page_num
|
|
||||||
# Get the results.
|
|
||||||
try:
|
|
||||||
paginator = ObjectPaginator(manager, lookup_params, DEFAULT_RESULTS_PER_PAGE)
|
|
||||||
# Naked except! Because we don't have any other way of validating "params".
|
|
||||||
# They might be invalid if the keyword arguments are incorrect, or if the
|
|
||||||
# values are not in the correct type (which would result in a database
|
|
||||||
# error).
|
|
||||||
except Exception:
|
|
||||||
raise
|
|
||||||
raise IncorrectLookupParameters()
|
|
||||||
|
|
||||||
# Get the total number of objects, with no filters applied.
|
|
||||||
real_lookup_params = lookup_params.copy()
|
|
||||||
del real_lookup_params['order_by']
|
|
||||||
if real_lookup_params:
|
|
||||||
full_result_count = manager.get_count()
|
|
||||||
else:
|
|
||||||
full_result_count = paginator.hits
|
|
||||||
del real_lookup_params
|
|
||||||
result_count = paginator.hits
|
|
||||||
can_show_all = result_count <= MAX_SHOW_ALL_ALLOWED
|
|
||||||
multi_page = result_count > DEFAULT_RESULTS_PER_PAGE
|
|
||||||
|
|
||||||
# Get the list of objects to display on this page.
|
|
||||||
if (show_all and can_show_all) or not multi_page:
|
|
||||||
result_list = manager.get_list(**lookup_params)
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
result_list = paginator.get_page(page_num)
|
|
||||||
except InvalidPage:
|
|
||||||
result_list = []
|
|
||||||
(self.result_count, self.full_result_count, self.result_list,
|
|
||||||
self.can_show_all, self.multi_page, self.paginator) = (result_count,
|
|
||||||
full_result_count, result_list, can_show_all, multi_page, paginator )
|
|
||||||
|
|
||||||
def url_for_result(self, result):
|
|
||||||
return "%s/change/" % getattr(result, self.pk_attname)
|
|
||||||
|
|
||||||
def get_ordering(self):
|
|
||||||
lookup_opts, params = self.lookup_opts, self.params
|
|
||||||
# For ordering, first check the "ordering" parameter in the admin options,
|
|
||||||
# then check the object's default ordering. If neither of those exist,
|
|
||||||
# order descending by ID by default. Finally, look for manually-specified
|
|
||||||
# ordering from the query string.
|
|
||||||
ordering = lookup_opts.admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name]
|
|
||||||
|
|
||||||
# Normalize it to new-style ordering.
|
|
||||||
ordering = handle_legacy_orderlist(ordering)
|
|
||||||
|
|
||||||
if ordering[0].startswith('-'):
|
|
||||||
order_field, order_type = ordering[0][1:], 'desc'
|
|
||||||
else:
|
|
||||||
order_field, order_type = ordering[0], 'asc'
|
|
||||||
if params.has_key(ORDER_VAR):
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
f = lookup_opts.get_field(lookup_opts.admin.list_display[int(params[ORDER_VAR])])
|
|
||||||
except models.FieldDoesNotExist:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if not isinstance(f.rel, models.ManyToOne) or not f.null:
|
|
||||||
order_field = f.name
|
|
||||||
except (IndexError, ValueError):
|
|
||||||
pass # Invalid ordering specified. Just use the default.
|
|
||||||
if params.has_key(ORDER_TYPE_VAR) and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
|
|
||||||
order_type = params[ORDER_TYPE_VAR]
|
|
||||||
self.order_field, self.order_type = order_field, order_type
|
|
||||||
|
|
||||||
def get_lookup_params(self):
|
|
||||||
# Prepare the lookup parameters for the API lookup.
|
|
||||||
(params, order_field, lookup_opts, order_type, opts, query) = \
|
|
||||||
(self.params, self.order_field, self.lookup_opts, self.order_type, self.opts, self.query)
|
|
||||||
|
|
||||||
lookup_params = params.copy()
|
|
||||||
for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR):
|
|
||||||
if lookup_params.has_key(i):
|
|
||||||
del lookup_params[i]
|
|
||||||
# If the order-by field is a field with a relationship, order by the value
|
|
||||||
# in the related table.
|
|
||||||
lookup_order_field = order_field
|
|
||||||
try:
|
|
||||||
f = lookup_opts.get_field(order_field)
|
|
||||||
except models.FieldDoesNotExist:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if isinstance(lookup_opts.get_field(order_field).rel, models.ManyToOne):
|
|
||||||
f = lookup_opts.get_field(order_field)
|
|
||||||
rel_ordering = f.rel.to._meta.ordering and f.rel.to._meta.ordering[0] or f.rel.to._meta.pk.column
|
|
||||||
lookup_order_field = '%s.%s' % (f.rel.to._meta.db_table, rel_ordering)
|
|
||||||
# Use select_related if one of the list_display options is a field with a
|
|
||||||
# relationship.
|
|
||||||
if lookup_opts.admin.list_select_related:
|
|
||||||
lookup_params['select_related'] = True
|
|
||||||
else:
|
|
||||||
for field_name in lookup_opts.admin.list_display:
|
|
||||||
try:
|
|
||||||
f = lookup_opts.get_field(field_name)
|
|
||||||
except models.FieldDoesNotExist:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if isinstance(f.rel, models.ManyToOne):
|
|
||||||
lookup_params['select_related'] = True
|
|
||||||
break
|
|
||||||
lookup_params['order_by'] = ((order_type == 'desc' and '-' or '') + lookup_order_field,)
|
|
||||||
if lookup_opts.admin.search_fields and query:
|
|
||||||
complex_queries = []
|
|
||||||
for bit in query.split():
|
|
||||||
or_queries = []
|
|
||||||
for field_name in lookup_opts.admin.search_fields:
|
|
||||||
or_queries.append(models.Q(**{'%s__icontains' % field_name: bit}))
|
|
||||||
complex_queries.append(reduce(operator.or_, or_queries))
|
|
||||||
lookup_params['complex'] = reduce(operator.and_, complex_queries)
|
|
||||||
if opts.one_to_one_field:
|
|
||||||
lookup_params.update(opts.one_to_one_field.rel.limit_choices_to)
|
|
||||||
self.lookup_params = lookup_params
|
|
||||||
|
|
||||||
def change_list(request, path):
|
|
||||||
try:
|
|
||||||
cl = ChangeList(request, path)
|
|
||||||
except IncorrectLookupParameters:
|
|
||||||
return HttpResponseRedirect(request.path)
|
|
||||||
|
|
||||||
c = Context(request, {
|
|
||||||
'title': cl.title,
|
|
||||||
'is_popup': cl.is_popup,
|
|
||||||
'cl': cl,
|
|
||||||
'path': path[:path.rindex('/')]
|
|
||||||
})
|
|
||||||
c.update({'has_add_permission': c['perms'][cl.app_label][cl.opts.get_add_permission()]}),
|
|
||||||
return render_to_response(['admin/%s/%s/change_list' % (cl.app_label, cl.opts.object_name.lower()),
|
|
||||||
'admin/%s/change_list' % cl.app_label,
|
|
||||||
'admin/change_list'], context_instance=c)
|
|
||||||
change_list = staff_member_required(change_list)
|
|
@ -1,81 +1,54 @@
|
|||||||
from django import forms, template
|
from django import forms, template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.admin.filterspecs import FilterSpec
|
||||||
from django.contrib.admin.views.decorators import staff_member_required
|
from django.contrib.admin.views.decorators import staff_member_required
|
||||||
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist, PermissionDenied
|
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist, PermissionDenied
|
||||||
|
from django.core.paginator import ObjectPaginator, InvalidPage
|
||||||
from django.shortcuts import get_object_or_404, render_to_response
|
from django.shortcuts import get_object_or_404, render_to_response
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.fields import BoundField, BoundFieldLine, BoundFieldSet
|
from django.db.models.fields import BoundField, BoundFieldLine, BoundFieldSet
|
||||||
|
from django.db.models.query import handle_legacy_orderlist
|
||||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
from django.utils import dateformat
|
from django.utils import dateformat
|
||||||
|
from django.utils.dates import MONTHS
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.text import capfirst, get_text_list
|
from django.utils.text import capfirst, get_text_list
|
||||||
import operator
|
import operator
|
||||||
from itertools import izip
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
|
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImproperlyConfigured, "You don't have 'django.contrib.admin' in INSTALLED_APPS."
|
raise ImproperlyConfigured, "You don't have 'django.contrib.admin' in INSTALLED_APPS."
|
||||||
|
|
||||||
ADMIN_PREFIX = "/admin/"
|
# The system will display a "Show all" link on the change list only if the
|
||||||
|
# total result count is less than or equal to this setting.
|
||||||
|
MAX_SHOW_ALL_ALLOWED = 200
|
||||||
|
|
||||||
|
# Changelist settings
|
||||||
|
DEFAULT_RESULTS_PER_PAGE = 100
|
||||||
|
ALL_VAR = 'all'
|
||||||
|
ORDER_VAR = 'o'
|
||||||
|
ORDER_TYPE_VAR = 'ot'
|
||||||
|
PAGE_VAR = 'p'
|
||||||
|
SEARCH_VAR = 'q'
|
||||||
|
IS_POPUP_VAR = 'pop'
|
||||||
|
|
||||||
|
# Text to display within change-list table cells if the value is blank.
|
||||||
|
EMPTY_CHANGELIST_VALUE = '(None)'
|
||||||
|
|
||||||
use_raw_id_admin = lambda field: isinstance(field.rel, (models.ManyToOne, models.ManyToMany)) and field.rel.raw_id_admin
|
use_raw_id_admin = lambda field: isinstance(field.rel, (models.ManyToOne, models.ManyToMany)) and field.rel.raw_id_admin
|
||||||
|
|
||||||
def matches_app(mod, comps):
|
class IncorrectLookupParameters(Exception):
|
||||||
modcomps = mod.__name__.split('.')[:-1] #HACK: leave off 'models'
|
pass
|
||||||
for c, mc in izip(comps, modcomps):
|
|
||||||
if c != mc:
|
|
||||||
return [], False
|
|
||||||
return comps[len(modcomps):], True
|
|
||||||
|
|
||||||
def find_model(mod, remaining):
|
def get_model(app_label, model_name):
|
||||||
if len(remaining) == 0:
|
for module in models.get_installed_models():
|
||||||
raise Http404
|
if module.__name__.split('.')[-2] == app_label: # TODO: Refactor this logic.
|
||||||
if len(remaining) == 1:
|
for model in getattr(module, '_MODELS', ()):
|
||||||
if hasattr(mod, '_MODELS'):
|
if model._meta.object_name.lower() == model_name:
|
||||||
name = remaining[0]
|
|
||||||
for model in mod._MODELS:
|
|
||||||
if model.__name__.lower() == name:
|
|
||||||
return model
|
return model
|
||||||
raise Http404
|
raise Http404, "App %r, model %r, not found" % (app_label, model_name)
|
||||||
else:
|
|
||||||
raise Http404
|
|
||||||
else:
|
|
||||||
child = getattr(mod, remaining[0], None)
|
|
||||||
if child:
|
|
||||||
return find_model(child, remaining[1:])
|
|
||||||
else:
|
|
||||||
raise Http404
|
|
||||||
|
|
||||||
def get_app_label(mod):
|
|
||||||
#HACK
|
|
||||||
return mod.__name__.split('.')[-2]
|
|
||||||
|
|
||||||
def get_model_and_app(path):
|
|
||||||
comps = path.split('/')
|
|
||||||
comps = comps[:-1] # remove '' after final /
|
|
||||||
for mod in models.get_installed_models():
|
|
||||||
remaining, matched = matches_app(mod, comps)
|
|
||||||
if matched and len(remaining) > 0:
|
|
||||||
return (find_model(mod, remaining), get_app_label(mod))
|
|
||||||
raise Http404 # Couldn't find app
|
|
||||||
|
|
||||||
_model_urls = {}
|
|
||||||
|
|
||||||
def url_for_model(model):
|
|
||||||
try:
|
|
||||||
return _model_urls[model]
|
|
||||||
except KeyError:
|
|
||||||
comps = model.__module__.split('.')
|
|
||||||
for mod in models.get_installed_models():
|
|
||||||
remaining, matched = matches_app(mod, comps)
|
|
||||||
if matched and len(remaining) > 0:
|
|
||||||
comps = comps[:-len(remaining)] + remaining[1:]
|
|
||||||
url = "%s%s/%s/" % (ADMIN_PREFIX, '/'.join(comps) , model.__name__.lower())
|
|
||||||
_model_urls[model] = url
|
|
||||||
return url
|
|
||||||
raise ImproperlyConfigured, '%s is not a model in an installed app' % model.__name__
|
|
||||||
|
|
||||||
def get_javascript_imports(opts, auto_populated_fields, ordered_objects, field_sets):
|
def get_javascript_imports(opts, auto_populated_fields, ordered_objects, field_sets):
|
||||||
# Put in any necessary JavaScript imports.
|
# Put in any necessary JavaScript imports.
|
||||||
@ -127,7 +100,7 @@ class AdminBoundField(BoundField):
|
|||||||
self._repr_filled = False
|
self._repr_filled = False
|
||||||
|
|
||||||
if field.rel:
|
if field.rel:
|
||||||
self.related_url = url_for_model(field.rel.to)
|
self.related_url = '../../../%s/%s/' % (field.rel.to._meta.app_label, field.rel.to._meta.object_name.lower())
|
||||||
|
|
||||||
def existing_display(self):
|
def existing_display(self):
|
||||||
try:
|
try:
|
||||||
@ -222,8 +195,8 @@ def index(request):
|
|||||||
return render_to_response('admin/index', {'title': _('Site administration')}, context_instance=template.RequestContext(request))
|
return render_to_response('admin/index', {'title': _('Site administration')}, context_instance=template.RequestContext(request))
|
||||||
index = staff_member_required(index)
|
index = staff_member_required(index)
|
||||||
|
|
||||||
def add_stage(request, path, show_delete=False, form_url='', post_url='../', post_url_continue='../%s/change', object_id_override=None):
|
def add_stage(request, app_label, model_name, show_delete=False, form_url='', post_url='../', post_url_continue='../%s/change', object_id_override=None):
|
||||||
model, app_label = get_model_and_app(path)
|
model = get_model(app_label, model_name)
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
|
|
||||||
if not request.user.has_perm(app_label + '.' + opts.get_add_permission()):
|
if not request.user.has_perm(app_label + '.' + opts.get_add_permission()):
|
||||||
@ -289,7 +262,6 @@ def add_stage(request, path, show_delete=False, form_url='', post_url='../', pos
|
|||||||
'form': form,
|
'form': form,
|
||||||
'is_popup': request.REQUEST.has_key('_popup'),
|
'is_popup': request.REQUEST.has_key('_popup'),
|
||||||
'show_delete': show_delete,
|
'show_delete': show_delete,
|
||||||
'path': path ,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if object_id_override is not None:
|
if object_id_override is not None:
|
||||||
@ -298,13 +270,13 @@ def add_stage(request, path, show_delete=False, form_url='', post_url='../', pos
|
|||||||
return render_change_form(model, manipulator, app_label, c, add=True)
|
return render_change_form(model, manipulator, app_label, c, add=True)
|
||||||
add_stage = staff_member_required(add_stage)
|
add_stage = staff_member_required(add_stage)
|
||||||
|
|
||||||
def change_stage(request, path, object_id):
|
def change_stage(request, app_label, model_name, object_id):
|
||||||
model, app_label = get_model_and_app(path)
|
model = get_model(app_label, model_name)
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
if not request.user.has_perm(app_label + '.' + opts.get_change_permission()):
|
if not request.user.has_perm(app_label + '.' + opts.get_change_permission()):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
if request.POST and request.POST.has_key("_saveasnew"):
|
if request.POST and request.POST.has_key("_saveasnew"):
|
||||||
return add_stage(request, path, form_url='../../add/')
|
return add_stage(request, app_label, model_name, form_url='../../add/')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
manipulator = model.ChangeManipulator(object_id)
|
manipulator = model.ChangeManipulator(object_id)
|
||||||
@ -384,7 +356,6 @@ def change_stage(request, path, object_id):
|
|||||||
'object_id': object_id,
|
'object_id': object_id,
|
||||||
'original': manipulator.original_object,
|
'original': manipulator.original_object,
|
||||||
'is_popup': request.REQUEST.has_key('_popup'),
|
'is_popup': request.REQUEST.has_key('_popup'),
|
||||||
'path': path,
|
|
||||||
})
|
})
|
||||||
return render_change_form(model, manipulator, app_label, c, change=True)
|
return render_change_form(model, manipulator, app_label, c, change=True)
|
||||||
change_stage = staff_member_required(change_stage)
|
change_stage = staff_member_required(change_stage)
|
||||||
@ -473,9 +444,9 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
|
|||||||
if not user.has_perm(p):
|
if not user.has_perm(p):
|
||||||
perms_needed.add(related.opts.verbose_name)
|
perms_needed.add(related.opts.verbose_name)
|
||||||
|
|
||||||
def delete_stage(request, path, object_id):
|
def delete_stage(request, app_label, model_name, object_id):
|
||||||
import sets
|
import sets
|
||||||
model, app_label = get_model_and_app(path)
|
model = get_model(app_label, model_name)
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
if not request.user.has_perm(app_label + '.' + opts.get_delete_permission()):
|
if not request.user.has_perm(app_label + '.' + opts.get_delete_permission()):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
@ -504,15 +475,206 @@ def delete_stage(request, path, object_id):
|
|||||||
}, context_instance=template.RequestContext(request))
|
}, context_instance=template.RequestContext(request))
|
||||||
delete_stage = staff_member_required(delete_stage)
|
delete_stage = staff_member_required(delete_stage)
|
||||||
|
|
||||||
def history(request, app_label, module_name, object_id):
|
def history(request, app_label, model_name, object_id):
|
||||||
action_list = LogEntry.objects.get_list(object_id__exact=object_id, content_type__id__exact=opts.get_content_type_id(),
|
model = get_model(app_label, model_name)
|
||||||
|
action_list = LogEntry.objects.get_list(object_id__exact=object_id, content_type__id__exact=model._meta.get_content_type_id(),
|
||||||
order_by=("action_time",), select_related=True)
|
order_by=("action_time",), select_related=True)
|
||||||
# If no history was found, see whether this object even exists.
|
# If no history was found, see whether this object even exists.
|
||||||
obj = get_object_or_404(mod, pk=object_id)
|
obj = get_object_or_404(model, pk=object_id)
|
||||||
return render_to_response('admin/object_history', {
|
return render_to_response('admin/object_history', {
|
||||||
'title': _('Change history: %s') % obj,
|
'title': _('Change history: %s') % obj,
|
||||||
'action_list': action_list,
|
'action_list': action_list,
|
||||||
'module_name': capfirst(opts.verbose_name_plural),
|
'module_name': capfirst(model._meta.verbose_name_plural),
|
||||||
'object': obj,
|
'object': obj,
|
||||||
}, context_instance=template.RequestContext(request))
|
}, context_instance=template.RequestContext(request))
|
||||||
history = staff_member_required(history)
|
history = staff_member_required(history)
|
||||||
|
|
||||||
|
class ChangeList(object):
|
||||||
|
def __init__(self, request, model):
|
||||||
|
self.model = model
|
||||||
|
self.opts = self.model._meta
|
||||||
|
self.lookup_opts = self.opts
|
||||||
|
self.manager = self.model._default_manager
|
||||||
|
self.get_search_parameters(request)
|
||||||
|
self.get_ordering()
|
||||||
|
self.query = request.GET.get(SEARCH_VAR, '')
|
||||||
|
self.get_lookup_params()
|
||||||
|
self.get_results(request)
|
||||||
|
self.title = (self.is_popup
|
||||||
|
and _('Select %s') % self.opts.verbose_name
|
||||||
|
or _('Select %s to change') % self.opts.verbose_name)
|
||||||
|
self.get_filters(request)
|
||||||
|
self.pk_attname = self.lookup_opts.pk.attname
|
||||||
|
|
||||||
|
def get_filters(self, request):
|
||||||
|
self.filter_specs = []
|
||||||
|
if self.lookup_opts.admin.list_filter and not self.opts.one_to_one_field:
|
||||||
|
filter_fields = [self.lookup_opts.get_field(field_name) \
|
||||||
|
for field_name in self.lookup_opts.admin.list_filter]
|
||||||
|
for f in filter_fields:
|
||||||
|
spec = FilterSpec.create(f, request, self.params)
|
||||||
|
if spec and spec.has_output():
|
||||||
|
self.filter_specs.append(spec)
|
||||||
|
self.has_filters = bool(self.filter_specs)
|
||||||
|
|
||||||
|
def get_query_string(self, new_params={}, remove=[]):
|
||||||
|
p = self.params.copy()
|
||||||
|
for r in remove:
|
||||||
|
for k in p.keys():
|
||||||
|
if k.startswith(r):
|
||||||
|
del p[k]
|
||||||
|
for k, v in new_params.items():
|
||||||
|
if p.has_key(k) and v is None:
|
||||||
|
del p[k]
|
||||||
|
elif v is not None:
|
||||||
|
p[k] = v
|
||||||
|
return '?' + '&'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
|
||||||
|
|
||||||
|
def get_search_parameters(self, request):
|
||||||
|
# Get search parameters from the query string.
|
||||||
|
try:
|
||||||
|
self.page_num = int(request.GET.get(PAGE_VAR, 0))
|
||||||
|
except ValueError:
|
||||||
|
self.page_num = 0
|
||||||
|
self.show_all = request.GET.has_key(ALL_VAR)
|
||||||
|
self.is_popup = request.GET.has_key(IS_POPUP_VAR)
|
||||||
|
self.params = dict(request.GET.items())
|
||||||
|
if self.params.has_key(PAGE_VAR):
|
||||||
|
del self.params[PAGE_VAR]
|
||||||
|
|
||||||
|
def get_results(self, request):
|
||||||
|
manager, lookup_params = self.manager, self.lookup_params
|
||||||
|
show_all, page_num = self.show_all, self.page_num
|
||||||
|
# Get the results.
|
||||||
|
try:
|
||||||
|
paginator = ObjectPaginator(manager, lookup_params, DEFAULT_RESULTS_PER_PAGE)
|
||||||
|
# Naked except! Because we don't have any other way of validating "params".
|
||||||
|
# They might be invalid if the keyword arguments are incorrect, or if the
|
||||||
|
# values are not in the correct type (which would result in a database
|
||||||
|
# error).
|
||||||
|
except Exception:
|
||||||
|
raise IncorrectLookupParameters
|
||||||
|
|
||||||
|
# Get the total number of objects, with no filters applied.
|
||||||
|
real_lookup_params = lookup_params.copy()
|
||||||
|
del real_lookup_params['order_by']
|
||||||
|
if real_lookup_params:
|
||||||
|
full_result_count = manager.get_count()
|
||||||
|
else:
|
||||||
|
full_result_count = paginator.hits
|
||||||
|
del real_lookup_params
|
||||||
|
result_count = paginator.hits
|
||||||
|
can_show_all = result_count <= MAX_SHOW_ALL_ALLOWED
|
||||||
|
multi_page = result_count > DEFAULT_RESULTS_PER_PAGE
|
||||||
|
|
||||||
|
# Get the list of objects to display on this page.
|
||||||
|
if (show_all and can_show_all) or not multi_page:
|
||||||
|
result_list = manager.get_list(**lookup_params)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
result_list = paginator.get_page(page_num)
|
||||||
|
except InvalidPage:
|
||||||
|
result_list = []
|
||||||
|
(self.result_count, self.full_result_count, self.result_list,
|
||||||
|
self.can_show_all, self.multi_page, self.paginator) = (result_count,
|
||||||
|
full_result_count, result_list, can_show_all, multi_page, paginator )
|
||||||
|
|
||||||
|
def url_for_result(self, result):
|
||||||
|
return "%s/" % getattr(result, self.pk_attname)
|
||||||
|
|
||||||
|
def get_ordering(self):
|
||||||
|
lookup_opts, params = self.lookup_opts, self.params
|
||||||
|
# For ordering, first check the "ordering" parameter in the admin options,
|
||||||
|
# then check the object's default ordering. If neither of those exist,
|
||||||
|
# order descending by ID by default. Finally, look for manually-specified
|
||||||
|
# ordering from the query string.
|
||||||
|
ordering = lookup_opts.admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name]
|
||||||
|
|
||||||
|
# Normalize it to new-style ordering.
|
||||||
|
ordering = handle_legacy_orderlist(ordering)
|
||||||
|
|
||||||
|
if ordering[0].startswith('-'):
|
||||||
|
order_field, order_type = ordering[0][1:], 'desc'
|
||||||
|
else:
|
||||||
|
order_field, order_type = ordering[0], 'asc'
|
||||||
|
if params.has_key(ORDER_VAR):
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
f = lookup_opts.get_field(lookup_opts.admin.list_display[int(params[ORDER_VAR])])
|
||||||
|
except models.FieldDoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if not isinstance(f.rel, models.ManyToOne) or not f.null:
|
||||||
|
order_field = f.name
|
||||||
|
except (IndexError, ValueError):
|
||||||
|
pass # Invalid ordering specified. Just use the default.
|
||||||
|
if params.has_key(ORDER_TYPE_VAR) and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
|
||||||
|
order_type = params[ORDER_TYPE_VAR]
|
||||||
|
self.order_field, self.order_type = order_field, order_type
|
||||||
|
|
||||||
|
def get_lookup_params(self):
|
||||||
|
# Prepare the lookup parameters for the API lookup.
|
||||||
|
(params, order_field, lookup_opts, order_type, opts, query) = \
|
||||||
|
(self.params, self.order_field, self.lookup_opts, self.order_type, self.opts, self.query)
|
||||||
|
|
||||||
|
lookup_params = params.copy()
|
||||||
|
for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR):
|
||||||
|
if lookup_params.has_key(i):
|
||||||
|
del lookup_params[i]
|
||||||
|
# If the order-by field is a field with a relationship, order by the value
|
||||||
|
# in the related table.
|
||||||
|
lookup_order_field = order_field
|
||||||
|
try:
|
||||||
|
f = lookup_opts.get_field(order_field)
|
||||||
|
except models.FieldDoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if isinstance(lookup_opts.get_field(order_field).rel, models.ManyToOne):
|
||||||
|
f = lookup_opts.get_field(order_field)
|
||||||
|
rel_ordering = f.rel.to._meta.ordering and f.rel.to._meta.ordering[0] or f.rel.to._meta.pk.column
|
||||||
|
lookup_order_field = '%s.%s' % (f.rel.to._meta.db_table, rel_ordering)
|
||||||
|
# Use select_related if one of the list_display options is a field with a
|
||||||
|
# relationship.
|
||||||
|
if lookup_opts.admin.list_select_related:
|
||||||
|
lookup_params['select_related'] = True
|
||||||
|
else:
|
||||||
|
for field_name in lookup_opts.admin.list_display:
|
||||||
|
try:
|
||||||
|
f = lookup_opts.get_field(field_name)
|
||||||
|
except models.FieldDoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if isinstance(f.rel, models.ManyToOne):
|
||||||
|
lookup_params['select_related'] = True
|
||||||
|
break
|
||||||
|
lookup_params['order_by'] = ((order_type == 'desc' and '-' or '') + lookup_order_field,)
|
||||||
|
if lookup_opts.admin.search_fields and query:
|
||||||
|
complex_queries = []
|
||||||
|
for bit in query.split():
|
||||||
|
or_queries = []
|
||||||
|
for field_name in lookup_opts.admin.search_fields:
|
||||||
|
or_queries.append(models.Q(**{'%s__icontains' % field_name: bit}))
|
||||||
|
complex_queries.append(reduce(operator.or_, or_queries))
|
||||||
|
lookup_params['complex'] = reduce(operator.and_, complex_queries)
|
||||||
|
if opts.one_to_one_field:
|
||||||
|
lookup_params.update(opts.one_to_one_field.rel.limit_choices_to)
|
||||||
|
self.lookup_params = lookup_params
|
||||||
|
|
||||||
|
def change_list(request, app_label, model_name):
|
||||||
|
model = get_model(app_label, model_name)
|
||||||
|
if not request.user.has_perm(app_label + '.' + model._meta.get_change_permission()):
|
||||||
|
raise PermissionDenied
|
||||||
|
try:
|
||||||
|
cl = ChangeList(request, model)
|
||||||
|
except IncorrectLookupParameters:
|
||||||
|
return HttpResponseRedirect(request.path)
|
||||||
|
c = template.RequestContext(request, {
|
||||||
|
'title': cl.title,
|
||||||
|
'is_popup': cl.is_popup,
|
||||||
|
'cl': cl,
|
||||||
|
})
|
||||||
|
c.update({'has_add_permission': c['perms'][app_label][cl.opts.get_add_permission()]}),
|
||||||
|
return render_to_response(['admin/%s/%s/change_list' % (app_label, cl.opts.object_name.lower()),
|
||||||
|
'admin/%s/change_list' % app_label,
|
||||||
|
'admin/change_list'], context_instance=c)
|
||||||
|
change_list = staff_member_required(change_list)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user