No %s matched your search criteria.
' % opts.verbose_name_plural)
+ return ''.join(raw_template)
+result_list = simple_tag(result_list)
+
+#@simple_tag
+def date_hierarchy(cl):
+ lookup_opts, params, lookup_params, lookup_mod = \
+ cl.lookup_opts, cl.params, cl.lookup_params, cl.lookup_mod
+
+ raw_template = []
+ if lookup_opts.admin.date_hierarchy:
+ field_name = lookup_opts.admin.date_hierarchy
+
+ year_field = '%s__year' % field_name
+ month_field = '%s__month' % field_name
+ day_field = '%s__day' % field_name
+ field_generic = '%s__' % field_name
+ year_lookup = params.get(year_field)
+ month_lookup = params.get(month_field)
+ day_lookup = params.get(day_field)
+
+ raw_template.append('\n')
- if request.user.has_perm(app_label + '.' + lookup_opts.get_add_permission()):
- raw_template.append('
\n' % ((is_popup and '?_popup=1' or ''), opts.verbose_name))
- raw_template.append('
\n' % (filter_template and ' filtered' or ''))
-
- # Search form.
- if lookup_opts.admin.search_fields:
- raw_template.append('
\n')
- raw_template.append('')
-
- # Date-based navigation.
- if lookup_opts.admin.date_hierarchy:
- field_name = lookup_opts.admin.date_hierarchy
-
- year_field = '%s__year' % field_name
- month_field = '%s__month' % field_name
- day_field = '%s__day' % field_name
- field_generic = '%s__' % field_name
- year_lookup = params.get(year_field)
- month_lookup = params.get(month_field)
- day_lookup = params.get(day_field)
-
- raw_template.append('
\n
\n')
- if year_lookup and month_lookup and day_lookup:
- raw_template.append('- ‹ %s %s
' % \
- (get_query_string(params, {year_field: year_lookup, month_field: month_lookup}, [field_generic]), MONTHS[int(month_lookup)], year_lookup))
- raw_template.append('- %s %s
' % (MONTHS[int(month_lookup)], day_lookup))
- elif year_lookup and month_lookup:
- raw_template.append('- ‹ %s
' % \
- (get_query_string(params, {year_field: year_lookup}, [field_generic]), year_lookup))
- date_lookup_params = lookup_params.copy()
- date_lookup_params.update({year_field: year_lookup, month_field: month_lookup})
- for day in getattr(lookup_mod, 'get_%s_list' % field_name)('day', **date_lookup_params):
- raw_template.append('- %s
' % \
- (get_query_string(params, {year_field: year_lookup, month_field: month_lookup, day_field: day.day}, [field_generic]), day.strftime('%B %d')))
- elif year_lookup:
- raw_template.append('- ‹ All dates
' % \
- get_query_string(params, {}, [year_field]))
- date_lookup_params = lookup_params.copy()
- date_lookup_params.update({year_field: year_lookup})
- for month in getattr(lookup_mod, 'get_%s_list' % field_name)('month', **date_lookup_params):
- raw_template.append('- %s %s
' % \
- (get_query_string(params, {year_field: year_lookup, month_field: month.month}, [field_generic]), month.strftime('%B'), month.year))
- else:
- for year in getattr(lookup_mod, 'get_%s_list' % field_name)('year', **lookup_params):
- raw_template.append('- %s
\n' % \
- (get_query_string(params, {year_field: year.year}, [field_generic]), year.year))
- raw_template.append('
\n
\n')
-
- # Filters.
- if filter_template:
- raw_template.append('
\n
Filter
\n')
- raw_template.extend(filter_template)
- raw_template.append('')
- del filter_template
-
- # Result table.
- if result_list:
- # Table headers.
- raw_template.append('
\n\n\n')
- for i, field_name in enumerate(lookup_opts.admin.list_display):
+ if not isinstance(f.rel, meta.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
+ if isinstance(lookup_opts.get_field(order_field).rel, meta.ManyToOne):
+ f = lookup_opts.get_field(order_field)
+ rel_ordering = f.rel.to.ordering and f.rel.to.ordering[0] or f.rel.to.pk.column
+ lookup_order_field = '%s.%s' % (f.rel.to.db_table, rel_ordering)
+ # Use select_related if one of the list_display options is a field with a
+ # relationship.
+ for field_name in lookup_opts.admin.list_display:
try:
f = lookup_opts.get_field(field_name)
except meta.FieldDoesNotExist:
- # For non-field list_display values, check for the function
- # attribute "short_description". If that doesn't exist, fall
- # back to the method name. And __repr__ is a special-case.
- if field_name == '__repr__':
- header = lookup_opts.verbose_name
- else:
- func = getattr(mod.Klass, field_name) # Let AttributeErrors propogate.
- try:
- header = func.short_description
- except AttributeError:
- header = func.__name__
- # Non-field list_display values don't get ordering capability.
- raw_template.append('%s | ' % capfirst(header))
+ pass
else:
- if isinstance(f.rel, meta.ManyToOne) and f.null:
- raw_template.append('%s | ' % capfirst(f.verbose_name))
- else:
- th_classes = []
- new_order_type = 'asc'
- if field_name == order_field:
- th_classes.append('sorted %sending' % order_type.lower())
- new_order_type = {'asc': 'desc', 'desc': 'asc'}[order_type.lower()]
- raw_template.append('%s | ' % \
- ((th_classes and ' class="%s"' % ' '.join(th_classes) or ''),
- get_query_string(params, {ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
- capfirst(f.verbose_name)))
- raw_template.append('
\n\n')
- # Result rows.
- pk = lookup_opts.pk.name
- for i, result in enumerate(result_list):
- raw_template.append('\n' % (i % 2 + 1))
- for j, field_name in enumerate(lookup_opts.admin.list_display):
- row_class = ''
- try:
- f = lookup_opts.get_field(field_name)
- except meta.FieldDoesNotExist:
- # For non-field list_display values, the value is a method
- # name. Execute the method.
- try:
- result_repr = strip_tags(str(getattr(result, field_name)()))
- except ObjectDoesNotExist:
- result_repr = EMPTY_CHANGELIST_VALUE
- else:
- field_val = getattr(result, f.column)
- # Foreign-key fields are special: Use the repr of the
- # related object.
- if isinstance(f.rel, meta.ManyToOne):
- if field_val is not None:
- result_repr = getattr(result, 'get_%s' % f.name)()
- else:
- result_repr = EMPTY_CHANGELIST_VALUE
- # Dates are special: They're formatted in a certain way.
- elif isinstance(f, meta.DateField):
- if field_val:
- if isinstance(f, meta.DateTimeField):
- result_repr = dateformat.format(field_val, 'N j, Y, P')
- else:
- result_repr = dateformat.format(field_val, 'N j, Y')
- else:
- result_repr = EMPTY_CHANGELIST_VALUE
- row_class = ' class="nowrap"'
- # Booleans are special: We use images.
- elif isinstance(f, meta.BooleanField) or isinstance(f, meta.NullBooleanField):
- BOOLEAN_MAPPING = {True: 'yes', False: 'no', None: 'unknown'}
- result_repr = '
' % (ADMIN_MEDIA_PREFIX, BOOLEAN_MAPPING[field_val], field_val)
- # ImageFields are special: Use a thumbnail.
- elif isinstance(f, meta.ImageField):
- from django.parts.media.photos import get_thumbnail_url
- result_repr = '
' % (get_thumbnail_url(getattr(result, 'get_%s_url' % f.name)(), '120'), field_val, field_val)
- # FloatFields are special: Zero-pad the decimals.
- elif isinstance(f, meta.FloatField):
- if field_val is not None:
- result_repr = ('%%.%sf' % f.decimal_places) % field_val
- else:
- result_repr = EMPTY_CHANGELIST_VALUE
- # Fields with choices are special: Use the representation
- # of the choice.
- elif f.choices:
- result_repr = dict(f.choices).get(field_val, EMPTY_CHANGELIST_VALUE)
- else:
- result_repr = strip_tags(str(field_val))
- # Some browsers don't like empty " | "s.
- if result_repr == '':
- result_repr = ' '
- if j == 0: # First column is a special case
- result_id = getattr(result, pk)
- raw_template.append('%s | ' % \
- (row_class, result_id, (is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr))
- else:
- raw_template.append('%s | ' % (row_class, result_repr))
- raw_template.append('
\n')
- del result_list # to free memory
- raw_template.append('
\n')
- else:
- raw_template.append('
No %s matched your search criteria.
' % opts.verbose_name_plural)
+ if isinstance(f.rel, meta.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:
+ or_queries = []
+ for bit in query.split():
+ or_query = []
+ for field_name in lookup_opts.admin.search_fields:
+ or_query.append(('%s__icontains' % field_name, bit))
+ or_queries.append(or_query)
+ lookup_params['_or'] = or_queries
+
+ if opts.one_to_one_field:
+ lookup_params.update(opts.one_to_one_field.rel.limit_choices_to)
+ self.lookup_params = lookup_params
+
- # Pagination.
- raw_template.append('
')
- if (show_all and can_show_all) or not multi_page:
- pass
- else:
- raw_template.append('Page › ')
- ON_EACH_SIDE = 3
- ON_ENDS = 2
- DOT = '.'
- # If there are 10 or fewer pages, display links to every page.
- # Otherwise, do some fancy
- if p.pages <= 10:
- page_range = range(p.pages)
- else:
- # Insert "smart" pagination links, so that there are always ON_ENDS
- # links at either end of the list of pages, and there are always
- # ON_EACH_SIDE links at either end of the "current page" link.
- page_range = []
- if page_num > (ON_EACH_SIDE + ON_ENDS):
- page_range.extend(range(0, ON_EACH_SIDE - 1))
- page_range.append(DOT)
- page_range.extend(range(page_num - ON_EACH_SIDE, page_num + 1))
- else:
- page_range.extend(range(0, page_num + 1))
- if page_num < (p.pages - ON_EACH_SIDE - ON_ENDS - 1):
- page_range.extend(range(page_num + 1, page_num + ON_EACH_SIDE + 1))
- page_range.append(DOT)
- page_range.extend(range(p.pages - ON_ENDS, p.pages))
- else:
- page_range.extend(range(page_num + 1, p.pages))
- for i in page_range:
- if i == DOT:
- raw_template.append('... ')
- elif i == page_num:
- raw_template.append('%d ' % (i+1))
- else:
- raw_template.append('%d ' % \
- (get_query_string(params, {PAGE_VAR: i}), (i == p.pages-1 and ' class="end"' or ''), i+1))
- raw_template.append('%s %s' % (result_count, result_count == 1 and opts.verbose_name or opts.verbose_name_plural))
- if can_show_all and not show_all and multi_page:
- raw_template.append(' Show all' % \
- get_query_string(params, {ALL_VAR: ''}))
- raw_template.append('
')
-
- raw_template.append('
\n
')
- raw_template.append('{% endblock %}\n')
- t = loader.get_template_from_string(''.join(raw_template))
+def change_list(request, app_label, module_name):
+ try:
+ cl = ChangeList(request, app_label, module_name)
+ except IncorrectLookupParameters:
+ return HttpResponseRedirect(request.path)
+
c = Context(request, {
- 'title': (is_popup and 'Select %s' % opts.verbose_name or 'Select %s to change' % opts.verbose_name),
- 'is_popup': is_popup,
+ 'title': cl.title,
+ 'is_popup': cl.is_popup,
+ 'cl' : cl
})
- return HttpResponse(t.render(c))
+ return render_to_response('admin/change_list',
+ context_instance = c)
change_list = staff_member_required(change_list)
+
use_raw_id_admin = lambda field: isinstance(field.rel, (meta.ManyToOne, meta.ManyToMany)) and field.rel.raw_id_admin
-def _get_submit_row_template(opts, app_label, add, change, show_delete, ordered_objects):
- t = ['\n')
- return t
def get_javascript_imports(opts,auto_populated_fields, ordered_objects, field_sets):
# Put in any necessary JavaScript imports.
@@ -534,17 +410,17 @@ def get_javascript_imports(opts,auto_populated_fields, ordered_objects, field_se
if not seen_collapse and 'collapse' in field_set.classes:
seen_collapse = True
js.append('js/admin/CollapsedFieldsets.js' )
- try:
- for field_line in field_set:
+
+ for field_line in field_set:
+ try:
for f in field_line:
if f.rel and isinstance(f, meta.ManyToManyField) and f.rel.filter_interface:
js.extend(['js/SelectBox.js' , 'js/SelectFilter2.js'])
raise StopIteration
- except StopIteration:
- break
+ except StopIteration:
+ break
return js
-
class AdminBoundField(BoundField):
def __init__(self, field, field_mapping, original):
super(AdminBoundField, self).__init__(field,field_mapping,original)
@@ -606,48 +482,48 @@ class AdminBoundFieldSet(BoundFieldSet):
def __init__(self, field_set, field_mapping, original):
super(AdminBoundFieldSet, self).__init__(field_set, field_mapping, original, AdminBoundFieldLine)
+
+class AdminBoundManipulator(object):
+ def __init__(self, opts, manipulator, field_mapping):
+ self.inline_related_objects = opts.get_followed_related_objects()
-def render_change_form(opts, app_label, context, add=False, change=False, show_delete=False, form_url=''):
- ordered_objects = opts.get_ordered_objects()[:]
- auto_populated_fields = [f for f in opts.fields if f.prepopulate_from]
- coltype = ordered_objects and 'colMS' or 'colM'
-
- has_absolute_url = hasattr(opts.get_model_module().Klass, 'get_absolute_url')
- form_enc_attrib = opts.has_field_type(meta.FileField) and 'enctype="multipart/form-data" ' or ''
- form = context['form']
- original = context['original']
+ field_sets = opts.admin.get_field_sets(opts)
+ self.original = hasattr(manipulator, 'original_object') and manipulator.original_object or None
+ self.bound_field_sets = [field_set.bind(field_mapping, self.original, AdminBoundFieldSet)
+ for field_set in field_sets]
+
+
+ self.ordered_objects = opts.get_ordered_objects()[:]
+ self.auto_populated_fields = [f for f in opts.fields if f.prepopulate_from]
+ self.javascript_imports = get_javascript_imports(opts, self.auto_populated_fields, self.ordered_objects, field_sets);
+
+ self.coltype = self.ordered_objects and 'colMS' or 'colM'
+ self.has_absolute_url = hasattr(opts.get_model_module().Klass, 'get_absolute_url')
+ self.form_enc_attrib = opts.has_field_type(meta.FileField) and \
+ 'enctype="multipart/form-data" ' or ''
+
+
+
+ self.first_form_field_id = self.bound_field_sets[0].bound_field_lines[0].bound_fields[0].form_fields[0].get_id();
+ self.ordered_object_names = ' '.join(['object.%s' % o.pk.name for o in self.ordered_objects])
+
+ self.save_on_top = opts.admin.save_on_top
+ self.save_as = opts.admin.save_as
+
+ self.content_type_id = opts.get_content_type_id()
+ self.verbose_name_plural = opts.verbose_name_plural
+ self.verbose_name = opts.verbose_name
+ self.object_name = opts.object_name
+
+def render_change_form(opts, manipulator, app_label, context, add=False, change=False, show_delete=False, form_url=''):
- field_sets = opts.admin.get_field_sets(opts)
- bound_field_sets = [field_set.bind(form, original, AdminBoundFieldSet)
- for field_set in field_sets]
-
- javascript_imports = get_javascript_imports(opts, auto_populated_fields, ordered_objects, field_sets);
- first_form_field = bound_field_sets[0].bound_field_lines[0].bound_fields[0].form_fields[0];
- inline_related_objects = opts.get_followed_related_objects()
- ordered_object_names = ' '.join(['object.%s' % o.pk.name for o in ordered_objects])
-
extra_context = {
'add': add,
'change': change,
- 'first_form_field_id': first_form_field.get_id(),
- 'ordered_objects' : ordered_objects,
- 'ordered_object_names' : ordered_object_names,
- 'auto_populated_fields' : auto_populated_fields,
- 'javascript_imports' : javascript_imports,
- 'coltype' : coltype,
- 'has_absolute_url': has_absolute_url,
- 'form_enc_attrib': form_enc_attrib,
+ 'bound_manipulator' : AdminBoundManipulator(opts, manipulator, context['form']),
+ 'has_delete_permission' : context['perms'][app_label][opts.get_delete_permission()],
'form_url' : form_url,
- 'bound_field_sets' : bound_field_sets,
- 'inline_related_objects': inline_related_objects,
- 'content_type_id' : opts.get_content_type_id(),
- 'save_on_top' : opts.admin.save_on_top,
- 'verbose_name_plural': opts.verbose_name_plural,
- 'verbose_name': opts.verbose_name,
- 'save_as': opts.admin.save_as,
'app_label': app_label,
- 'object_name': opts.object_name,
- 'has_delete_permission' : context['perms'][app_label][opts.get_delete_permission()]
}
context.update(extra_context)
@@ -677,7 +553,7 @@ def add_stage(request, app_label, module_name, show_delete=False, form_url='', p
new_object = manipulator.save(new_data)
log_add_message(request.user, opts,manipulator,new_object)
msg = 'The %s "%s" was added successfully.' % (opts.verbose_name, new_object)
-
+ pk_value = getattr(new_object,opts.pk.column)
# Here, we distinguish between different save types by checking for
# the presence of keys in request.POST.
if request.POST.has_key("_continue"):
@@ -713,7 +589,7 @@ def add_stage(request, app_label, module_name, show_delete=False, form_url='', p
if object_id_override is not None:
c['object_id'] = object_id_override
- return render_change_form(opts, app_label, c, add=True)
+ return render_change_form(opts, manipulator, app_label, c, add=True)
add_stage = staff_member_required(add_stage)
def log_change_message(user, opts,manipulator,new_object):
@@ -754,6 +630,7 @@ def change_stage(request, app_label, module_name, object_id):
new_object = manipulator.save(new_data)
log_change_message(request.user,opts,manipulator,new_object)
msg = 'The %s "%s" was changed successfully.' % (opts.verbose_name, new_object)
+ pk_value = getattr(new_object,opts.pk.column)
if request.POST.has_key("_continue"):
request.user.add_message("%s You may edit it again below." % msg)
if request.REQUEST.has_key('_popup'):
@@ -779,7 +656,7 @@ def change_stage(request, app_label, module_name, object_id):
id_order_list = []
for rel_obj in opts.get_ordered_objects():
- id_order_list.extend(getattr(obj, 'get_%s_order' % rel_obj.object_name.lower())())
+ id_order_list.extend(getattr(manipulator.original_object, 'get_%s_order' % rel_obj.object_name.lower())())
if id_order_list:
new_data['order_'] = ','.join(map(str, id_order_list))
errors = {}
@@ -794,7 +671,7 @@ def change_stage(request, app_label, module_name, object_id):
wrt = related.opts.order_with_respect_to
if wrt and wrt.rel and wrt.rel.to == opts:
func = getattr(manipulator.original_object, 'get_%s_list' %
- opts.get_rel_object_method_name(rel_opts, rel_field))
+ related.get_method_name_part())
orig_list = func()
form.order_objects.extend(orig_list)
@@ -806,7 +683,7 @@ def change_stage(request, app_label, module_name, object_id):
'is_popup' : request.REQUEST.has_key('_popup')
})
- return render_change_form(opts, app_label, c, change=True)
+ return render_change_form(opts,manipulator, app_label, c, change=True)
@@ -825,8 +702,8 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
for related in opts.get_all_related_objects():
if related.opts in objects_seen:
continue
- objects_seen.append(rel_opts)
- rel_opts_name = opts.get_rel_object_method_name(related.opts, related.field)
+ objects_seen.append(related.opts)
+ rel_opts_name = related.get_method_name_part()
if isinstance(related.field.rel, meta.OneToOne):
try:
sub_obj = getattr(obj, 'get_%s' % rel_opts_name)()
@@ -868,29 +745,29 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
if not user.has_perm(p):
perms_needed.add(rel_opts.verbose_name)
- for rel_opts, rel_field in opts.get_all_related_many_to_many_objects():
- if rel_opts in objects_seen:
+ for related in opts.get_all_related_many_to_many_objects():
+ if related.opts in objects_seen:
continue
- objects_seen.append(rel_opts)
- rel_opts_name = opts.get_rel_object_method_name(rel_opts, rel_field)
+ objects_seen.append(related.opts)
+ rel_opts_name = related.get_method_name_part()
has_related_objs = False
for sub_obj in getattr(obj, 'get_%s_list' % rel_opts_name)():
has_related_objs = True
- if rel_field.rel.edit_inline or not rel_opts.admin:
+ if related.field.rel.edit_inline or not related.opts.admin:
# Don't display link to edit, because it either has no
# admin or is edited inline.
nh(deleted_objects, current_depth, ['One or more %s in %s: %s' % \
- (rel_field.name, rel_opts.verbose_name, strip_tags(repr(sub_obj))), []])
+ (related.field.name, related.opts.verbose_name, strip_tags(repr(sub_obj))), []])
else:
# Display a link to the admin page.
nh(deleted_objects, current_depth, ['One or more %s in %s: