Kaydet (Commit) 9dda4abe authored tarafından Adrian Holovaty's avatar Adrian Holovaty

MERGED NEW-ADMIN BRANCH (except for po/mo files, which will come in a separate commit)

git-svn-id: http://code.djangoproject.com/svn/django/trunk@1434 bcc190cf-cafb-0310-a4f2-bffc1f526a37
üst 4fe5c9b7
......@@ -16,19 +16,19 @@ def validate_class(klass):
assert isinstance(f.rel, meta.ManyToMany), \
"ManyToManyField %s should have 'rel' set to a ManyToMany instance." % f.name
# Inline related objects.
for rel_opts, rel_field in opts.get_inline_related_objects():
assert len([f for f in rel_opts.fields if f.core]) > 0, \
for related in opts.get_followed_related_objects():
assert len([f for f in related.opts.fields if f.core]) > 0, \
"At least one field in %s should have core=True, because it's being edited inline by %s." % \
(rel_opts.object_name, opts.object_name)
(related.opts.object_name, opts.object_name)
# All related objects.
related_apps_seen = []
for rel_opts, rel_field in opts.get_all_related_objects():
if rel_opts in related_apps_seen:
assert rel_field.rel.related_name is not None, \
for related in opts.get_all_related_objects():
if related.opts in related_apps_seen:
assert related.field.rel.related_name is not None, \
"Relationship in field %s.%s needs to set 'related_name' because more than one" \
" %s object is referenced in %s." % \
(rel_opts.object_name, rel_field.name, opts.object_name, rel_opts.object_name)
related_apps_seen.append(rel_opts)
(related.opts.object_name, related.field.name, opts.object_name, rel_opts.object_name)
related_apps_seen.append(related.opts)
# Etc.
if opts.admin is not None:
assert opts.admin.ordering or opts.ordering, \
......
"""
FilterSpec encapsulates the logic for displaying filters in the Django admin.
Filters are specified in models with the "list_filter" option.
Each filter subclass knows how to display a filter for a field that passes a
certain test -- e.g. being a DateField or ForeignKey.
"""
from django.core import meta
import datetime
class FilterSpec(object):
filter_specs = []
def __init__(self, f, request, params):
self.field = f
self.params = params
def register(cls, test, factory):
cls.filter_specs.append( (test, factory) )
register = classmethod(register)
def create(cls, f, request, params):
for test, factory in cls.filter_specs:
if test(f):
return factory(f, request, params)
create = classmethod(create)
def has_output(self):
return True
def choices(self, cl):
raise NotImplementedError()
def title(self):
return self.field.verbose_name
def output(self, cl):
t = []
if self.has_output():
t.append(_('<h3>By %s:</h3>\n<ul>\n') % self.title())
for choice in self.choices(cl):
t.append('<li%s><a href="%s">%s</a></li>\n' % \
((choice['selected'] and ' class="selected"' or ''),
choice['query_string'] ,
choice['display']))
t.append('</ul>\n\n')
return "".join(t)
class RelatedFilterSpec(FilterSpec):
def __init__(self, f, request, params):
super(RelatedFilterSpec, self).__init__(f, request, params)
if isinstance(f, meta.ManyToManyField):
self.lookup_title = f.rel.to.verbose_name
else:
self.lookup_title = f.verbose_name
self.lookup_kwarg = '%s__%s__exact' % (f.name, f.rel.to.pk.name)
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
self.lookup_choices = f.rel.to.get_model_module().get_list()
def has_output(self):
return len(self.lookup_choices) > 1
def title(self):
return self.lookup_title
def choices(self, cl):
yield {'selected': self.lookup_val is None,
'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
'display': _('All')}
for val in self.lookup_choices:
pk_val = getattr(val, self.field.rel.to.pk.attname)
yield {'selected': self.lookup_val == str(pk_val),
'query_string': cl.get_query_string( {self.lookup_kwarg: pk_val}),
'display': val}
FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)
class ChoicesFilterSpec(FilterSpec):
def __init__(self, f, request, params):
super(ChoicesFilterSpec, self).__init__(f, request, params)
self.lookup_kwarg = '%s__exact' % f.name
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
def choices(self, cl):
yield {'selected': self.lookup_val is None,
'query_string': cl.get_query_string( {}, [self.lookup_kwarg]),
'display': _('All')}
for k, v in self.field.choices:
yield {'selected': str(k) == self.lookup_val,
'query_string': cl.get_query_string( {self.lookup_kwarg: k}),
'display': v}
FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec)
class DateFieldFilterSpec(FilterSpec):
def __init__(self, f, request, params):
super(DateFieldFilterSpec, self).__init__(f, request, params)
self.field_generic = '%s__' % self.field.name
self.date_params = dict([(k, v) for k, v in params.items() if k.startswith(self.field_generic)])
today = datetime.date.today()
one_week_ago = today - datetime.timedelta(days=7)
today_str = isinstance(self.field, meta.DateTimeField) and today.strftime('%Y-%m-%d 23:59:59') or today.strftime('%Y-%m-%d')
self.links = (
(_('Any date'), {}),
(_('Today'), {'%s__year' % self.field.name: str(today.year),
'%s__month' % self.field.name: str(today.month),
'%s__day' % self.field.name: str(today.day)}),
(_('Past 7 days'), {'%s__gte' % self.field.name: one_week_ago.strftime('%Y-%m-%d'),
'%s__lte' % f.name: today_str}),
(_('This month'), {'%s__year' % self.field.name: str(today.year),
'%s__month' % f.name: str(today.month)}),
(_('This year'), {'%s__year' % self.field.name: str(today.year)})
)
def title(self):
return self.field.verbose_name
def choices(self, cl):
for title, param_dict in self.links:
yield {'selected': self.date_params == param_dict,
'query_string': cl.get_query_string( param_dict, self.field_generic),
'display': title}
FilterSpec.register(lambda f: isinstance(f, meta.DateField), DateFieldFilterSpec)
class BooleanFieldFilterSpec(FilterSpec):
def __init__(self, f, request, params):
super(BooleanFieldFilterSpec, self).__init__(f, request, params)
self.lookup_kwarg = '%s__exact' % f.name
self.lookup_kwarg2 = '%s__isnull' % f.name
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
self.lookup_val2 = request.GET.get(self.lookup_kwarg2, None)
def title(self):
return self.field.verbose_name
def choices(self, cl):
for k, v in ((_('All'), None), (_('Yes'), '1'), (_('No'), '0')):
yield {'selected': self.lookup_val == v and not self.lookup_val2,
'query_string': cl.get_query_string( {self.lookup_kwarg: v}, [self.lookup_kwarg2]),
'display': k}
if isinstance(self.field, meta.NullBooleanField):
yield {'selected': self.lookup_val2 == 'True',
'query_string': cl.get_query_string( {self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]),
'display': _('Unknown')}
FilterSpec.register(lambda f: isinstance(f, meta.BooleanField) or isinstance(f, meta.NullBooleanField), BooleanFieldFilterSpec)
{% extends "admin/base_site" %}
{% load i18n %}
{% load admin_modify %}
{% load adminmedia %}
{% block extrahead %}
{% for js in bound_manipulator.javascript_imports %}{% include_admin_script js %}{% endfor %}
{% endblock %}
{% block coltype %}{{ bound_manipulator.coltype }}{% endblock %}
{% block bodyclass %}{{ app_label }}-{{ bound_manipulator.object_name.lower }} change-form{% endblock %}
{% block breadcrumbs %}{% if not is_popup %}
<div class="breadcrumbs">
<a href="../../../">{% trans "Home" %}</a> &rsaquo;
<a href="../">{{ bound_manipulator.verbose_name_plural|capfirst }}</a> &rsaquo;
{% if add %}{% trans "Add" %} {{ bound_manipulator.verbose_name }}{% else %}{{ bound_manipulator.original|striptags|truncatewords:"18" }}{% endif %}
</div>
{% endif %}{% endblock %}
{% block content %}<div id="content-main">
{% if change %}{% if not is_popup %}
<ul class="object-tools"><li><a href="history/" class="historylink">{% trans "History" %}</a></li>
{% if bound_manipulator.has_absolute_url %}<li><a href="/r/{{ bound_manipulator.content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
</ul>
{% endif %}{% endif %}
<form {{ bound_manipulator.form_enc_attrib }} action='{{ form_url }}' method="post">{% block form_top %}{% endblock %}
{% if is_popup %}<input type="hidden" name="_popup" value="1">{% endif %}
{% if bound_manipulator.save_on_top %}{% submit_row bound_manipulator %}{% endif %}
{% if form.error_dict %}
<p class="errornote">
{% blocktrans count form.error_dict.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
</p>
{% endif %}
{% for bound_field_set in bound_manipulator.bound_field_sets %}
<fieldset class="module aligned {{ bound_field_set.classes }}">
{% if bound_field_set.name %}<h2>{{ bound_field_set.name }}</h2>{% endif %}
{% for bound_field_line in bound_field_set %}
{% admin_field_line bound_field_line %}
{% for bound_field in bound_field_line %}
{% filter_interface_script_maybe bound_field %}
{% endfor %}
{% endfor %}
</fieldset>
{% endfor %}
{% block after_field_sets %}{% endblock %}
{% if change %}
{% if bound_manipulator.ordered_objects %}
<fieldset class="module"><h2>{% trans "Ordering" %}</h2>
<div class="form-row{% if form.order_.errors %} error{% endif %} ">
{% if form.order_.errors %}{{ form.order_.html_error_list }}{% endif %}
<p><label for="id_order_">{% trans "Order:" %}</label> {{ form.order_ }}</p>
</div></fieldset>
{% endif %}
{% endif %}
{% for related_object in bound_manipulator.inline_related_objects %}{% edit_inline related_object %}{% endfor %}
{% block after_related_objects %}{% endblock %}
{% submit_row bound_manipulator %}
{% if add %}
<script type="text/javascript">document.getElementById("{{ bound_manipulator.first_form_field_id }}").focus();</script>
{% endif %}
{% if bound_manipulator.auto_populated_fields %}
<script type="text/javascript">
{% auto_populated_field_script bound_manipulator.auto_populated_fields change %}
</script>
{% endif %}
{% if change %}
{% if bound_manipulator.ordered_objects %}
{% if form.order_objects %}<ul id="orderthese">
{% for object in form.order_objects %}
<li id="p{% object_pk bound_manipulator object %}">
<span id="handlep{% object_pk bound_manipulator object %}">{{ object|truncatewords:"5" }}</span>
</li>
{% endfor %}
</ul>{% endif %}
{% endif %}
{% endif %}
</form></div>
{% endblock %}
{% load admin_list %}
{% load i18n %}
{% extends "admin/base_site" %}
{% block bodyclass %}change-list{% endblock %}
{% if not is_popup %}{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> &rsaquo; {{ cl.opts.verbose_name_plural|capfirst }} </div>{% endblock %}{% endif %}
{% block coltype %}flex{% endblock %}
{% block content %}
<div id="content-main">
{% if has_add_permission %}
<ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
{% endif %}
<div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
{% search_form cl %}
{% date_hierarchy cl %}
{% filters cl %}
{% result_list cl %}
{% pagination cl %}
</div>
</div>
{% endblock %}
<table cellspacing="0">
<thead>
<tr>
{% for header in result_headers %}<th{{ header.class_attrib }}>
{% if header.sortable %}<a href="{{ header.url }}">{% endif %}
{{ header.text|capfirst }}
{% if header.sortable %}</a>{% endif %}</th>{% endfor %}
</tr>
</thead>
{% for result in results %}
<tr class="{% cycle row1,row2 %}">{% for item in result %}{{ item }}{% endfor %}</tr>
{% endfor %}
</table>
{% if show %}
<div class="xfull">
<ul class="toplinks">
{% if back %}<li class="date-back"><a href="{{ back.link }}">&lsaquo; {{ back.title }}</a></li>{% endif %}
{% for choice in choices %}
<li> {% if choice.link %}<a href="{{ choice.link }}">{% endif %}{{ choice.title }}{% if choice.link %}</a>{% endif %}</li>
{% endfor %}
</ul><br class="clear" />
</div>
{% endif %}
\ No newline at end of file
<fieldset class="module aligned">
{% 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 %}
{% if bound_field.hidden %}
{% field_widget bound_field %}
{% else %}
{% admin_field_line bound_field %}
{% endif %}
{% endfor %}
{% endfor %}
</fieldset>
\ No newline at end of file
<fieldset class="module">
<h2>{{ bound_related_object.relation.opts.verbose_name_plural|capfirst }}</h2><table>
<thead><tr>
{% 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 bound_related_object.form_field_collection_wrappers %}
{% if change %}{% if original_row_needed %}
{% if fcw.obj.original %}
<tr class="row-label {% cycle row1,row2 %}"><td colspan="{{ num_headers }}"><strong>{{ fcw.obj.original }}</strong></tr>
{% endif %}
{% endif %}{% endif %}
{% if fcw.obj.errors %}
<tr class="errorlist"><td colspan="{{ num_headers }}">
{{ fcw.obj.html_combined_error_list }}
</tr>
{% endif %}
<tr class="{% cycle row1,row2 %}">
{% for bound_field in fcw.bound_fields %}
{% if not bound_field.hidden %}
<td {{ bound_field.cell_class_attribute }}>
{% field_widget bound_field %}
</td>
{% endif %}
{% endfor %}
{% 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 bound_related_object.form_field_collection_wrappers %}
{% for bound_field in fcw.bound_fields %}
{% if bound_field.hidden %}
{% field_widget bound_field %}
{% endif %}
{% endfor %}
{% endfor %}
</fieldset>
<div class="{{ class_names }}" >
{% 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 %}
{% endif %}
{% field_widget bound_field %}
{% if not bound_field.has_label_first %}
{% field_label bound_field %}
{% endif %}
{% if change %}
{% if bound_field.field.primary_key %}
{{ bound_field.original_value }}
{% endif %}
{% if bound_field.raw_id_admin %}
{% if bound_field.existing_display %}&nbsp;<strong>{{ bound_field.existing_display|truncatewords:"14" }}</strong>{% endif %}
{% endif %}
{% endif %}
{% if bound_field.field.help_text %}<p class="help">{{ bound_field.field.help_text }}</p>{% endif %}
{% endfor %}
</div>
<h3>{% blocktrans %} By {{ title }} {% endblocktrans %}</h3>
<ul>
{% for choice in choices %}
<li{% if choice.selected %} class="selected"{% endif %}>
<a href="{{ choice.query_string }}">{{ choice.display }}</a></li>
{% endfor %}
</ul>
{% if cl.has_filters %}<div id="changelist-filter">
<h2>Filter</h2>
{% for spec in cl.filter_specs %}
{% filter cl spec %}
{% endfor %}</div>{% endif %}
<p class="paginator">
{% if pagination_required %}
{% for i in page_range %}
{% paginator_number cl i %}
{% endfor %}
{% endif %}
{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %}
{% if show_all_url %}&nbsp;&nbsp;<a href="{{ show_all_url }}" class="showall">Show all</a>{% endif %}
</p>
{% if cl.lookup_opts.admin.search_fields %}
<div id="toolbar"><form id="changelist-search" action="" method="get">
<label><img src="{% admin_media_prefix %}img/admin/icon_searchbox.png" /></label>
<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query|escape }}" id="searchbar" />
<input type="submit" value="Go" />
{% if show_result_count %}
<span class="small quiet">{{ cl.result_count }} result{{ cl.result_count|pluralize }} (<a href="?">{{ cl.full_result_count }} total</a>)</span>
{% endif %}
{% for pair in cl.params.items %}
{% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0|escape }}" value="{{ pair.1|escape }}"/>{% endifnotequal %}
{% endfor %}
</form></div>
<script type="text/javascript">document.getElementById("searchbar").focus();</script>
{% endif %}
{% load i18n %}
<div class="submit-row">
{% if show_delete_link %}<p class="float-left"><a href="delete/" class="deletelink">{% trans "Delete" %}</a></p>{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% trans 'Save as new' %}" name="_saveasnew" {{ onclick_attrib }}/>{%endif%}
{% if show_save_and_add_another %}<input type="submit" value="{% trans 'Save and add another' %}" name="_addanother" {{ onclick_attrib }} />{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% trans 'Save and continue editing' %}" name="_continue" {{ onclick_attrib }}/>{% endif %}
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" {{ onclick_attrib }}/>{% endif %}
</div>
{% extends "admin/base_site" %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Home</a> &rsaquo; <a href="../">Documentation</a> &rsaquo; Bookmarklets</div>{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">{% trans "Home" %}</a> &rsaquo; <a href="../">{% trans "Documentation" %}</a> &rsaquo; {% trans "Bookmarklets" %}</div>{% endblock %}
{% block title %}Documentation bookmarklets{% endblock %}
{% block title %}{% trans "Documentation bookmarklets" %}{% endblock %}
{% block content %}
{% blocktrans %}
<p class="help">To install bookmarklets, drag the link to your bookmarks
toolbar, or right-click the link and add it to your bookmarks. Now you can
select the bookmarklet from any page in the site. Note that some of these
bookmarklets require you to be viewing the site from a computer designated
as "internal" (talk to your system administrator if you aren't sure if
your computer is "internal").</p>
{% endblocktrans %}
<div id="content-main">
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('HEAD',location.href,false);x.send(null);try{view=x.getResponseHeader('x-view');}catch(e){alert('No view found for this page');return;}if(view=="undefined"){alert("No view found for this page");}document.location='{{ admin_url }}/doc/views/'+view+'/';})()">Documentation for this page</a></h3>
<p>Jumps you from any page to the documentation for the view that generates that page.</p>
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('HEAD',location.href,false);x.send(null);try{view=x.getResponseHeader('x-view');}catch(e){alert('No view found for this page');return;}if(view=="undefined"){alert("No view found for this page");}document.location='{{ admin_url }}/doc/views/'+view+'/';})()">{% trans "Documentation for this page" %}</a></h3>
<p>{% trans "Jumps you from any page to the documentation for the view that generates that page." %}</p>
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{type=x.getResponseHeader('x-object-type');id=x.getResponseHeader('x-object-id');}catch(e){type='(none)';id='(none)';}d=document;b=d.body;e=d.createElement('div');e.id='xxxhhh';s=e.style;s.position='absolute';s.left='10px';s.top='10px';s.font='10px monospace';s.border='1px black solid';s.padding='4px';s.backgroundColor='#eee';e.appendChild(d.createTextNode('Type: '+type));e.appendChild(d.createElement('br'));e.appendChild(d.createTextNode('ID: '+id));e.appendChild(d.createElement('br'));l=d.createElement('a');l.href='#';l.onclick=function(){b.removeChild(e);};l.appendChild(d.createTextNode('[close]'));l.style.textDecoration='none';e.appendChild(l);b.appendChild(e);})();">Show object ID</a></h3>
<p>Shows the content-type and unique ID for pages that represent a single object.</p>
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{type=x.getResponseHeader('x-object-type');id=x.getResponseHeader('x-object-id');}catch(e){type='(none)';id='(none)';}d=document;b=d.body;e=d.createElement('div');e.id='xxxhhh';s=e.style;s.position='absolute';s.left='10px';s.top='10px';s.font='10px monospace';s.border='1px black solid';s.padding='4px';s.backgroundColor='#eee';e.appendChild(d.createTextNode('Type: '+type));e.appendChild(d.createElement('br'));e.appendChild(d.createTextNode('ID: '+id));e.appendChild(d.createElement('br'));l=d.createElement('a');l.href='#';l.onclick=function(){b.removeChild(e);};l.appendChild(d.createTextNode('[close]'));l.style.textDecoration='none';e.appendChild(l);b.appendChild(e);})();">{% trans "Show object ID" %}</a></h3>
<p>{% trans "Shows the content-type and unique ID for pages that represent a single object." %}</p>
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){var x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){var x=new XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{var type=x.getResponseHeader('x-object-type');var id=x.getResponseHeader('x-object-id');}catch(e){return;}document.location='{{ admun_url }}/'+type.split('.').join('/')+'/'+id+'/';})()">Edit this object (current window)</a></h3>
<p>Jumps to the admin page for pages that represent a single object.</p>
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){var x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){var x=new XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{var type=x.getResponseHeader('x-object-type');var id=x.getResponseHeader('x-object-id');}catch(e){return;}document.location='{{ admun_url }}/'+type.split('.').join('/')+'/'+id+'/';})()">{% trans "Edit this object (current window)" %}</a></h3>
<p>{% trans "Jumps to the admin page for pages that represent a single object." %}</p>
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){var x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){var x=new XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{var type=x.getResponseHeader('x-object-type');var id=x.getResponseHeader('x-object-id');}catch(e){return;}window.open('{{ admun_url }}/'+type.split('.').join('/')+'/'+id+'/');})()">Edit this object (new window)</a></h3>
<p>As above, but opens the admin page in a new window.</p>
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){var x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){var x=new XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{var type=x.getResponseHeader('x-object-type');var id=x.getResponseHeader('x-object-id');}catch(e){return;}window.open('{{ admun_url }}/'+type.split('.').join('/')+'/'+id+'/');})()">{% trans "Edit this object (new window)" %}</a></h3>
<p>{% trans "As above, but opens the admin page in a new window." %}</p>
</div>
{% endblock %}
<p class="datetime">
Date: {{ bound_field.form_fields.0 }}<br />
Time: {{ bound_field.form_fields.1 }}
</p>
{% 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 %}
{% 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 %}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -670,12 +670,12 @@ def get_validation_errors(outfile):
e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name)
# Check core=True, if needed.
for rel_opts, rel_field in opts.get_inline_related_objects():
for related in opts.get_followed_related_objects():
try:
for f in rel_opts.fields:
for f in related.opts.fields:
if f.core:
raise StopIteration
e.add(rel_opts, "At least one field in %s should have core=True, because it's being edited inline by %s.%s." % (rel_opts.object_name, opts.module_name, opts.object_name))
e.add(related.opts, "At least one field in %s should have core=True, because it's being edited inline by %s.%s." % (related.opts.object_name, opts.module_name, opts.object_name))
except StopIteration:
pass
......
This diff is collapsed.
This diff is collapsed.
......@@ -19,58 +19,61 @@ for mod in modules:
# Add "get_thingie", "get_thingie_count" and "get_thingie_list" methods
# for all related objects.
for rel_obj, rel_field in klass._meta.get_all_related_objects():
for related in klass._meta.get_all_related_objects():
# Determine whether this related object is in another app.
# If it's in another app, the method names will have the app
# label prepended, and the add_BLAH() method will not be
# generated.
rel_mod = rel_obj.get_model_module()
rel_obj_name = klass._meta.get_rel_object_method_name(rel_obj, rel_field)
if isinstance(rel_field.rel, meta.OneToOne):
rel_mod = related.opts.get_model_module()
rel_obj_name = related.get_method_name_part()
if isinstance(related.field.rel, meta.OneToOne):
# Add "get_thingie" methods for one-to-one related objects.
# EXAMPLE: Place.get_restaurants_restaurant()
func = curry(meta.method_get_related, 'get_object', rel_mod, rel_field)
func.__doc__ = "Returns the associated `%s.%s` object." % (rel_obj.app_label, rel_obj.module_name)
func = curry(meta.method_get_related, 'get_object', rel_mod, related.field)
func.__doc__ = "Returns the associated `%s.%s` object." % (related.opts.app_label, related.opts.module_name)
setattr(klass, 'get_%s' % rel_obj_name, func)
elif isinstance(rel_field.rel, meta.ManyToOne):
elif isinstance(related.field.rel, meta.ManyToOne):
# Add "get_thingie" methods for many-to-one related objects.
# EXAMPLE: Poll.get_choice()
func = curry(meta.method_get_related, 'get_object', rel_mod, rel_field)
func.__doc__ = "Returns the associated `%s.%s` object matching the given criteria." % (rel_obj.app_label, rel_obj.module_name)
func = curry(meta.method_get_related, 'get_object', rel_mod, related.field)
func.__doc__ = "Returns the associated `%s.%s` object matching the given criteria." % \
(related.opts.app_label, related.opts.module_name)
setattr(klass, 'get_%s' % rel_obj_name, func)
# Add "get_thingie_count" methods for many-to-one related objects.
# EXAMPLE: Poll.get_choice_count()
func = curry(meta.method_get_related, 'get_count', rel_mod, rel_field)
func.__doc__ = "Returns the number of associated `%s.%s` objects." % (rel_obj.app_label, rel_obj.module_name)
func = curry(meta.method_get_related, 'get_count', rel_mod, related.field)
func.__doc__ = "Returns the number of associated `%s.%s` objects." % \
(related.opts.app_label, related.opts.module_name)
setattr(klass, 'get_%s_count' % rel_obj_name, func)
# Add "get_thingie_list" methods for many-to-one related objects.
# EXAMPLE: Poll.get_choice_list()
func = curry(meta.method_get_related, 'get_list', rel_mod, rel_field)
func.__doc__ = "Returns a list of associated `%s.%s` objects." % (rel_obj.app_label, rel_obj.module_name)
func = curry(meta.method_get_related, 'get_list', rel_mod, related.field)
func.__doc__ = "Returns a list of associated `%s.%s` objects." % \
(related.opts.app_label, related.opts.module_name)
setattr(klass, 'get_%s_list' % rel_obj_name, func)
# Add "add_thingie" methods for many-to-one related objects,
# but only for related objects that are in the same app.
# EXAMPLE: Poll.add_choice()
if rel_obj.app_label == klass._meta.app_label:
func = curry(meta.method_add_related, rel_obj, rel_mod, rel_field)
if related.opts.app_label == klass._meta.app_label:
func = curry(meta.method_add_related, related.opts, rel_mod, related.field)
func.alters_data = True
setattr(klass, 'add_%s' % rel_obj_name, func)
del func
del rel_obj_name, rel_mod, rel_obj, rel_field # clean up
del rel_obj_name, rel_mod, related # clean up
# Do the same for all related many-to-many objects.
for rel_opts, rel_field in klass._meta.get_all_related_many_to_many_objects():
rel_mod = rel_opts.get_model_module()
rel_obj_name = klass._meta.get_rel_object_method_name(rel_opts, rel_field)
setattr(klass, 'get_%s' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_object', klass._meta, rel_mod, rel_field))
setattr(klass, 'get_%s_count' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_count', klass._meta, rel_mod, rel_field))
setattr(klass, 'get_%s_list' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_list', klass._meta, rel_mod, rel_field))
if rel_opts.app_label == klass._meta.app_label:
func = curry(meta.method_set_related_many_to_many, rel_opts, rel_field)
for related in klass._meta.get_all_related_many_to_many_objects():
rel_mod = related.opts.get_model_module()
rel_obj_name = related.get_method_name_part()
setattr(klass, 'get_%s' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_object', klass._meta, rel_mod, related.field))
setattr(klass, 'get_%s_count' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_count', klass._meta, rel_mod, related.field))
setattr(klass, 'get_%s_list' % rel_obj_name, curry(meta.method_get_related_many_to_many, 'get_list', klass._meta, rel_mod, related.field))
if related.opts.app_label == klass._meta.app_label:
func = curry(meta.method_set_related_many_to_many, related.opts, related.field)
func.alters_data = True
setattr(klass, 'set_%s' % rel_opts.module_name, func)
setattr(klass, 'set_%s' % related.opts.module_name, func)
del func
del rel_obj_name, rel_mod, rel_opts, rel_field # clean up
del rel_obj_name, rel_mod, related # clean up
# Add "set_thingie_order" and "get_thingie_order" methods for objects
# that are ordered with respect to this.
......
......@@ -9,7 +9,7 @@ from django.core.exceptions import Http404, ObjectDoesNotExist, ImproperlyConfig
def create_object(request, app_label, module_name, template_name=None,
template_loader=template_loader, extra_context={},
post_save_redirect=None, login_required=False):
post_save_redirect=None, login_required=False, follow=None):
"""
Generic object-creation function.
......@@ -22,17 +22,17 @@ def create_object(request, app_label, module_name, template_name=None,
return redirect_to_login(request.path)
mod = models.get_module(app_label, module_name)
manipulator = mod.AddManipulator()
manipulator = mod.AddManipulator(follow=follow)
if request.POST:
# If data was POSTed, we're trying to create a new object
new_data = request.POST.copy()
# Check for errors
errors = manipulator.get_validation_errors(new_data)
manipulator.do_html2python(new_data)
if not errors:
# No errors -- this means we can save the data!
manipulator.do_html2python(new_data)
new_object = manipulator.save(new_data)
if not request.user.is_anonymous():
......@@ -48,7 +48,8 @@ def create_object(request, app_label, module_name, template_name=None,
raise ImproperlyConfigured("No URL to redirect to from generic create view.")
else:
# No POST, so we want a brand new form without any data or errors
errors = new_data = {}
errors = {}
new_data = manipulator.flatten_data()
# Create the FormWrapper, template, context, response
form = formfields.FormWrapper(manipulator, new_data, errors)
......@@ -68,7 +69,7 @@ def create_object(request, app_label, module_name, template_name=None,
def update_object(request, app_label, module_name, object_id=None, slug=None,
slug_field=None, template_name=None, template_loader=template_loader,
extra_lookup_kwargs={}, extra_context={}, post_save_redirect=None,
login_required=False):
login_required=False, follow=None):
"""
Generic object-update function.
......@@ -98,13 +99,13 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
except ObjectDoesNotExist:
raise Http404("%s.%s does not exist for %s" % (app_label, module_name, lookup_kwargs))
manipulator = mod.ChangeManipulator(object.id)
manipulator = mod.ChangeManipulator(object.id, follow=follow)
if request.POST:
new_data = request.POST.copy()
errors = manipulator.get_validation_errors(new_data)
manipulator.do_html2python(new_data)
if not errors:
manipulator.do_html2python(new_data)
manipulator.save(new_data)
if not request.user.is_anonymous():
......@@ -120,7 +121,7 @@ def update_object(request, app_label, module_name, object_id=None, slug=None,
else:
errors = {}
# This makes sure the form acurate represents the fields of the place.
new_data = object.__dict__
new_data = manipulator.flatten_data()
form = formfields.FormWrapper(manipulator, new_data, errors)
if not template_name:
......
......@@ -36,6 +36,7 @@ setup(
'django.contrib.admin': ['templates/admin/*.html',
'templates/admin_doc/*.html',
'templates/registration/*.html',
'templates/widget/*.html',
'media/css/*.css',
'media/img/admin/*.gif',
'media/img/admin/*.png',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment