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

Fixed token parsing bug in the error stuff.

Reorganisation and rationalisation of helper objects for admin templates. 


git-svn-id: http://code.djangoproject.com/svn/django/branches/new-admin@802 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Robert Wittams
2005-10-08 14:28:21 +00:00
parent 6e90c35b63
commit 5923c63c8d
8 changed files with 190 additions and 125 deletions

View File

@@ -50,14 +50,14 @@
{% endif %} {% endif %}
<b> <b>
</b> </b>
{% for fieldset in admin_fieldsets %} {% for bound_field_set in bound_field_sets %}
<fieldset class="module aligned {{ fieldset.classes }}"> <fieldset class="module aligned {{ bound_field_set.classes }}">
{% if fieldset.name %} {% if bound_field_set.name %}
<h2>{{fieldset.name }}</h2> <h2>{{bound_field_set.name }}</h2>
{% endif %} {% endif %}
{% for bound_field_set in fieldset.bound_field_sets %} {% for bound_field_line in bound_field_set %}
{% for bound_field in bound_field_set %} {% admin_field_line bound_field_line %}
{% admin_field_bound bound_field %} {% for bound_field in bound_field_line %}
{% filter_interface_script_maybe bound_field %} {% filter_interface_script_maybe bound_field %}
{% endfor %} {% endfor %}
{% endfor %} {% endfor %}

View File

@@ -8,7 +8,7 @@
{% if bound_field.not_in_table %} {% if bound_field.not_in_table %}
{% field_widget bound_field %} {% field_widget bound_field %}
{% else %} {% else %}
{% admin_field_bound bound_field %} {% admin_field_line bound_field %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{%endfor%} {%endfor%}

View File

@@ -1,4 +1,4 @@
<div class="{{ class_names }}"> <div class="{{ class_names }}" >
{% for bound_field in bound_fields %} {% for bound_field in bound_fields %}
{{ bound_field.html_error_list }} {{ bound_field.html_error_list }}
{% endfor %} {% endfor %}
@@ -16,8 +16,8 @@
{% if change %} {% if change %}
{% if bound_field.field.primary_key %} {% if bound_field.field.primary_key %}
{{ bound_field.original_value }} {{ bound_field.original_value }}
{% endif %} {% endif %}
{% if bound_field.raw_id_admin %} {% if bound_field.raw_id_admin %}
{% if bound_field.existing_repr %} {% if bound_field.existing_repr %}
@@ -31,6 +31,6 @@
{{bound_field.field.help_text}} {{bound_field.field.help_text}}
</p> </p>
{% endif %} {% endif %}
{% endfor %}
{% endfor %}
</div> </div>

View File

@@ -1,27 +0,0 @@
{% if bound_field.is_date_time %}
<p class="datetime">
Date: {{ bound_field.form_fields.0 }}<br />
Time: {{ bound_field.form_fields.1 }}
</p>
{% else %}
{% if bound_field.is_file_field %}
{% if bound_field.original_value %}
Currently: <a href="{{ bound_field.original_url }}" > {{ bound_field.original_value }} </a><br />
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 %}
<a href="../../../{{ bound_field.field.rel.to.app_label }}/{{ bound_field.field.rel.to.module_name }}/" class="related-lookup" id="lookup_{{bound_field.element_id}}" onclick="return showRelatedObjectLookupPopup(this);"> <img src="{% admin_media_prefix %}img/admin/selector-search.gif" width="16" height="16" alt="Lookup"></a>
{% else %}
{% if bound_field.needs_add_label %}
<a href="../../../{{ bound_field.field.rel.to.app_label }}/{{ bound_field.field.rel.to.module_name }}/add/" class="add-another" id="add_{{ bound_field.element_id}}" onclick="return showAddAnotherPopup(this);"> <img src="{% admin_media_prefix %}img/admin/icon_addlink.gif" width="10" height="10" alt="Add Another"/></a>
{% endif %}
{% endif %}
{% endif %}
{% endif %}

View File

@@ -786,6 +786,93 @@ class OneToOne(ManyToOne):
self.lookup_overrides = lookup_overrides or {} self.lookup_overrides = lookup_overrides or {}
self.raw_id_admin = raw_id_admin 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: class Admin:
def __init__(self, fields=None, js=None, list_display=None, list_filter=None, date_hierarchy=None, 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): 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'. the dict has attribs 'fields' and maybe 'classes'.
fields is a list of subclasses of Field. 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: 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)]}),) 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[1]['fields'] = admin_fields
new_fieldset_list.append(new_fieldset) new_fieldset_list.append(new_fieldset)
return new_fieldset_list 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

View File

@@ -113,6 +113,11 @@ class Template:
def __init__(self, template_string, filename=UNKNOWN_SOURCE): def __init__(self, template_string, filename=UNKNOWN_SOURCE):
"Compilation stage" "Compilation stage"
self.nodelist = compile_string(template_string, filename) self.nodelist = compile_string(template_string, filename)
from pprint import pprint, pformat
print "------------------------"
print filename
pprint(self.nodelist)
print "------------------------"
def __iter__(self): def __iter__(self):
for node in self.nodelist: for node in self.nodelist:
@@ -213,6 +218,11 @@ def tokenize(template_string, filename):
while linebreaks and line != lastline and linebreaks[line] <= upto: while linebreaks and line != lastline and linebreaks[line] <= upto:
line += 1 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] return [ create_token(tok, (filename, line)) for tok, line in token_tups]
def create_token(token_string, source): def create_token(token_string, source):

View File

@@ -8,6 +8,7 @@ from django.utils.functional import curry
from django.core.template_decorators import simple_tag, inclusion_tag from django.core.template_decorators import simple_tag, inclusion_tag
from django.views.admin.main import AdminBoundField from django.views.admin.main import AdminBoundField
from django.core.meta.fields import BoundField
import re import re
word_re = re.compile('[A-Z][a-z]+') 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) #@inclusion_tag('admin_submit_line', takes_context=True)
def submit_row(context): def submit_row(context):
change = context['change'] change = context['change']
add = context['add'] add = context['add']
show_delete = context['show_delete'] show_delete = context['show_delete']
ordered_objects = context['ordered_objects'] ordered_objects = context['ordered_objects']
save_as = context['save_as'] save_as = context['save_as']
has_delete_permission = context['has_delete_permission'] has_delete_permission = context['has_delete_permission']
is_popup = context['is_popup'] is_popup = context['is_popup']
return { return {
'onclick_attrib' : (ordered_objects and change 'onclick_attrib' : (ordered_objects and change
and 'onclick="submitOrderForm();"' or ''), and 'onclick="submitOrderForm();"' or ''),
'show_delete_link' : (not is_popup and has_delete_permission 'show_delete_link' : (not is_popup and has_delete_permission
and (change or show_delete)), and (change or show_delete)),
'show_save_as_new' : not is_popup and change and save_as, '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_add_another': not is_popup and (not save_as or add),
'show_save_and_continue': not is_popup, 'show_save_and_continue': not is_popup,
'show_save': True 'show_save': True
} }
srdec = inclusion_tag('admin_submit_line', takes_context=True) srdec = inclusion_tag('admin_submit_line', takes_context=True)
submit_row = srdec(submit_row) submit_row = srdec(submit_row)
@@ -118,10 +119,10 @@ class FieldWrapper(object):
and self.field.rel.raw_id_admin and self.field.rel.raw_id_admin
class FormFieldCollectionWrapper(object): class FormFieldCollectionWrapper(object):
def __init__(self, obj, fields): def __init__(self, field_mapping, fields):
self.obj = obj self.field_mapping = field_mapping
self.fields = fields 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): def showurl(self):
return False return False
@@ -145,7 +146,6 @@ class EditInlineNode(template.Node):
context.pop() context.pop()
return output return output
def fill_context(self, relation, add, change, context): def fill_context(self, relation, add, change, context):
field_wrapper_list = relation.editable_fields(FieldWrapper) field_wrapper_list = relation.editable_fields(FieldWrapper)
@@ -154,13 +154,12 @@ class EditInlineNode(template.Node):
form = template.resolve_variable('form', context) form = template.resolve_variable('form', context)
form_field_collections = form[relation.opts.module_name] form_field_collections = form[relation.opts.module_name]
fields = relation.editable_fields() 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['field_wrapper_list'] = field_wrapper_list
context['form_field_collection_wrapper_list'] = form_field_collection_wrapper_list context['form_field_collection_wrapper_list'] = form_field_collection_wrapper_list
context['num_headers'] = len(field_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['original_row_needed'] = max([fw.use_raw_id_admin() for fw in field_wrapper_list])
# context['name_prefix'] = "%s." % (var_name,)
#@simple_tag #@simple_tag
@@ -216,12 +215,12 @@ for node in one_arg_tag_nodes:
register_one_arg_tag(node) register_one_arg_tag(node)
#@inclusion_tag('admin_field', takes_context=True) #@inclusion_tag('admin_field_line', takes_context=True)
def admin_field_bound(context, argument_val): def admin_field_line(context, argument_val):
if (isinstance(argument_val, list)): if (isinstance(argument_val, BoundField)):
bound_fields = argument_val
else:
bound_fields = [argument_val] bound_fields = [argument_val]
else:
bound_fields = [bf for bf in argument_val]
add = context['add'] add = context['add']
change = context['change'] change = context['change']
@@ -244,7 +243,7 @@ def admin_field_bound(context, argument_val):
} }
afbdec = inclusion_tag('admin_field', takes_context=True) afbdec = inclusion_tag('admin_field_line', takes_context=True)
admin_field_bound = afbdec(admin_field_bound) admin_field_line = afbdec(admin_field_line)

View File

@@ -1,6 +1,7 @@
# Generic admin views, with admin templates created dynamically at runtime. # Generic admin views, with admin templates created dynamically at runtime.
from django.core import formfields, meta, template_loader, template 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.exceptions import Http404, ObjectDoesNotExist, PermissionDenied
from django.core.extensions import DjangoContext as Context from django.core.extensions import DjangoContext as Context
from django.core.extensions import get_object_or_404, render_to_response 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 break
return js 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): class AdminBoundField(BoundField):
def __init__(self, field, original, rel, field_mapping): def __init__(self, field, field_mapping, original):
super(AdminBoundField, self).__init__(field,original, rel, field_mapping) super(AdminBoundField, self).__init__(field,field_mapping,original)
self.element_id = self.form_fields[0].get_id() self.element_id = self.form_fields[0].get_id()
self.has_label_first = not isinstance(self.field, meta.BooleanField) 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.cell_class_attribute = ' class="%s" ' % ' '.join(classes)
self._repr_filled = False self._repr_filled = False
def _fetch_existing_repr(self, func_name): def _fetch_existing_repr(self, func_name):
class_dict = self.original.__class__.__dict__ class_dict = self.original.__class__.__dict__
func = class_dict.get(func_name) func = class_dict.get(func_name)
@@ -591,9 +575,9 @@ class AdminBoundField(BoundField):
if isinstance(self.field.rel, meta.ManyToOne): if isinstance(self.field.rel, meta.ManyToOne):
func_name = 'get_%s' % self.field.name func_name = 'get_%s' % self.field.name
self._repr = self._fetch_existing_repr(func_name) self._repr = self._fetch_existing_repr(func_name)
elif isinstance(self.field.rel, meta.ManyToMany): elif isinstance(self.field.rel, meta.ManyToMany):
func_name = 'get_%s_list' % self.field.name func_name = 'get_%s_list' % self.field.name
self._repr = ",".join(self._fetch_existing_repr(func_name)) self._repr = ",".join(self._fetch_existing_repr(func_name))
self._repr_filled = True self._repr_filled = True
def existing_repr(self): 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]) return " ".join([form_field.html_error_list() for form_field in self.form_fields if form_field.errors])
class AdminFieldSet(object): class AdminBoundFieldLine(BoundFieldLine):
def __init__(self, fieldset_name, options, form, original): def __init__(self, field_line, field_mapping, original):
self.name = fieldset_name super(AdminBoundFieldLine, self).__init__(field_line, field_mapping, original, AdminBoundField)
self.options = options for bound_field in self:
self.bound_field_sets = self.get_bound_field_sets(form, original) bound_field.first = True
self.classes = options.get('classes', '') break
def __repr__(self): class AdminBoundFieldSet(BoundFieldSet):
return "Fieldset:(%s,%s)" % (self.name, self.bound_field_sets) def __init__(self, field_set, field_mapping, original):
super(AdminBoundFieldSet, self).__init__(field_set, field_mapping, original, AdminBoundFieldLine)
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
def fill_extra_context(opts, app_label, context, add=False, change=False, show_delete=False, form_url=''): 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) admin_field_objs = opts.admin.get_field_objs(opts)
ordered_objects = opts.get_ordered_objects()[:] ordered_objects = opts.get_ordered_objects()[:]
auto_populated_fields = [f for f in opts.fields if f.prepopulate_from] 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: if ordered_objects:
coltype = 'colMS' coltype = 'colMS'
@@ -646,7 +621,9 @@ def fill_extra_context(opts, app_label, context, add=False, change=False, show_d
form = context['form'] form = context['form']
original = context['original'] 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() inline_related_objects = opts.get_inline_related_objects_wrapped()
ordered_object_names = ' '.join(['object.%s' % o.pk.name for o in ordered_objects]) ordered_object_names = ' '.join(['object.%s' % o.pk.name for o in ordered_objects])
@@ -654,17 +631,16 @@ def fill_extra_context(opts, app_label, context, add=False, change=False, show_d
extra_context = { extra_context = {
'add': add, 'add': add,
'change': change, 'change': change,
'admin_field_objs' : admin_field_objs,
'ordered_objects' : ordered_objects, 'ordered_objects' : ordered_objects,
'ordered_object_names' : ordered_object_names,
'auto_populated_fields' : auto_populated_fields, 'auto_populated_fields' : auto_populated_fields,
'javascript_imports' : javascript_imports, 'javascript_imports' : javascript_imports,
'coltype' : coltype, 'coltype' : coltype,
'has_absolute_url': has_absolute_url, 'has_absolute_url': has_absolute_url,
'form_enc_attrib': form_enc_attrib, 'form_enc_attrib': form_enc_attrib,
'form_url' : form_url, 'form_url' : form_url,
'admin_fieldsets' : admin_fieldsets, 'bound_field_sets' : bound_field_sets,
'inline_related_objects': inline_related_objects, 'inline_related_objects': inline_related_objects,
'ordered_object_names' : ordered_object_names,
'content_type_id' : opts.get_content_type_id(), 'content_type_id' : opts.get_content_type_id(),
'save_on_top' : opts.admin.save_on_top, 'save_on_top' : opts.admin.save_on_top,
'verbose_name_plural': opts.verbose_name_plural, 'verbose_name_plural': opts.verbose_name_plural,