1
0
mirror of https://github.com/django/django.git synced 2025-06-14 16:09:12 +00:00

Changes to get admin semi-working

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1675 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Robert Wittams 2005-12-15 23:26:04 +00:00
parent bc1cef4e7b
commit 8b857e8044
6 changed files with 186 additions and 51 deletions

View File

@ -190,8 +190,8 @@ result_list = register.inclusion_tag("admin/change_list_results")(result_list)
#@register.inclusion_tag("admin/date_hierarchy") #@register.inclusion_tag("admin/date_hierarchy")
def date_hierarchy(cl): def date_hierarchy(cl):
lookup_opts, params, lookup_params, lookup_mod = \ lookup_opts, params, lookup_params, manager = \
cl.lookup_opts, cl.params, cl.lookup_params, cl.lookup_mod cl.lookup_opts, cl.params, cl.lookup_params, cl.manager
if lookup_opts.admin.date_hierarchy: if lookup_opts.admin.date_hierarchy:
field_name = lookup_opts.admin.date_hierarchy field_name = lookup_opts.admin.date_hierarchy
@ -208,7 +208,7 @@ def date_hierarchy(cl):
return cl.get_query_string(d, [field_generic]) return cl.get_query_string(d, [field_generic])
def get_dates(unit, params): def get_dates(unit, params):
return getattr(lookup_mod, 'get_%s_list' % field_name)(unit, **params) return getattr(manager, 'get_%s_list' % field_name)(unit, **params)
if year_lookup and month_lookup and day_lookup: if year_lookup and month_lookup and day_lookup:
month_name = MONTHS[int(month_lookup)] month_name = MONTHS[int(month_lookup)]

View File

@ -17,6 +17,8 @@ class AdminApplistNode(template.Node):
has_module_perms = user.has_module_perms(app_label) has_module_perms = user.has_module_perms(app_label)
if has_module_perms: if has_module_perms:
model_list = [] model_list = []
#HACK
app_url = "/".join( [comp for comp in app.__name__.split('.') if comp != 'models' ])
for m in app._MODELS: for m in app._MODELS:
if m._meta.admin: if m._meta.admin:
module_name = m._meta.module_name module_name = m._meta.module_name
@ -28,10 +30,12 @@ class AdminApplistNode(template.Node):
# Check whether user has any perm for this module. # Check whether user has any perm for this module.
# If so, add the module to the model_list. # If so, add the module to the model_list.
if True in perms.values(): if True in perms.values():
model_list.append({ model_list.append({
'name': capfirst(m._meta.verbose_name_plural), 'name': capfirst(m._meta.verbose_name_plural),
'admin_url': '%s/%s/' % (app_label, m._meta.module_name), 'admin_url': '%s/%s/' % (app_url, m.__name__.lower()),
'perms': perms, 'perms': perms,
}) })

View File

@ -48,11 +48,10 @@ if 'ellington.media' in INSTALLED_APPS:
) )
urlpatterns += ( urlpatterns += (
# Metasystem admin pages ('^((?:[^/]+/)+?)add/$', 'django.contrib.admin.views.main.add_stage'),
('^(?P<app_label>[^/]+)/(?P<module_name>[^/]+)/$', 'django.contrib.admin.views.main.change_list'), ('^((?:[^/]+/)+?)([^/]+)/history/$', 'django.contrib.admin.views.main.history'),
('^(?P<app_label>[^/]+)/(?P<module_name>[^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'), ('^((?:[^/]+/)+?)([^/]+)/delete/$', 'django.contrib.admin.views.main.delete_stage'),
('^(?P<app_label>[^/]+)/(?P<module_name>[^/]+)/(?P<object_id>.+)/history/$', 'django.contrib.admin.views.main.history'), ('^((?:[^/]+/)+?)([^/]+)/change/$', 'django.contrib.admin.views.main.change_stage'),
('^(?P<app_label>[^/]+)/(?P<module_name>[^/]+)/(?P<object_id>.+)/delete/$', 'django.contrib.admin.views.main.delete_stage'), ('^((?:[^/]+/)+?)$', 'django.contrib.admin.views.main.change_list' ),
('^(?P<app_label>[^/]+)/(?P<module_name>[^/]+)/(?P<object_id>.+)/$', 'django.contrib.admin.views.main.change_stage'),
) )
urlpatterns = patterns('', *urlpatterns) urlpatterns = patterns('', *urlpatterns)

View File

@ -1,4 +1,5 @@
# Generic admin views. # Generic admin views.
from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.admin.filterspecs import FilterSpec from django.contrib.admin.filterspecs import FilterSpec
from django.core import formfields, template from django.core import formfields, template
@ -21,6 +22,7 @@ from django.utils import dateformat
from django.utils.dates import MONTHS from django.utils.dates import MONTHS
from django.utils.html import escape from django.utils.html import escape
import operator import operator
from itertools import izip
# The system will display a "Show all" link only if the total result count # The system will display a "Show all" link only if the total result count
# is less than or equal to this setting. # is less than or equal to this setting.
@ -41,7 +43,7 @@ EMPTY_CHANGELIST_VALUE = '(None)'
def _get_mod_opts(app_label, module_name): def _get_mod_opts(app_label, module_name):
"Helper function that returns a tuple of (module, opts), raising Http404 if necessary." "Helper function that returns a tuple of (module, opts), raising Http404 if necessary."
try: try:
mod = models.get_module(app_label, module_name) mod = models.get_app(app_label)
except ImportError: except ImportError:
raise Http404 # Invalid app or module name. Maybe it's not in INSTALLED_APPS. raise Http404 # Invalid app or module name. Maybe it's not in INSTALLED_APPS.
opts = mod.Klass._meta opts = mod.Klass._meta
@ -49,6 +51,52 @@ def _get_mod_opts(app_label, module_name):
raise Http404 # This object is valid but has no admin interface. raise Http404 # This object is valid but has no admin interface.
return mod, opts return mod, opts
def matches_app(mod, comps):
modcomps = mod.__name__.split('.')[:-1] #HACK: leave off 'models'
for c, mc in izip(comps, modcomps):
if c != mc:
return ([],False)
return (comps[len(modcomps):], True)
def find_model(mod, remaining):
# print "finding ", mod, remaining
if len(remaining) == 0:
# print "no comps left"
raise Http404
if len(remaining) == 1:
if hasattr(mod, '_MODELS'):
name = remaining[0]
for model in mod._MODELS:
print "'%s'" % name, model
if model.__name__.lower() == name:
return model
raise Http404
else:
raise Http404
else:
child = getattr(mod, remaining[0], None)
# print mod, remaining[0], child
if child:
return find_model(child, remaining[1:])
else:
raise Http404
def get_app_label(mod):
modcomps = mod.__name__.split('.')
return modcomps[-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:
# print "matched ", mod
# print "left", remaining
return ( find_model(mod, remaining), get_app_label(mod) )
raise Http404 # Couldn't find app
def index(request): def index(request):
return render_to_response('admin/index', {'title': _('Site administration')}, context_instance=Context(request)) return render_to_response('admin/index', {'title': _('Site administration')}, context_instance=Context(request))
index = staff_member_required(index) index = staff_member_required(index)
@ -57,8 +105,8 @@ class IncorrectLookupParameters(Exception):
pass pass
class ChangeList(object): class ChangeList(object):
def __init__(self, request, app_label, module_name): def __init__(self, request, path):
self.get_modules_and_options(app_label, module_name, request) self.resolve_model(path, request)
self.get_search_parameters(request) self.get_search_parameters(request)
self.get_ordering() self.get_ordering()
self.query = request.GET.get(SEARCH_VAR, '') self.query = request.GET.get(SEARCH_VAR, '')
@ -94,12 +142,16 @@ class ChangeList(object):
p[k] = v p[k] = v
return '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20') return '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20')
def get_modules_and_options(self, app_label, module_name, request): def resolve_model(self, path, request):
self.mod, self.opts = _get_mod_opts(app_label, module_name) self.model, self.app_label = get_model_and_app(path)
if not request.user.has_perm(app_label + '.' + self.opts.get_change_permission()): # _get_mod_opts(app_label, module_name)
self.opts = self.model._meta
if not request.user.has_perm(self.app_label + '.' + self.opts.get_change_permission()):
raise PermissionDenied raise PermissionDenied
self.lookup_mod, self.lookup_opts = self.mod, self.opts self.lookup_opts = self.opts
self.manager = self.model._default_manager
def get_search_parameters(self, request): def get_search_parameters(self, request):
# Get search parameters from the query string. # Get search parameters from the query string.
@ -114,11 +166,11 @@ class ChangeList(object):
del self.params[PAGE_VAR] del self.params[PAGE_VAR]
def get_results(self, request): def get_results(self, request):
lookup_mod, lookup_params, show_all, page_num = \ manager, lookup_params, show_all, page_num = \
self.lookup_mod, self.lookup_params, self.show_all, self.page_num self.manager, self.lookup_params, self.show_all, self.page_num
# Get the results. # Get the results.
try: try:
paginator = ObjectPaginator(lookup_mod, lookup_params, DEFAULT_RESULTS_PER_PAGE) paginator = ObjectPaginator(manager, lookup_params, DEFAULT_RESULTS_PER_PAGE)
# Naked except! Because we don't have any other way of validating "params". # 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 # 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 # values are not in the correct type (which would result in a database
@ -130,7 +182,7 @@ class ChangeList(object):
real_lookup_params = lookup_params.copy() real_lookup_params = lookup_params.copy()
del real_lookup_params['order_by'] del real_lookup_params['order_by']
if real_lookup_params: if real_lookup_params:
full_result_count = lookup_mod.get_count() full_result_count = manager.get_count()
else: else:
full_result_count = paginator.hits full_result_count = paginator.hits
del real_lookup_params del real_lookup_params
@ -140,7 +192,7 @@ class ChangeList(object):
# Get the list of objects to display on this page. # Get the list of objects to display on this page.
if (show_all and can_show_all) or not multi_page: if (show_all and can_show_all) or not multi_page:
result_list = lookup_mod.get_list(**lookup_params) result_list = manager.get_list(**lookup_params)
else: else:
try: try:
result_list = paginator.get_page(page_num) result_list = paginator.get_page(page_num)
@ -231,9 +283,10 @@ class ChangeList(object):
lookup_params.update(opts.one_to_one_field.rel.limit_choices_to) lookup_params.update(opts.one_to_one_field.rel.limit_choices_to)
self.lookup_params = lookup_params self.lookup_params = lookup_params
def change_list(request, app_label, module_name): def change_list(request, path):
print "change_list:", path
try: try:
cl = ChangeList(request, app_label, module_name) cl = ChangeList(request, path)
except IncorrectLookupParameters: except IncorrectLookupParameters:
return HttpResponseRedirect(request.path) return HttpResponseRedirect(request.path)
@ -242,9 +295,9 @@ def change_list(request, app_label, module_name):
'is_popup': cl.is_popup, 'is_popup': cl.is_popup,
'cl' : cl 'cl' : cl
}) })
c.update({'has_add_permission': c['perms'][app_label][cl.opts.get_add_permission()]}), c.update({'has_add_permission': c['perms'][cl.app_label][cl.opts.get_add_permission()]}),
return render_to_response(['admin/%s/%s/change_list' % (app_label, cl.opts.object_name.lower()), return render_to_response(['admin/%s/%s/change_list' % (cl.app_label, cl.opts.object_name.lower()),
'admin/%s/change_list' % app_label, 'admin/%s/change_list' % cl.app_label,
'admin/change_list'], context_instance=c) 'admin/change_list'], context_instance=c)
change_list = staff_member_required(change_list) change_list = staff_member_required(change_list)
@ -464,12 +517,15 @@ def log_change_message(user, opts,manipulator,new_object):
change_message = _('No fields changed.') change_message = _('No fields changed.')
LogEntry.objects.log_action(user.id, opts.get_content_type_id(), pk_value, str(new_object), CHANGE, change_message) LogEntry.objects.log_action(user.id, opts.get_content_type_id(), pk_value, str(new_object), CHANGE, change_message)
def change_stage(request, app_label, module_name, object_id): def change_stage(request, path, object_id):
mod, opts = _get_mod_opts(app_label, module_name) print "change_stage", path, object_id
model, app_label = get_model_and_app(path)
opts = model._meta
#mod, opts = _get_mod_opts(app_label, module_name)
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, app_label, module_name, form_url='../add/') return add_stage(request, path, form_url='../add/')
try: try:
manipulator = mod.ChangeManipulator(object_id) manipulator = mod.ChangeManipulator(object_id)
except ObjectDoesNotExist: except ObjectDoesNotExist:

View File

@ -1,23 +1,28 @@
from copy import copy from copy import copy
from math import ceil from math import ceil
from django.db.models import ModelBase
class InvalidPage(Exception): class InvalidPage(Exception):
pass pass
class ObjectPaginator: class ObjectPaginator:
""" """
This class makes pagination easy. Feed it a module (an object with This class makes pagination easy. Feed it a manager (an object with
get_count() and get_list() methods) and a dictionary of arguments get_count() and get_list() methods) or a model which has a default manager,
to be passed to those methods, plus the number of objects you want and a dictionary of arguments to be passed to those methods, plus the
on each page. Then read the hits and pages properties to see how number of objects you want on each page. Then read the hits and pages
many pages it involves. Call get_page with a page number (starting properties to see how many pages it involves. Call get_page with a page
at 0) to get back a list of objects for that page. number (starting at 0) to get back a list of objects for that page.
Finally, check if a page number has a next/prev page using Finally, check if a page number has a next/prev page using
has_next_page(page_number) and has_previous_page(page_number). has_next_page(page_number) and has_previous_page(page_number).
""" """
def __init__(self, module, args, num_per_page, count_method='get_count', list_method='get_list'): def __init__(self, manager_or_model, args, num_per_page, count_method='get_count', list_method='get_list'):
self.module, self.args = module, args if hasattr(manager_or_model, '_default_manager'):
manager = manager_or_model._default_manager
else:
manager = manager_or_model
self.manager, self.args = manager, args
self.num_per_page = num_per_page self.num_per_page = num_per_page
self.count_method, self.list_method = count_method, list_method self.count_method, self.list_method = count_method, list_method
self._hits, self._pages = None, None self._hits, self._pages = None, None
@ -35,7 +40,7 @@ class ObjectPaginator:
# Retrieve one extra record, and check for the existence of that extra # Retrieve one extra record, and check for the existence of that extra
# record to determine whether there's a next page. # record to determine whether there's a next page.
args['limit'] = self.num_per_page + 1 args['limit'] = self.num_per_page + 1
object_list = getattr(self.module, self.list_method)(**args) object_list = getattr(self.manager, self.list_method)(**args)
if not object_list: if not object_list:
raise InvalidPage raise InvalidPage
self._has_next[page_number] = (len(object_list) > self.num_per_page) self._has_next[page_number] = (len(object_list) > self.num_per_page)
@ -48,7 +53,7 @@ class ObjectPaginator:
args = copy(self.args) args = copy(self.args)
args['offset'] = (page_number + 1) * self.num_per_page args['offset'] = (page_number + 1) * self.num_per_page
args['limit'] = 1 args['limit'] = 1
object_list = getattr(self.module, self.list_method)(**args) object_list = getattr(self.manager, self.list_method)(**args)
self._has_next[page_number] = (object_list != []) self._has_next[page_number] = (object_list != [])
else: else:
self._has_next[page_number] = page_number < (self.pages - 1) self._has_next[page_number] = page_number < (self.pages - 1)
@ -64,7 +69,7 @@ class ObjectPaginator:
del order_args['order_by'] del order_args['order_by']
if order_args.has_key('select_related'): if order_args.has_key('select_related'):
del order_args['select_related'] del order_args['select_related']
self._hits = getattr(self.module, self.count_method)(**order_args) self._hits = getattr(self.manager, self.count_method)(**order_args)
return self._hits return self._hits
def _get_pages(self): def _get_pages(self):

View File

@ -1051,6 +1051,17 @@ class Model(object):
delete.alters_data = True delete.alters_data = True
def __get_add_manipulator(cls):
cls.AddManipulator = get_manipulator
AddManipulator = property(classmethod(__get_add_manipulator))
def __get_change_manipulator(cls):
ChangeManipulator = property(classmethod(__get_change_manipulator))
def __get_FIELD_display(self, field): def __get_FIELD_display(self, field):
value = getattr(self, field.attname) value = getattr(self, field.attname)
return dict(field.choices).get(value, value) return dict(field.choices).get(value, value)
@ -1259,6 +1270,8 @@ class Model(object):
connection.commit() connection.commit()
############################################ ############################################
# HELPER FUNCTIONS (CURRIED MODEL METHODS) # # HELPER FUNCTIONS (CURRIED MODEL METHODS) #
############################################ ############################################
@ -1503,6 +1516,73 @@ def get_manipulator(opts, klass, extra_methods, add=False, change=False):
setattr(man, k, v) setattr(man, k, v)
return man return man
class AutomaticManipulator(formfields.Manipulator):
def __classinit__(cls, model):
cls.model = model
cls.manager = model._default_manager
__classinit__ = classmethod(__classinit__)
def __init__(self, follow=None):
self.follow = self.model._meta.get_follow(follow)
self.fields = []
for f in opts.fields + opts.many_to_many:
if self.follow.get(f.name, False):
self.fields.extend(f.get_manipulator_fields(opts, self, change))
# Add fields for related objects.
for f in opts.get_all_related_objects():
if self.follow.get(f.name, False):
fol = self.follow[f.name]
self.fields.extend(f.get_manipulator_fields(opts, self, change, fol))
def save(self):
pass
def get_related_objects(opts, klass, add, change, self):
return opts.get_followed_related_objects(self.follow)
def flatten_data(opts, klass, add, change, self):
new_data = {}
obj = change and self.original_object or None
for f in opts.get_data_holders(self.follow):
fol = self.follow.get(f.name)
new_data.update(f.flatten_data(fol, obj))
return new_data
class ModelAddManipulator(AutomaticManipulator):
pass
class ModelSaveManipulator(AutomaticManipulator):
def __init__(self, obj_key=None, follow=None):
assert obj_key is not None, "ChangeManipulator.__init__() must be passed obj_key parameter."
self.obj_key = obj_key
try:
self.original_object = self.manager.get_object(pk=obj_key)
except ObjectDoesNotExist:
# If the object doesn't exist, this might be a manipulator for a
# one-to-one related object that hasn't created its subobject yet.
# For example, this might be a Restaurant for a Place that doesn't
# yet have restaurant information.
if opts.one_to_one_field:
# Sanity check -- Make sure the "parent" object exists.
# For example, make sure the Place exists for the Restaurant.
# Let the ObjectDoesNotExist exception propogate up.
lookup_kwargs = opts.one_to_one_field.rel.limit_choices_to
lookup_kwargs['%s__exact' % opts.one_to_one_field.rel.field_name] = obj_key
_ = opts.one_to_one_field.rel.to._meta.get_model_module().get_object(**lookup_kwargs)
params = dict([(f.attname, f.get_default()) for f in opts.fields])
params[opts.pk.attname] = obj_key
self.original_object = opts.get_model_module().Klass(**params)
else:
raise
super(ModelSaveManipulator, self).__init__(self, follow=follow)
if opts.get_ordered_objects():
self.fields.append(formfields.CommaSeparatedIntegerField(field_name="order_"))
def manipulator_init(opts, add, change, self, obj_key=None, follow=None): def manipulator_init(opts, add, change, self, obj_key=None, follow=None):
self.follow = opts.get_follow(follow) self.follow = opts.get_follow(follow)
@ -1691,16 +1771,7 @@ def manipulator_save(opts, klass, add, change, self, new_data):
getattr(new_object, 'set_%s_order' % rel_opts.object_name.lower())(order) getattr(new_object, 'set_%s_order' % rel_opts.object_name.lower())(order)
return new_object return new_object
def manipulator_get_related_objects(opts, klass, add, change, self):
return opts.get_followed_related_objects(self.follow)
def manipulator_flatten_data(opts, klass, add, change, self):
new_data = {}
obj = change and self.original_object or None
for f in opts.get_data_holders(self.follow):
fol = self.follow.get(f.name)
new_data.update(f.flatten_data(fol, obj))
return new_data
def manipulator_validator_unique_together(field_name_list, opts, self, field_data, all_data): def manipulator_validator_unique_together(field_name_list, opts, self, field_data, all_data):
from django.utils.text import get_text_list from django.utils.text import get_text_list