1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

Changed how edit_inline works in the admin. Now it is done by a subclass of BoundRelatedObject.

This means anyone using edit_inline="path/to/template" will need to subclass this ( or 
TabularBoundRelatedObject or StackedBoundRelatedObject). The functionality may be restored if 
it becomes obvious exactly what information should be available to these templates; before it 
was kind of random. 

So you can do 
class MyBoundRelatedObject(TabularBoundRelatedObject):
	def template_name(self):
	    return "path/to/template"

and then edit_inline=MyBoundRelatedObject to duplicate the previous functionality. 



git-svn-id: http://code.djangoproject.com/svn/django/branches/new-admin@986 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Robert Wittams 2005-10-20 23:27:27 +00:00
parent bd47a97997
commit c40fd89b1a
8 changed files with 83 additions and 53 deletions

View File

@ -1,7 +1,7 @@
<fieldset class="module aligned">
{% for fcw in form_field_collection_wrapper_list %}
<h2>{{relation.opts.verbose_name|capfirst }}&nbsp;#{{ forloop.counter }}</h2>
{% if fcw.show_url %}{% if fcw.obj.original %}
{% for fcw in bound_related_object.form_field_collection_wrappers %}
<h2>{{ bound_related_object.relation.opts.verbose_name|capfirst }}&nbsp;#{{ forloop.counter }}</h2>
{% if bound_related_object.show_url %}{% if fcw.obj.original %}
<p><a href="/r/{{ fcw.obj.original.content_type_id }}/{{ fcw.obj.original.id }}/">View on site</a></p>
{% endif %}{% endif %}
{% for bound_field in fcw.bound_fields %}
@ -13,4 +13,3 @@
{% endfor %}
{%endfor%}
</fieldset>

View File

@ -1,12 +1,12 @@
<fieldset class="module">
<h2>{{relation.opts.verbose_name_plural|capfirst}}</h2><table>
<h2>{{bound_related_object.relation.opts.verbose_name_plural|capfirst}}</h2><table>
<thead><tr>
{% for fw in field_wrapper_list %}
{% for fw in bound_related_object.field_wrapper_list %}
{% if fw.needs_header %}
<th{{fw.header_class_attribute}}> {{fw.field.verbose_name|capfirst}} </th>
{% endif %}
{% endfor %}
{% for fcw in form_field_collection_wrapper_list %}
{% for fcw in bound_related_object.form_field_collection_wrappers %}
{% if change %}{% if original_row_needed %}
{% if fcw.obj.original %}
@ -26,14 +26,14 @@
</td>
{% endif %}
{% endfor %}
{% if fcw.show_url %}<td>
{% if bound_related_object.show_url %}<td>
{% if fcw.obj.original %}<a href="/r/{{ fcw.obj.original.content_type_id }}/{{ fcw.obj.original.id }}/">View on site</a>{% endif %}
</td>{% endif %}
</tr>
{% endfor %} </table>
{% for fcw in form_field_collection_wrapper_list %}
{% for fcw in bound_related_object.form_field_collection_wrapper_list %}
{% for bound_field in fcw.bound_fields %}
{% if bound_field.not_in_table %}
{% field_widget bound_field %}

View File

@ -4,11 +4,11 @@ from django.conf.settings import ADMIN_MEDIA_PREFIX
from django.utils.text import capfirst
from django.utils.html import escape
from django.utils.functional import curry
from django.core.template.decorators import simple_tag, inclusion_tag
from django.contrib.admin.views.main import AdminBoundField
from django.core.meta.fields import BoundField, Field
from django.core.meta import BoundRelatedObject, TABULAR, STACKED
import re
word_re = re.compile('[A-Z][a-z]+')
@ -122,14 +122,41 @@ class FieldWrapper(object):
return isinstance(self.field.rel, (meta.ManyToOne, meta.ManyToMany)) \
and self.field.rel.raw_id_admin
class FormFieldCollectionWrapper(object):
def __init__(self, field_mapping, fields):
self.field_mapping = field_mapping
self.fields = fields
self.bound_fields = [ AdminBoundField(field, self.field_mapping, field_mapping['original']) 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
class TabularBoundRelatedObject(BoundRelatedObject):
def __init__(self, related_object, field_mapping, original):
super(TabularBoundRelatedObject, self).__init__(related_object, field_mapping, original)
self.field_wrapper_list = self.relation.editable_fields(FieldWrapper)
fields = self.relation.editable_fields()
self.form_field_collection_wrappers = [FormFieldCollectionWrapper(field_mapping ,fields)
for field_mapping in self.field_mappings]
self.original_row_needed = max([fw.use_raw_id_admin() for fw in self.field_wrapper_list])
self.show_url = original and hasattr(self.relation.opts, 'get_absolute_url')
def template_name(self):
return "admin/edit_inline_tabular"
class StackedBoundRelatedObject(BoundRelatedObject):
def __init__(self, related_object, field_mapping, original):
super(StackedBoundRelatedObject, self).__init__(related_object, field_mapping, original)
fields = self.relation.editable_fields()
self.form_field_collection_wrappers = [FormFieldCollectionWrapper(field_mapping ,fields)
for field_mapping in self.field_mappings]
self.show_url = original and hasattr(self.relation.opts, 'get_absolute_url')
def template_name(self):
return "admin/edit_inline_stacked"
bound_related_object_overrides = {
TABULAR : TabularBoundRelatedObject,
STACKED : StackedBoundRelatedObject
}
class EditInlineNode(template.Node):
def __init__(self, rel_var):
@ -137,34 +164,24 @@ class EditInlineNode(template.Node):
def render(self, context):
relation = template.resolve_variable(self.rel_var, context)
add, change = context['add'], context['change']
context.push()
self.fill_context(relation, add, change, context)
klass = relation.field.rel.edit_inline
bound_related_object_class = bound_related_object_overrides.get(klass, klass)
t = template_loader.get_template(relation.field.rel.edit_inline)
original = context.get('original', None)
bound_related_object = relation.bind(context['form'], original, bound_related_object_class)
context['bound_related_object'] = bound_related_object
t = template_loader.get_template( bound_related_object.template_name() )
output = t.render(context)
context.pop()
return output
def fill_context(self, relation, add, change, context):
field_wrapper_list = relation.editable_fields(FieldWrapper)
var_name = relation.opts.object_name.lower()
form = template.resolve_variable('form', context)
form_field_collections = form[relation.opts.module_name]
fields = relation.editable_fields()
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])
#@simple_tag
def output_all(form_fields):

View File

@ -146,6 +146,16 @@ class FieldDoesNotExist(Exception):
class BadKeywordArguments(Exception):
pass
class BoundRelatedObject(object):
def __init__(self,related_object, field_mapping, original):
self.relation = related_object
self.field_mappings = field_mapping[related_object.opts.module_name]
def template_name(self):
raise NotImplementedException
def __repr__(self):
return repr(self.__dict__)
class RelatedObject(object):
def __init__(self,parent_opts, opts, field):
@ -250,8 +260,8 @@ class RelatedObject(object):
return fields
class BoundRelatedObject(object):
pass
def bind(self, field_mapping, original, bound_related_object_class=BoundRelatedObject):
return bound_related_object_class(self, field_mapping, original)
class Options:
def __init__(self, module_name='', verbose_name='', verbose_name_plural='', db_table='',
@ -469,7 +479,7 @@ class Options:
self._ordered_objects = objects
return self._ordered_objects
def has_field_type(self, field_type, follow):
def has_field_type(self, field_type, follow = None):
"""
Returns True if this object's admin form has at least one of the given
field_type (e.g. FileField).
@ -1754,12 +1764,15 @@ def manipulator_flatten_data(opts, klass, add, change, self):
def manipulator_validator_unique_together(field_name_list, opts, self, field_data, all_data):
from django.utils.text import get_text_list
field_list = [opts.get_field(field_name) for field_name in field_name_list]
if isinstance(field_list[0].rel, ManyToOne):
kwargs = {'%s__%s__iexact' % (field_name_list[0], field_list[0].rel.field_name): field_data}
else:
kwargs = {'%s__iexact' % field_name_list[0]: field_data}
for f in field_list[1:]:
# This is really not going to work for fields that have different form fields, eg DateTime
# This validation needs to occur after html2python to be effective.
field_val = all_data.get(f.column, None)
if field_val is None:
# This will be caught by another validator, assuming the field

View File

@ -16,7 +16,7 @@ BLANK_CHOICE_DASH = [("", "---------")]
BLANK_CHOICE_NONE = [("", "None")]
# Values for Relation.edit_inline.
TABULAR, STACKED = "admin/edit_inline_tabular", "admin/edit_inline_stacked"
TABULAR, STACKED = 1, 2
RECURSIVE_RELATIONSHIP_CONSTANT = 'self'

View File

@ -196,6 +196,12 @@ class Context:
return True
return False
def get(self, key, otherwise):
for dict in self.dicts:
if dict.has_key(key):
return dict[key]
return otherwise
def update(self, other_dict):
"Like dict.update(). Pushes an entire dictionary's keys and values onto the context."
self.dicts = [other_dict] + self.dicts

View File

@ -7,17 +7,13 @@ import os
# At compile time, cache the directories to search.
app_template_dirs = []
for app in INSTALLED_APPS:
try:
i = app.rfind('.')
m, a = app[:i], app[i+1:]
mod = getattr(__import__(m, '', '', [a]), a)
template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
if os.path.isdir(template_dir):
app_template_dirs.append(template_dir)
except Exception, e:
print "exception loading"
print e
raise e
i = app.rfind('.')
m, a = app[:i], app[i+1:]
mod = getattr(__import__(m, '', '', [a]), a)
template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
if os.path.isdir(template_dir):
app_template_dirs.append(template_dir)
# It won't change, so convert it to a tuple to save memory.
app_template_dirs = tuple(app_template_dirs)

View File

@ -100,7 +100,6 @@ class TestRunner:
self.output(1, "Creating test database")
try:
cursor.execute("CREATE DATABASE %s" % TEST_DATABASE_NAME)
print "created"
except Exception, e:
self.output(0, "There was an error creating the test database:%s " % str(e))
confirm = raw_input("The test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME)