1
0
mirror of https://github.com/django/django.git synced 2025-06-13 15:39:13 +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")
def date_hierarchy(cl):
lookup_opts, params, lookup_params, lookup_mod = \
cl.lookup_opts, cl.params, cl.lookup_params, cl.lookup_mod
lookup_opts, params, lookup_params, manager = \
cl.lookup_opts, cl.params, cl.lookup_params, cl.manager
if 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])
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:
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)
if has_module_perms:
model_list = []
#HACK
app_url = "/".join( [comp for comp in app.__name__.split('.') if comp != 'models' ])
for m in app._MODELS:
if m._meta.admin:
module_name = m._meta.module_name
@ -28,10 +30,12 @@ class AdminApplistNode(template.Node):
# Check whether user has any perm for this module.
# If so, add the module to the model_list.
if True in perms.values():
model_list.append({
'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,
})

View File

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

View File

@ -1,4 +1,5 @@
# Generic admin views.
from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.admin.filterspecs import FilterSpec
from django.core import formfields, template
@ -21,6 +22,7 @@ from django.utils import dateformat
from django.utils.dates import MONTHS
from django.utils.html import escape
import operator
from itertools import izip
# The system will display a "Show all" link only if the total result count
# is less than or equal to this setting.
@ -41,7 +43,7 @@ EMPTY_CHANGELIST_VALUE = '(None)'
def _get_mod_opts(app_label, module_name):
"Helper function that returns a tuple of (module, opts), raising Http404 if necessary."
try:
mod = models.get_module(app_label, module_name)
mod = models.get_app(app_label)
except ImportError:
raise Http404 # Invalid app or module name. Maybe it's not in INSTALLED_APPS.
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.
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):
return render_to_response('admin/index', {'title': _('Site administration')}, context_instance=Context(request))
index = staff_member_required(index)
@ -57,8 +105,8 @@ class IncorrectLookupParameters(Exception):
pass
class ChangeList(object):
def __init__(self, request, app_label, module_name):
self.get_modules_and_options(app_label, module_name, request)
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, '')
@ -94,12 +142,16 @@ class ChangeList(object):
p[k] = v
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):
self.mod, self.opts = _get_mod_opts(app_label, module_name)
if not request.user.has_perm(app_label + '.' + self.opts.get_change_permission()):
def resolve_model(self, path, request):
self.model, self.app_label = get_model_and_app(path)
# _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
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):
# Get search parameters from the query string.
@ -114,11 +166,11 @@ class ChangeList(object):
del self.params[PAGE_VAR]
def get_results(self, request):
lookup_mod, lookup_params, show_all, page_num = \
self.lookup_mod, self.lookup_params, self.show_all, self.page_num
manager, lookup_params, show_all, page_num = \
self.manager, self.lookup_params, self.show_all, self.page_num
# Get the results.
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".
# 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
@ -130,7 +182,7 @@ class ChangeList(object):
real_lookup_params = lookup_params.copy()
del real_lookup_params['order_by']
if real_lookup_params:
full_result_count = lookup_mod.get_count()
full_result_count = manager.get_count()
else:
full_result_count = paginator.hits
del real_lookup_params
@ -140,7 +192,7 @@ class ChangeList(object):
# Get the list of objects to display on this 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:
try:
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)
self.lookup_params = lookup_params
def change_list(request, app_label, module_name):
def change_list(request, path):
print "change_list:", path
try:
cl = ChangeList(request, app_label, module_name)
cl = ChangeList(request, path)
except IncorrectLookupParameters:
return HttpResponseRedirect(request.path)
@ -242,9 +295,9 @@ def change_list(request, app_label, module_name):
'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,
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)
@ -464,12 +517,15 @@ def log_change_message(user, opts,manipulator,new_object):
change_message = _('No fields changed.')
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):
mod, opts = _get_mod_opts(app_label, module_name)
def change_stage(request, path, object_id):
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()):
raise PermissionDenied
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:
manipulator = mod.ChangeManipulator(object_id)
except ObjectDoesNotExist:

View File

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

View File

@ -1051,6 +1051,17 @@ class Model(object):
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):
value = getattr(self, field.attname)
return dict(field.choices).get(value, value)
@ -1259,6 +1270,8 @@ class Model(object):
connection.commit()
############################################
# HELPER FUNCTIONS (CURRIED MODEL METHODS) #
############################################
@ -1503,6 +1516,73 @@ def get_manipulator(opts, klass, extra_methods, add=False, change=False):
setattr(man, k, v)
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):
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)
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):
from django.utils.text import get_text_list