Changeset 1430
- Timestamp:
- 11/24/05 22:37:46 (3 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/new-admin/django/contrib/admin/templatetags/admin_list.py
r1367 r1430 1 from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, DEFAULT_RESULTS_PER_PAGE, ALL_VAR 2 from django.contrib.admin.views.main import ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR, SEARCH_VAR 3 from django.contrib.admin.views.main import IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE, MONTHS 4 from django.core import meta, template 5 from django.core.exceptions import ObjectDoesNotExist 1 6 from django.core.template.decorators import simple_tag, inclusion_tag 2 3 from django.contrib.admin.views.main import MAX_SHOW_ALL_ALLOWED, DEFAULT_RESULTS_PER_PAGE, ALL_VAR, \ 4 ORDER_VAR, ORDER_TYPE_VAR, PAGE_VAR , SEARCH_VAR , IS_POPUP_VAR, EMPTY_CHANGELIST_VALUE, \ 5 MONTHS 6 from django.utils.translation import get_date_formats 7 8 9 from django.core import meta 7 from django.utils import dateformat 8 from django.utils.html import strip_tags, escape 10 9 from django.utils.text import capfirst 11 from django.utils.html import strip_tags, escape 12 from django.core.exceptions import ObjectDoesNotExist 10 from django.utils.translation import get_date_formats 13 11 from django.conf.settings import ADMIN_MEDIA_PREFIX 14 from django.core import template 15 from django.utils import dateformat 12 16 13 DOT = '.' 17 14 … … 21 18 return '... ' 22 19 elif i == cl.page_num: 23 return '<span class="this-page">%d</span> ' % (i+1) 20 return '<span class="this-page">%d</span> ' % (i+1) 24 21 else: 25 return '<a href="%s"%s>%d</a> ' % (cl.get_query_string( {PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class="end"' or ''), i+1)22 return '<a href="%s"%s>%d</a> ' % (cl.get_query_string({PAGE_VAR: i}), (i == cl.paginator.pages-1 and ' class="end"' or ''), i+1) 26 23 paginator_number = simple_tag(paginator_number) 27 24 28 25 #@inclusion_tag('admin/pagination') 29 26 def pagination(cl): 30 paginator, page_num = cl.paginator, cl.page_num 31 27 paginator, page_num = cl.paginator, cl.page_num 28 32 29 pagination_required = (not cl.show_all or not cl.can_show_all) and cl.multi_page 33 30 if not pagination_required: … … 36 33 ON_EACH_SIDE = 3 37 34 ON_ENDS = 2 38 35 39 36 # If there are 10 or fewer pages, display links to every page. 40 37 # Otherwise, do some fancy … … 60 57 61 58 need_show_all_link = cl.can_show_all and not cl.show_all and cl.multi_page 62 63 return {'cl': cl,64 'pagination_required': pagination_required,65 'show_all_url': need_show_all_link and cl.get_query_string({ALL_VAR:''}),66 'page_range': page_range,67 'ALL_VAR': ALL_VAR,68 '1': 169 }59 return { 60 'cl': cl, 61 'pagination_required': pagination_required, 62 'show_all_url': need_show_all_link and cl.get_query_string({ALL_VAR: ''}), 63 'page_range': page_range, 64 'ALL_VAR': ALL_VAR, 65 '1': 1, 66 } 70 67 pagination = inclusion_tag('admin/pagination')(pagination) 71 72 68 73 69 def result_headers(cl): 74 70 lookup_opts = cl.lookup_opts 75 71 76 72 for i, field_name in enumerate(lookup_opts.admin.list_display): 77 try:78 f = lookup_opts.get_field(field_name)79 except meta.FieldDoesNotExist:80 # For non-field list_display values, check for the function81 # attribute "short_description". If that doesn't exist, fall82 # back to the method name. And __repr__ is a special-case.83 if field_name == '__repr__':84 header = lookup_opts.verbose_name85 else:86 func = getattr(cl.mod.Klass, field_name) # Let AttributeErrors propogate.87 try:88 header = func.short_description89 except AttributeError:90 header = func.__name__.replace('_', ' ')91 # Non-field list_display values don't get ordering capability.92 yield {"text": header}93 else:94 if isinstance(f.rel, meta.ManyToOne) and f.null:95 yield {"text": f.verbose_name}96 else:97 th_classes = []98 new_order_type = 'asc'99 if field_name == cl.order_field:100 th_classes.append('sorted %sending' % cl.order_type.lower())101 new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()]102 103 yield {"text" : f.verbose_name,104 "sortable": True,105 "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),106 "class_attrib" : (th_classes and ' class="%s"' % ' '.join(th_classes) or '')}107 73 try: 74 f = lookup_opts.get_field(field_name) 75 except meta.FieldDoesNotExist: 76 # For non-field list_display values, check for the function 77 # attribute "short_description". If that doesn't exist, fall 78 # back to the method name. And __repr__ is a special-case. 79 if field_name == '__repr__': 80 header = lookup_opts.verbose_name 81 else: 82 func = getattr(cl.mod.Klass, field_name) # Let AttributeErrors propogate. 83 try: 84 header = func.short_description 85 except AttributeError: 86 header = func.__name__.replace('_', ' ') 87 # Non-field list_display values don't get ordering capability. 88 yield {"text": header} 89 else: 90 if isinstance(f.rel, meta.ManyToOne) and f.null: 91 yield {"text": f.verbose_name} 92 else: 93 th_classes = [] 94 new_order_type = 'asc' 95 if field_name == cl.order_field: 96 th_classes.append('sorted %sending' % cl.order_type.lower()) 97 new_order_type = {'asc': 'desc', 'desc': 'asc'}[cl.order_type.lower()] 98 99 yield {"text": f.verbose_name, 100 "sortable": True, 101 "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}), 102 "class_attrib": (th_classes and ' class="%s"' % ' '.join(th_classes) or '')} 103 108 104 def items_for_result(cl, result): 109 105 first = True … … 122 118 result_repr = EMPTY_CHANGELIST_VALUE 123 119 else: 124 # Strip HTML tags in the resulting text, except if the 125 # function has an "allow_tags" attribute set to True. 126 if not getattr(func, 'allow_tags', False): 120 # Strip HTML tags in the resulting text, except if the 121 # function has an "allow_tags" attribute set to True. 122 if not getattr(func, 'allow_tags', False): 127 123 result_repr = strip_tags(result_repr) 128 124 else: 129 125 field_val = getattr(result, f.attname) 130 126 131 127 if isinstance(f.rel, meta.ManyToOne): 132 128 if field_val is not None: … … 137 133 elif isinstance(f, meta.DateField) or isinstance(f, meta.TimeField): 138 134 if field_val: 139 (date_format, datetime_format, time_format) = get_date_formats() 135 (date_format, datetime_format, time_format) = get_date_formats() 140 136 if isinstance(f, meta.DateTimeField): 141 137 result_repr = capfirst(dateformat.format(field_val, datetime_format)) … … 177 173 else: 178 174 yield ('<td%s>%s</td>' % (row_class, result_repr)) 179 175 180 176 def results(cl): 181 177 for res in cl.result_list: … … 185 181 def result_list(cl): 186 182 res = list(results(cl)) 187 return {'cl': cl, 188 'result_headers': list(result_headers(cl)),189 'results': list(results(cl)),}183 return {'cl': cl, 184 'result_headers': list(result_headers(cl)), 185 'results': list(results(cl))} 190 186 result_list = inclusion_tag("admin/change_list_results")(result_list) 191 192 187 193 188 #@inclusion_tag("admin/date_hierarchy") … … 195 190 lookup_opts, params, lookup_params, lookup_mod = \ 196 191 cl.lookup_opts, cl.params, cl.lookup_params, cl.lookup_mod 197 192 198 193 if lookup_opts.admin.date_hierarchy: 199 194 field_name = lookup_opts.admin.date_hierarchy 200 195 201 196 year_field = '%s__year' % field_name 202 197 month_field = '%s__month' % field_name … … 206 201 month_lookup = params.get(month_field) 207 202 day_lookup = params.get(day_field) 208 209 def link(d): 203 204 def link(d): 210 205 return cl.get_query_string(d, [field_generic]) 211 206 212 207 def get_dates(unit, params): 213 208 return getattr(lookup_mod, 'get_%s_list' % field_name)(unit, **params) 214 209 215 210 if year_lookup and month_lookup and day_lookup: 216 211 month_name = MONTHS[int(month_lookup)] 217 return { 'show': True, 218 'back': 219 { 'link' : link({year_field: year_lookup, month_field: month_lookup}), 220 'title': "%s %s" % ( month_name, year_lookup), 221 }, 222 'choices': [ {'title': "%s %s" % ( month_name, day_lookup)} ] 223 } 212 return { 213 'show': True, 214 'back': { 215 'link': link({year_field: year_lookup, month_field: month_lookup}), 216 'title': "%s %s" % (month_name, year_lookup) 217 }, 218 'choices': [{'title': "%s %s" % (month_name, day_lookup)}] 219 } 224 220 elif year_lookup and month_lookup: 225 221 date_lookup_params = lookup_params.copy() 226 222 date_lookup_params.update({year_field: year_lookup, month_field: month_lookup}) 227 223 days = get_dates('day', date_lookup_params) 228 return { 'show': True, 229 'back': 230 { 'link' : link({year_field: year_lookup}), 231 'title' : year_lookup 232 }, 233 'choices': 234 [ { 'link' : link({year_field: year_lookup, month_field: month_lookup, day_field: day.day}), 235 'title': day.strftime('%B %d') } for day in days ] 236 } 224 return { 225 'show': True, 226 'back': { 227 'link': link({year_field: year_lookup}), 228 'title': year_lookup 229 }, 230 'choices': [{ 231 'link': link({year_field: year_lookup, month_field: month_lookup, day_field: day.day}), 232 'title': day.strftime('%B %d') 233 } for day in days] 234 } 237 235 elif year_lookup: 238 236 date_lookup_params = lookup_params.copy() 239 237 date_lookup_params.update({year_field: year_lookup}) 240 238 months = get_dates('month', date_lookup_params) 241 return { 'show' : True, 242 'back': 243 { 'link' : link({}), 244 'title': _('All dates') 245 }, 246 'choices': 247 [ { 'link': link( {year_field: year_lookup, month_field: month.month}), 248 'title': "%s %s" % (month.strftime('%B') , month.year) } for month in months ] 249 } 239 return { 240 'show' : True, 241 'back': { 242 'link' : link({}), 243 'title': _('All dates') 244 }, 245 'choices': [{ 246 'link': link( {year_field: year_lookup, month_field: month.month}), 247 'title': "%s %s" % (month.strftime('%B') , month.year) 248 } for month in months] 249 } 250 250 else: 251 251 years = get_dates('year', lookup_params) 252 return { 'show': True, 253 'choices': 254 [ { 'link': link( {year_field: year.year}), 255 'title': year.year } for year in years ] 256 } 252 return { 253 'show': True, 254 'choices': [{ 255 'link': link({year_field: year.year}), 256 'title': year.year 257 } for year in years ] 258 } 257 259 date_hierarchy = inclusion_tag('admin/date_hierarchy')(date_hierarchy) 258 260 259 261 #@inclusion_tag('admin/search_form') 260 262 def search_form(cl): 261 return { 'cl': cl, 262 'show_result_count': cl.result_count != cl.full_result_count and not cl.opts.one_to_one_field, 263 'search_var': SEARCH_VAR } 263 return { 264 'cl': cl, 265 'show_result_count': cl.result_count != cl.full_result_count and not cl.opts.one_to_one_field, 266 'search_var': SEARCH_VAR 267 } 264 268 search_form = inclusion_tag('admin/search_form')(search_form) 265 269 266 270 #@inclusion_tag('admin/filter') 267 271 def filter(cl, spec): 268 return {'title': spec.title(), 269 'choices' : list(spec.choices(cl))} 272 return {'title': spec.title(), 'choices' : list(spec.choices(cl))} 270 273 filter = inclusion_tag('admin/filter')(filter) 271 274 django/branches/new-admin/django/contrib/admin/views/main.py
r1361 r1430 46 46 return mod, opts 47 47 48 49 48 def index(request): 50 49 return render_to_response('admin/index', {'title': _('Site administration')}, context_instance=Context(request)) … … 62 61 self.get_lookup_params() 63 62 self.get_results(request) 64 self.title = (self.is_popup 65 and _('Select %s') % self.opts.verbose_name 63 self.title = (self.is_popup 64 and _('Select %s') % self.opts.verbose_name 66 65 or _('Select %s to change') % self.opts.verbose_name) 67 66 self.get_filters(request) 68 67 self.pk_attname = self.lookup_opts.pk.attname 69 68 70 69 def get_filters(self, request): 71 70 self.filter_specs = [] 72 73 71 if self.lookup_opts.admin.list_filter and not self.opts.one_to_one_field: 74 72 filter_fields = [self.lookup_opts.get_field(field_name) \ … … 78 76 if spec.has_output(): 79 77 self.filter_specs.append(spec) 80 81 78 self.has_filters = bool(self.filter_specs) 82 79 83 80 def get_query_string(self, new_params={}, remove=[]): 84 81 p = self.params.copy() … … 93 90 p[k] = v 94 91 return '?' + '&'.join(['%s=%s' % (k, v) for k, v in p.items()]).replace(' ', '%20') 95 96 92 97 93 def get_modules_and_options(self, app_label, module_name, request): 98 94 self.mod, self.opts = _get_mod_opts(app_label, module_name) 99 95 if not request.user.has_perm(app_label + '.' + self.opts.get_change_permission()): 100 96 raise PermissionDenied 101 97 102 98 self.lookup_mod, self.lookup_opts = self.mod, self.opts 103 99 … … 114 110 if self.params.has_key(PAGE_VAR): 115 111 del self.params[PAGE_VAR] 116 112 117 113 def get_results(self, request): 118 114 lookup_mod, lookup_params, show_all, page_num = \ … … 127 123 except: 128 124 raise IncorrectLookupParameters() 129 125 130 126 # Get the total number of objects, with no filters applied. 131 127 real_lookup_params = lookup_params.copy() … … 139 135 can_show_all = result_count <= MAX_SHOW_ALL_ALLOWED 140 136 multi_page = result_count > DEFAULT_RESULTS_PER_PAGE 141 137 142 138 # Get the list of objects to display on this page. 143 139 if (show_all and can_show_all) or not multi_page: … … 148 144 except InvalidPage: 149 145 result_list = [] 150 (self.result_count, self.full_result_count, self.result_list, 151 self.can_show_all, self.multi_page, self.paginator) = (result_count, 146 (self.result_count, self.full_result_count, self.result_list, 147 self.can_show_all, self.multi_page, self.paginator) = (result_count, 152 148 full_result_count, result_list, can_show_all, multi_page, paginator ) 153 149 154 150 def url_for_result(self, result): 155 151 return "%s/" % getattr(result, self.pk_attname) 156 152 157 153 def get_ordering(self): 158 154 lookup_opts, params = self.lookup_opts, self.params … … 162 158 # ordering from the query string. 163 159 ordering = lookup_opts.admin.ordering or lookup_opts.ordering or ['-' + lookup_opts.pk.name] 164 160 165 161 # Normalize it to new-style ordering. 166 162 ordering = meta.handle_legacy_orderlist(ordering) 167 163 168 164 if ordering[0].startswith('-'): 169 165 order_field, order_type = ordering[0][1:], 'desc' … … 184 180 order_type = params[ORDER_TYPE_VAR] 185 181 self.order_field, self.order_type = order_field, order_type 186 182 187 183 def get_lookup_params(self): 188 184 # Prepare the lookup parameters for the API lookup. 189 185 (params, order_field, lookup_opts, order_type, opts, query) = \ 190 186 (self.params, self.order_field, self.lookup_opts, self.order_type, self.opts, self.query) 191 187 192 188 lookup_params = params.copy() 193 189 for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR): … … 197 193 # in the related table. 198 194 lookup_order_field = order_field 199 try: 195 try: 200 196 f = lookup_opts.get_field(order_field) 201 197 except meta.FieldDoesNotExist: … … 229 225 or_queries.append(or_query) 230 226 lookup_params['_or'] = or_queries 231 227 232 228 if opts.one_to_one_field: 233 229 lookup_params.update(opts.one_to_one_field.rel.limit_choices_to) 234 230 self.lookup_params = lookup_params 235 231 236 232 237 233 def change_list(request, app_label, module_name): … … 240 236 except IncorrectLookupParameters: 241 237 return HttpResponseRedirect(request.path) 242 238 243 239 c = Context(request, { 244 240 'title': cl.title, … … 247 243 }) 248 244 c.update( { 'has_add_permission': c['perms'][app_label][cl.opts.get_add_permission()]}), 249 return render_to_response('admin/change_list', 245 return render_to_response('admin/change_list', 250 246 context_instance = c) 251 247 change_list = staff_member_required(change_list) … … 271 267 seen_collapse = True 272 268 js.append('js/admin/CollapsedFieldsets.js' ) 273 269 274 270 for field_line in field_set: 275 271 try: … … 285 281 class AdminBoundField(BoundField): 286 282 def __init__(self, field, field_mapping, original): 287 super(AdminBoundField, self).__init__(field,field_mapping,original) 288 289 self.element_id = self.form_fields[0].get_id() 283 super(AdminBoundField, self).__init__(field,field_mapping,original) 284 285 self.element_id = self.form_fields[0].get_id() 290 286 self.has_label_first = not isinstance(self.field, meta.BooleanField) 291 287 self.raw_id_admin = use_raw_id_admin(field) … … 295 291 self.hidden = isinstance(self.field, meta.AutoField) 296 292 self.first = False 297 293 298 294 classes = [] 299 if(self.raw_id_admin): 295 if(self.raw_id_admin): 300 296 classes.append('nowrap') 301 297 if max([bool(f.errors()) for f in self.form_fields]): … … 304 300 self.cell_class_attribute = ' class="%s" ' % ' '.join(classes) 305 301 self._repr_filled = False 306 302 307 303 def _fetch_existing_display(self, func_name): 308 304 class_dict = self.original.__class__.__dict__ 309 305 func = class_dict.get(func_name) 310 306 return func(self.original) 311 307 312 308 def _fill_existing_display(self): 313 if self._display_filled: 309 if self._display_filled: 314 310 return 315 311 #HACK … … 318 314 self._display = self._fetch_existing_display(func_name) 319 315 elif isinstance(self.field.rel, meta.ManyToMany): 320 func_name = 'get_%s_list' % self.field.name 316 func_name = 'get_%s_list' % self.field.name 321 317 self._display = ",".join(self._fetch_existing_display(func_name)) 322 318 self._display_filled = True 323 319 324 320 def existing_display(self): 325 321 self._fill_existing_display() … … 330 326 331 327 def html_error_list(self): 332 return " ".join([form_field.html_error_list() for form_field in self.form_fields if form_field.errors]) 333 328 return " ".join([form_field.html_error_list() for form_field in self.form_fields if form_field.errors]) 334 329 335 330 class AdminBoundFieldLine(BoundFieldLine): … … 343 338 def __init__(self, field_set, field_mapping, original): 344 339 super(AdminBoundFieldSet, self).__init__(field_set, field_mapping, original, AdminBoundFieldLine) 345 340 346 341 class BoundManipulator(object): 347 342 def __init__(self, opts, manipulator, field_mapping): 348 343 self.inline_related_objects = opts.get_followed_related_objects(manipulator.follow) 349 344 self.original = hasattr(manipulator, 'original_object') and manipulator.original_object or None 350 self.bound_field_sets = [field_set.bind(field_mapping, self.original, AdminBoundFieldSet) 345 self.bound_field_sets = [field_set.bind(field_mapping, self.original, AdminBoundFieldSet) 351 346 for field_set in opts.admin.get_field_sets(opts)] 352 347 self.ordered_objects = opts.get_ordered_objects()[:] … … 356 351 super(AdminBoundManipulator, self).__init__(opts, manipulator, field_mapping) 357 352 field_sets = opts.admin.get_field_sets(opts) 358 353 359 354 self.auto_populated_fields = [f for f in opts.fields if f.prepopulate_from] 360 self.javascript_imports = get_javascript_imports(opts, self.auto_populated_fields, self.ordered_objects, field_sets); 361 355 self.javascript_imports = get_javascript_imports(opts, self.auto_populated_fields, self.ordered_objects, field_sets); 356 362 357 self.coltype = self.ordered_objects and 'colMS' or 'colM' 363 358 self.has_absolute_url = hasattr(opts.get_model_module().Klass, 'get_absolute_url') 364 359 self.form_enc_attrib = opts.has_field_type(meta.FileField) and \ 365 360 'enctype="multipart/form-data" ' or '' 366 367 self.first_form_field_id = self.bound_field_sets[0].bound_field_lines[0].bound_fields[0].form_fields[0].get_id(); 361 362 self.first_form_field_id = self.bound_field_sets[0].bound_field_lines[0].bound_fields[0].form_fields[0].get_id(); 368 363 self.ordered_object_pk_names = [o.pk.name for o in self.ordered_objects] 369 364 370 365 self.save_on_top = opts.admin.save_on_top 371 366 self.save_as = opts.admin.save_as 372 367 373 368 self.content_type_id = opts.get_content_type_id() 374 369 self.verbose_name_plural = opts.verbose_name_plural 375 370 self.verbose_name = opts.verbose_name 376 371 self.object_name = opts.object_name 377 372 378 373 def get_ordered_object_pk(self, ordered_obj): 379 374 for name in self.ordered_object_pk_names: … … 381 376 return str(getattr(ordered_obj, name)) 382 377 return "" 383 378 384 379 def render_change_form(opts, manipulator, app_label, context, add=False, change=False, show_delete=False, form_url=''): 385 386 380 extra_context = { 387 381 'add': add, … … 392 386 'app_label': app_label, 393 387 } 394 395 388 context.update(extra_context) 396 397 return render_to_response(["admin/%s/%s/change_form" % (app_label, opts.object_name.lower() ), 398 "admin/%s/change_form" % app_label , 399 "admin/change_form"], 400 context_instance=context) 401 389 return render_to_response(["admin/%s/%s/change_form" % (app_label, opts.object_name.lower() ), 390 "admin/%s/change_form" % app_label , 391 "admin/change_form"], context_instance=context) 392 402 393 def log_add_message(user, opts,manipulator,new_object): 403 394 pk_value = getattr(new_object, opts.pk.attname) … … 415 406 errors = manipulator.get_validation_errors(new_data) 416 407 manipulator.do_html2python(new_data) 417 408 418 409 if not errors and not request.POST.has_key("_preview"): 419 410 new_object = manipulator.save(new_data) … … 440 431 # Add default data. 441 432 new_data = manipulator.flatten_data() 442 433 443 434 # Override the defaults with request.GET, if it exists. 444 435 new_data.update(request.GET) … … 447 438 # Populate the FormWrapper. 448 439 form = formfields.FormWrapper(manipulator, new_data, errors, edit_inline=True) 449 440 450 441 c = Context(request, { 451 442 'title': _('Add %s') % opts.verbose_name, … … 456 447 if object_id_override is not None: 457 448 c['object_id'] = object_id_override 458 449 459 450 return render_change_form(opts, manipulator, app_label, c, add=True) 460 451 add_stage = staff_member_required(add_stage) … … 474 465 change_message = _('No fields changed.') 475 466 log.log_action(user.id, opts.get_content_type_id(), pk_value, str(new_object), log.CHANGE, change_message) 476 467 477 468 def change_stage(request, app_label, module_name, object_id): 478 469 mod, opts = _get_mod_opts(app_label, module_name) … … 492 483 493 484 errors = manipulator.get_validation_errors(new_data) 494 485 495 486 manipulator.do_html2python(new_data) 496 487 if not errors and not request.POST.has_key("_preview"): … … 517 508 # Populate new_data with a "flattened" version of the current data. 518 509 new_data = manipulator.flatten_data() 519 520 # TODO: do this in flatten_data... 510 511 # TODO: do this in flatten_data... 521 512 # If the object has ordered objects on its admin page, get the existing 522 513 # order and flatten it into a comma-separated list of IDs. 523 514 524 515 id_order_list = [] 525 516 for rel_obj in opts.get_ordered_objects(): … … 533 524 form.original = manipulator.original_object 534 525 form.order_objects = [] 535 526 536 527 #TODO Should be done in flatten_data / FormWrapper construction 537 528 for related in opts.get_followed_related_objects(): 538 529 wrt = related.opts.order_with_respect_to 539 if wrt and wrt.rel and wrt.rel.to == opts: 540 func = getattr(manipulator.original_object, 'get_%s_list' % 530 if wrt and wrt.rel and wrt.rel.to == opts: 531 func = getattr(manipulator.original_object, 'get_%s_list' % 541 532 related.get_method_name_part()) 542 533 orig_list = func() 543 534 form.order_objects.extend(orig_list) 544 535 545 536 c = Context(request, { 546 537 'title': _('Change %s') % opts.verbose_name, … … 552 543 553 544 return render_change_form(opts,manipulator, app_label, c, change=True) 554 555 556 545 557 546 def _nest_help(obj, depth, val):
