+
{% for bound_field in bound_fields %}
{{ bound_field.html_error_list }}
{% endfor %}
-
+
{% for bound_field in bound_fields %}
{% if bound_field.has_label_first %}
{% field_label bound_field %}
@@ -16,8 +16,8 @@
{% if change %}
{% if bound_field.field.primary_key %}
- {{ bound_field.original_value }}
- {% endif %}
+ {{ bound_field.original_value }}
+ {% endif %}
{% if bound_field.raw_id_admin %}
{% if bound_field.existing_repr %}
@@ -31,6 +31,6 @@
{{bound_field.field.help_text}}
{% endif %}
- {% endfor %}
+ {% endfor %}
diff --git a/django/conf/admin_templates/admin_field_widget.html b/django/conf/admin_templates/admin_field_widget.html
deleted file mode 100644
index 6a882cd2b6..0000000000
--- a/django/conf/admin_templates/admin_field_widget.html
+++ /dev/null
@@ -1,27 +0,0 @@
-{% if bound_field.is_date_time %}
-
- Date: {{ bound_field.form_fields.0 }}
- Time: {{ bound_field.form_fields.1 }}
-
-{% else %}
- {% if bound_field.is_file_field %}
- {% if bound_field.original_value %}
- Currently:
{{ bound_field.original_value }}
- Change: {% output_all bound_field.form_fields %}
- {% else %}
- {% output_all bound_field.form_fields %}
- {% endif %}
- {% else %}
- {% output_all bound_field.form_fields %}
- {% if bound_field.raw_id_admin %}
-

- {% else %}
- {% if bound_field.needs_add_label %}
-

- {% endif %}
- {% endif %}
- {% endif %}
-{% endif %}
-
-
-
diff --git a/django/core/meta/fields.py b/django/core/meta/fields.py
index 75e5f37925..bb7f4fcc32 100644
--- a/django/core/meta/fields.py
+++ b/django/core/meta/fields.py
@@ -786,6 +786,93 @@ class OneToOne(ManyToOne):
self.lookup_overrides = lookup_overrides or {}
self.raw_id_admin = raw_id_admin
+
+
+class BoundField(object):
+ def __init__(self, field, field_mapping, original):
+ self.field = field
+ self.form_fields = self.resolve_form_fields(field_mapping)
+ self.original = original
+
+ def resolve_form_fields(self, field_mapping):
+ return [field_mapping[name] for name in self.field.get_manipulator_field_names('')]
+
+ def as_field_list(self):
+ return [self.field]
+
+ def original_value(self):
+ return self.original.__dict__[self.field.name]
+
+ def __repr__(self):
+ return "BoundField:(%s, %s)" %( self.field.name, self.form_fields)
+
+class BoundFieldLine(object):
+ def __init__(self, field_line, field_mapping, original, bound_field_class=BoundField):
+ self.bound_fields = [bound_field_class(field, field_mapping, original) for field in field_line]
+
+ def __iter__(self):
+ for bound_field in self.bound_fields:
+ yield bound_field
+
+ def __repr__(self):
+ return "%s:(%s)" % (self.__class__.__name__, self.bound_fields)
+
+ def __len__(self):
+ return len(self.bound_fields)
+
+class FieldLine(object):
+ def __init__(self, linespec, field_locator_func):
+ if isinstance(linespec, basestring):
+ self.fields = [field_locator_func(linespec)]
+ else:
+ self.fields = [field_locator_func(field_name) for field_name in linespec]
+
+ def bind(self, field_mapping, original, bound_field_line_class=BoundFieldLine):
+ return bound_field_line_class(self, field_mapping, original)
+
+ def __iter__(self):
+ for field in self.fields:
+ yield field
+
+ def __len__(self):
+ return len(self.fields)
+
+class BoundFieldSet(object):
+ def __init__(self, field_set, field_mapping, original, bound_field_line_class=BoundFieldLine):
+ self.name = field_set.name
+ self.classes = field_set.classes
+ self.bound_field_lines = [ field_line.bind(field_mapping,original, bound_field_line_class)
+ for field_line in field_set]
+ def __repr__(self):
+ return "%s:(%s,%s)" % (self.__class__.__name__, self.name, self.bound_field_lines)
+
+ def __iter__(self):
+ for bound_field_line in self.bound_field_lines:
+ yield bound_field_line
+
+ def __len__(self):
+ return len(self.bound_field_lines)
+
+class FieldSet(object):
+ def __init__(self, name, classes, field_lines):
+ self.name = name
+ self.field_lines = field_lines
+ self.classes = classes
+
+ def __repr__(self):
+ return "FieldSet:(%s,%s)" % (self.name, self.field_lines)
+
+ def bind(self, field_mapping, original, bound_field_set_class=BoundFieldSet):
+ return bound_field_set_class(self, field_mapping, original)
+
+ def __iter__(self):
+ for field_line in self.field_lines:
+ yield field_line
+
+ def __len__(self):
+ return len(self.field_lines)
+
+
class Admin:
def __init__(self, fields=None, js=None, list_display=None, list_filter=None, date_hierarchy=None,
save_as=False, ordering=None, search_fields=None, save_on_top=False):
@@ -808,7 +895,7 @@ class Admin:
the dict has attribs 'fields' and maybe 'classes'.
fields is a list of subclasses of Field.
- Return value needs to be encapsulated.
+ TODO:Return value needs to be encapsulated.
"""
if self.fields is None:
field_struct = ((None, {'fields': [f.name for f in opts.fields + opts.many_to_many if f.editable and not isinstance(f, AutoField)]}),)
@@ -827,3 +914,23 @@ class Admin:
new_fieldset[1]['fields'] = admin_fields
new_fieldset_list.append(new_fieldset)
return new_fieldset_list
+
+ def get_field_sets(self, opts):
+ if self.fields is None:
+ field_struct = ((None, {
+ 'fields': [f.name for f in opts.fields + opts.many_to_many if f.editable and not isinstance(f, AutoField)]
+ }),)
+ else:
+ field_struct = self.fields
+
+
+ new_fieldset_list = []
+ for fieldset in field_struct:
+ name = fieldset[0]
+ fs_options = fieldset[1]
+ classes = fs_options.get('classes', None)
+ line_specs = fs_options['fields']
+ field_lines = [FieldLine(line_spec, opts.get_field) for line_spec in line_specs]
+ new_fieldset_list.append(FieldSet(name, classes, field_lines) )
+ return new_fieldset_list
+
\ No newline at end of file
diff --git a/django/core/template.py b/django/core/template.py
index 6f1da2a858..c0c95b165c 100644
--- a/django/core/template.py
+++ b/django/core/template.py
@@ -113,6 +113,11 @@ class Template:
def __init__(self, template_string, filename=UNKNOWN_SOURCE):
"Compilation stage"
self.nodelist = compile_string(template_string, filename)
+ from pprint import pprint, pformat
+ print "------------------------"
+ print filename
+ pprint(self.nodelist)
+ print "------------------------"
def __iter__(self):
for node in self.nodelist:
@@ -212,6 +217,11 @@ def tokenize(template_string, filename):
while linebreaks and line != lastline and linebreaks[line] <= upto:
line += 1
+
+ last_bit = template_string[upto:]
+ if len(last_bit):
+ token_tups.append( (last_bit, line) )
+
return [ create_token(tok, (filename, line)) for tok, line in token_tups]
diff --git a/django/templatetags/admin_modify.py b/django/templatetags/admin_modify.py
index fbf9071b01..2ab019b3ee 100644
--- a/django/templatetags/admin_modify.py
+++ b/django/templatetags/admin_modify.py
@@ -8,6 +8,7 @@ from django.utils.functional import curry
from django.core.template_decorators import simple_tag, inclusion_tag
from django.views.admin.main import AdminBoundField
+from django.core.meta.fields import BoundField
import re
word_re = re.compile('[A-Z][a-z]+')
@@ -24,24 +25,24 @@ include_admin_script = simple_tag(include_admin_script)
#@inclusion_tag('admin_submit_line', takes_context=True)
def submit_row(context):
- change = context['change']
- add = context['add']
- show_delete = context['show_delete']
- ordered_objects = context['ordered_objects']
- save_as = context['save_as']
- has_delete_permission = context['has_delete_permission']
- is_popup = context['is_popup']
-
- return {
- 'onclick_attrib' : (ordered_objects and change
- and 'onclick="submitOrderForm();"' or ''),
- 'show_delete_link' : (not is_popup and has_delete_permission
- and (change or show_delete)),
- 'show_save_as_new' : not is_popup and change and save_as,
- 'show_save_and_add_another': not is_popup and (not save_as or add),
- 'show_save_and_continue': not is_popup,
- 'show_save': True
- }
+ change = context['change']
+ add = context['add']
+ show_delete = context['show_delete']
+ ordered_objects = context['ordered_objects']
+ save_as = context['save_as']
+ has_delete_permission = context['has_delete_permission']
+ is_popup = context['is_popup']
+
+ return {
+ 'onclick_attrib' : (ordered_objects and change
+ and 'onclick="submitOrderForm();"' or ''),
+ 'show_delete_link' : (not is_popup and has_delete_permission
+ and (change or show_delete)),
+ 'show_save_as_new' : not is_popup and change and save_as,
+ 'show_save_and_add_another': not is_popup and (not save_as or add),
+ 'show_save_and_continue': not is_popup,
+ 'show_save': True
+ }
srdec = inclusion_tag('admin_submit_line', takes_context=True)
submit_row = srdec(submit_row)
@@ -118,10 +119,10 @@ class FieldWrapper(object):
and self.field.rel.raw_id_admin
class FormFieldCollectionWrapper(object):
- def __init__(self, obj, fields):
- self.obj = obj
+ def __init__(self, field_mapping, fields):
+ self.field_mapping = field_mapping
self.fields = fields
- self.bound_fields = [ AdminBoundField(field, obj['original'], True, self.obj) for field in self.fields ]
+ self.bound_fields = [ AdminBoundField(field, self.field_mapping, field_mapping['original']) for field in self.fields ]
def showurl(self):
return False
@@ -145,7 +146,6 @@ class EditInlineNode(template.Node):
context.pop()
return output
-
def fill_context(self, relation, add, change, context):
field_wrapper_list = relation.editable_fields(FieldWrapper)
@@ -154,13 +154,12 @@ class EditInlineNode(template.Node):
form = template.resolve_variable('form', context)
form_field_collections = form[relation.opts.module_name]
fields = relation.editable_fields()
- form_field_collection_wrapper_list = [FormFieldCollectionWrapper(o,fields) for o in form_field_collections]
+ form_field_collection_wrapper_list = [FormFieldCollectionWrapper(field_mapping ,fields) for field_mapping in form_field_collections]
context['field_wrapper_list'] = field_wrapper_list
context['form_field_collection_wrapper_list'] = form_field_collection_wrapper_list
context['num_headers'] = len(field_wrapper_list)
context['original_row_needed'] = max([fw.use_raw_id_admin() for fw in field_wrapper_list])
-# context['name_prefix'] = "%s." % (var_name,)
#@simple_tag
@@ -215,13 +214,13 @@ def register_one_arg_tag(node):
for node in one_arg_tag_nodes:
register_one_arg_tag(node)
-
-#@inclusion_tag('admin_field', takes_context=True)
-def admin_field_bound(context, argument_val):
- if (isinstance(argument_val, list)):
- bound_fields = argument_val
+
+#@inclusion_tag('admin_field_line', takes_context=True)
+def admin_field_line(context, argument_val):
+ if (isinstance(argument_val, BoundField)):
+ bound_fields = [argument_val]
else:
- bound_fields = [argument_val]
+ bound_fields = [bf for bf in argument_val]
add = context['add']
change = context['change']
@@ -236,15 +235,15 @@ def admin_field_bound(context, argument_val):
if isinstance(bound_fields[0].field, meta.BooleanField):
class_names.append('checkbox-row')
- return {
+ return {
'add' : context['add'],
'change' : context['change'],
'bound_fields' : bound_fields,
'class_names' : " ".join(class_names)
- }
+ }
-afbdec = inclusion_tag('admin_field', takes_context=True)
-admin_field_bound = afbdec(admin_field_bound)
+afbdec = inclusion_tag('admin_field_line', takes_context=True)
+admin_field_line = afbdec(admin_field_line)
diff --git a/django/views/admin/main.py b/django/views/admin/main.py
index 1e451413a1..14b88fcc14 100644
--- a/django/views/admin/main.py
+++ b/django/views/admin/main.py
@@ -1,6 +1,7 @@
# Generic admin views, with admin templates created dynamically at runtime.
from django.core import formfields, meta, template_loader, template
+from django.core.meta.fields import BoundField, BoundFieldLine, BoundFieldSet
from django.core.exceptions import Http404, ObjectDoesNotExist, PermissionDenied
from django.core.extensions import DjangoContext as Context
from django.core.extensions import get_object_or_404, render_to_response
@@ -539,25 +540,10 @@ def get_javascript_imports(opts,auto_populated_fields, ordered_objects, admin_fi
break
return js
-class BoundField(object):
- def __init__(self, field, original, rel, field_mapping):
- self.field = field
- self.form_fields = self.resolve_form_fields(field_mapping)
- self.original = original
- self.rel = rel
- def resolve_form_fields(self, field_mapping):
- return [field_mapping[name] for name in self.field.get_manipulator_field_names('')]
-
- def as_field_list(self):
- return [self.field]
-
- def original_value(self):
- return self.original.__dict__[self.field.name]
-
class AdminBoundField(BoundField):
- def __init__(self, field, original, rel, field_mapping):
- super(AdminBoundField, self).__init__(field,original, rel, field_mapping)
+ def __init__(self, field, field_mapping, original):
+ super(AdminBoundField, self).__init__(field,field_mapping,original)
self.element_id = self.form_fields[0].get_id()
self.has_label_first = not isinstance(self.field, meta.BooleanField)
@@ -577,8 +563,6 @@ class AdminBoundField(BoundField):
self.cell_class_attribute = ' class="%s" ' % ' '.join(classes)
self._repr_filled = False
-
-
def _fetch_existing_repr(self, func_name):
class_dict = self.original.__class__.__dict__
func = class_dict.get(func_name)
@@ -591,9 +575,9 @@ class AdminBoundField(BoundField):
if isinstance(self.field.rel, meta.ManyToOne):
func_name = 'get_%s' % self.field.name
self._repr = self._fetch_existing_repr(func_name)
- elif isinstance(self.field.rel, meta.ManyToMany):
- func_name = 'get_%s_list' % self.field.name
- self._repr = ",".join(self._fetch_existing_repr(func_name))
+ elif isinstance(self.field.rel, meta.ManyToMany):
+ func_name = 'get_%s_list' % self.field.name
+ self._repr = ",".join(self._fetch_existing_repr(func_name))
self._repr_filled = True
def existing_repr(self):
@@ -607,33 +591,24 @@ class AdminBoundField(BoundField):
return " ".join([form_field.html_error_list() for form_field in self.form_fields if form_field.errors])
-class AdminFieldSet(object):
- def __init__(self, fieldset_name, options, form, original):
- self.name = fieldset_name
- self.options = options
- self.bound_field_sets = self.get_bound_field_sets(form, original)
- self.classes = options.get('classes', '')
-
- def __repr__(self):
- return "Fieldset:(%s,%s)" % (self.name, self.bound_field_sets)
-
- def get_bound_field_sets(self, form, original):
- fields = self.options['fields']
- bound_field_sets = [ [AdminBoundField(f, original, False, form) for f in field ] for field in fields]
- for set in bound_field_sets:
- first = True
- for bound_field in set:
- bound_field.first = first
- first = False
-
- return bound_field_sets
+class AdminBoundFieldLine(BoundFieldLine):
+ def __init__(self, field_line, field_mapping, original):
+ super(AdminBoundFieldLine, self).__init__(field_line, field_mapping, original, AdminBoundField)
+ for bound_field in self:
+ bound_field.first = True
+ break
+class AdminBoundFieldSet(BoundFieldSet):
+ def __init__(self, field_set, field_mapping, original):
+ super(AdminBoundFieldSet, self).__init__(field_set, field_mapping, original, AdminBoundFieldLine)
+
+
def fill_extra_context(opts, app_label, context, add=False, change=False, show_delete=False, form_url=''):
admin_field_objs = opts.admin.get_field_objs(opts)
ordered_objects = opts.get_ordered_objects()[:]
auto_populated_fields = [f for f in opts.fields if f.prepopulate_from]
- javascript_imports = get_javascript_imports(opts,auto_populated_fields, ordered_objects, admin_field_objs);
+ javascript_imports = get_javascript_imports(opts, auto_populated_fields, ordered_objects, admin_field_objs);
if ordered_objects:
coltype = 'colMS'
@@ -646,25 +621,26 @@ def fill_extra_context(opts, app_label, context, add=False, change=False, show_d
form = context['form']
original = context['original']
- admin_fieldsets = [AdminFieldSet(name, options, form, original) for name, options in admin_field_objs]
+ bound_field_sets = [field_set.bind(form, original, AdminBoundFieldSet)
+ for field_set in opts.admin.get_field_sets(opts)]
+
inline_related_objects = opts.get_inline_related_objects_wrapped()
ordered_object_names = ' '.join(['object.%s' % o.pk.name for o in ordered_objects])
extra_context = {
'add': add,
- 'change': change,
- 'admin_field_objs' : admin_field_objs,
+ 'change': change,
'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,
- 'form_url' : form_url,
- 'admin_fieldsets' : admin_fieldsets,
+ 'form_url' : form_url,
+ 'bound_field_sets' : bound_field_sets,
'inline_related_objects': inline_related_objects,
- 'ordered_object_names' : ordered_object_names,
'content_type_id' : opts.get_content_type_id(),
'save_on_top' : opts.admin.save_on_top,
'verbose_name_plural': opts.verbose_name_plural,