Skip to content

Commit

Permalink
Merge remote-tracking branch 'core/master' into schema-alteration
Browse files Browse the repository at this point in the history
Conflicts:
	django/db/backends/__init__.py
	django/db/models/fields/related.py
	tests/field_deconstruction/tests.py
  • Loading branch information
andrewgodwin committed Jun 28, 2013
2 parents e2d7e83 + 48dd1e6 commit 7a47ba6
Show file tree
Hide file tree
Showing 130 changed files with 1,166 additions and 419 deletions.
7 changes: 6 additions & 1 deletion AUTHORS
Expand Up @@ -97,6 +97,7 @@ answer newbie questions, and generally made Django that much better:
Ned Batchelder <http://www.nedbatchelder.com/>
batiste@dosimple.ch
Batman
Oliver Beattie <oliver@obeattie.com>
Brian Beck <http://blog.brianbeck.com/>
Shannon -jj Behrens <http://jjinux.blogspot.com/>
Esdras Beleza <linux@esdrasbeleza.com>
Expand Down Expand Up @@ -151,6 +152,7 @@ answer newbie questions, and generally made Django that much better:
Antonis Christofides <anthony@itia.ntua.gr>
Michal Chruszcz <troll@pld-linux.org>
Can Burak Çilingir <canburak@cs.bilgi.edu.tr>
Andrew Clark <amclark7@gmail.com>
Ian Clelland <clelland@gmail.com>
Travis Cline <travis.cline@gmail.com>
Russell Cloran <russell@rucus.net>
Expand Down Expand Up @@ -248,6 +250,7 @@ answer newbie questions, and generally made Django that much better:
martin.glueck@gmail.com
Ben Godfrey <http://aftnn.org>
GomoX <gomo@datafull.com>
Gil Gonçalves <lursty@gmail.com>
Guilherme Mesquita Gondim <semente@taurinus.org>
Mario Gonzalez <gonzalemario@gmail.com>
David Gouldin <dgouldin@gmail.com>
Expand All @@ -271,6 +274,7 @@ answer newbie questions, and generally made Django that much better:
Brian Harring <ferringb@gmail.com>
Brant Harris
Ronny Haryanto <http://ronny.haryan.to/>
Axel Haustant <noirbizarre@gmail.com>
Hawkeye
Kent Hauser <kent@khauser.net>
Joe Heck <http://www.rhonabwy.com/wp/>
Expand Down Expand Up @@ -486,7 +490,7 @@ answer newbie questions, and generally made Django that much better:
Brian Ray <http://brianray.chipy.org/>
Lee Reilly <lee@leereilly.net>
Łukasz Rekucki <lrekucki@gmail.com>
remco@diji.biz
Remco Wendt <remco.wendt@gmail.com>
Marc Remolt <m.remolt@webmasters.de>
Bruno Renié <buburno@gmail.com>
David Reynolds <david@reynoldsfamily.org.uk>
Expand Down Expand Up @@ -608,6 +612,7 @@ answer newbie questions, and generally made Django that much better:
Filip Wasilewski <filip.wasilewski@gmail.com>
Dan Watson <http://danwatson.net/>
Joel Watts <joel@joelwatts.com>
Russ Webber
Lakin Wecker <lakin@structuredabstraction.com>
Chris Wesseling <Chris.Wesseling@cwi.nl>
Benjamin Wohlwend <piquadrat@gmail.com>
Expand Down
2 changes: 1 addition & 1 deletion django/__init__.py
@@ -1,4 +1,4 @@
VERSION = (1, 6, 0, 'alpha', 1)
VERSION = (1, 7, 0, 'alpha', 0)

def get_version(*args, **kwargs):
# Don't litter django/__init__.py with all the get_version stuff.
Expand Down
2 changes: 1 addition & 1 deletion django/contrib/admin/actions.py
Expand Up @@ -19,7 +19,7 @@ def delete_selected(modeladmin, request, queryset):
deleteable objects, or, if the user has no permission one of the related
childs (foreignkeys), a "permission denied" message.
Next, it delets all selected objects and redirects back to the change list.
Next, it deletes all selected objects and redirects back to the change list.
"""
opts = modeladmin.model._meta
app_label = opts.app_label
Expand Down
123 changes: 67 additions & 56 deletions django/contrib/admin/options.py
Expand Up @@ -4,18 +4,15 @@

from django import forms
from django.conf import settings
from django.forms.formsets import all_valid, DELETION_FIELD_NAME
from django.forms.models import (modelform_factory, modelformset_factory,
inlineformset_factory, BaseInlineFormSet, modelform_defines_fields)
from django.contrib.contenttypes.models import ContentType
from django.contrib import messages
from django.contrib.admin import widgets, helpers
from django.contrib.admin.util import (unquote, flatten_fieldsets, get_deleted_objects,
model_format_dict, NestedObjects, lookup_needs_distinct)
from django.contrib.admin import validation
from django.contrib.admin.templatetags.admin_static import static
from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
from django.contrib import messages
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth import get_permission_codename
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied, ValidationError, FieldError
from django.core.paginator import Paginator
from django.core.urlresolvers import reverse
Expand All @@ -24,7 +21,10 @@
from django.db.models.related import RelatedObject
from django.db.models.fields import BLANK_CHOICE_DASH, FieldDoesNotExist
from django.db.models.sql.constants import QUERY_TERMS
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.forms.formsets import all_valid, DELETION_FIELD_NAME
from django.forms.models import (modelform_factory, modelformset_factory,
inlineformset_factory, BaseInlineFormSet, modelform_defines_fields)
from django.http import Http404, HttpResponseRedirect
from django.http.response import HttpResponseBase
from django.shortcuts import get_object_or_404
from django.template.response import SimpleTemplateResponse, TemplateResponse
Expand All @@ -39,6 +39,10 @@
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
from django.utils.encoding import force_text
from django.views.decorators.csrf import csrf_protect


IS_POPUP_VAR = '_popup'

HORIZONTAL, VERTICAL = 1, 2
# returns the <ul> class for a given radio_admin field
Expand All @@ -56,15 +60,15 @@ class IncorrectLookupParameters(Exception):
'form_class': forms.SplitDateTimeField,
'widget': widgets.AdminSplitDateTime
},
models.DateField: {'widget': widgets.AdminDateWidget},
models.TimeField: {'widget': widgets.AdminTimeWidget},
models.TextField: {'widget': widgets.AdminTextareaWidget},
models.URLField: {'widget': widgets.AdminURLFieldWidget},
models.IntegerField: {'widget': widgets.AdminIntegerFieldWidget},
models.DateField: {'widget': widgets.AdminDateWidget},
models.TimeField: {'widget': widgets.AdminTimeWidget},
models.TextField: {'widget': widgets.AdminTextareaWidget},
models.URLField: {'widget': widgets.AdminURLFieldWidget},
models.IntegerField: {'widget': widgets.AdminIntegerFieldWidget},
models.BigIntegerField: {'widget': widgets.AdminBigIntegerFieldWidget},
models.CharField: {'widget': widgets.AdminTextInputWidget},
models.ImageField: {'widget': widgets.AdminFileWidget},
models.FileField: {'widget': widgets.AdminFileWidget},
models.CharField: {'widget': widgets.AdminTextInputWidget},
models.ImageField: {'widget': widgets.AdminFileWidget},
models.FileField: {'widget': widgets.AdminFileWidget},
}

csrf_protect_m = method_decorator(csrf_protect)
Expand Down Expand Up @@ -350,7 +354,8 @@ def has_add_permission(self, request):
Can be overridden by the user in subclasses.
"""
opts = self.opts
return request.user.has_perm(opts.app_label + '.' + opts.get_add_permission())
codename = get_permission_codename('add', opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))

def has_change_permission(self, request, obj=None):
"""
Expand All @@ -364,7 +369,8 @@ def has_change_permission(self, request, obj=None):
request has permission to change *any* object of the given type.
"""
opts = self.opts
return request.user.has_perm(opts.app_label + '.' + opts.get_change_permission())
codename = get_permission_codename('change', opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))

def has_delete_permission(self, request, obj=None):
"""
Expand All @@ -378,7 +384,9 @@ def has_delete_permission(self, request, obj=None):
request has permission to delete *any* object of the given type.
"""
opts = self.opts
return request.user.has_perm(opts.app_label + '.' + opts.get_delete_permission())
codename = get_permission_codename('delete', opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))


class ModelAdmin(BaseModelAdmin):
"Encapsulates all admin options and functionality for a given model."
Expand Down Expand Up @@ -606,11 +614,11 @@ def log_addition(self, request, object):
"""
from django.contrib.admin.models import LogEntry, ADDITION
LogEntry.objects.log_action(
user_id = request.user.pk,
content_type_id = ContentType.objects.get_for_model(object).pk,
object_id = object.pk,
object_repr = force_text(object),
action_flag = ADDITION
user_id=request.user.pk,
content_type_id=ContentType.objects.get_for_model(object).pk,
object_id=object.pk,
object_repr=force_text(object),
action_flag=ADDITION
)

def log_change(self, request, object, message):
Expand All @@ -621,12 +629,12 @@ def log_change(self, request, object, message):
"""
from django.contrib.admin.models import LogEntry, CHANGE
LogEntry.objects.log_action(
user_id = request.user.pk,
content_type_id = ContentType.objects.get_for_model(object).pk,
object_id = object.pk,
object_repr = force_text(object),
action_flag = CHANGE,
change_message = message
user_id=request.user.pk,
content_type_id=ContentType.objects.get_for_model(object).pk,
object_id=object.pk,
object_repr=force_text(object),
action_flag=CHANGE,
change_message=message
)

def log_deletion(self, request, object, object_repr):
Expand All @@ -638,11 +646,11 @@ def log_deletion(self, request, object, object_repr):
"""
from django.contrib.admin.models import LogEntry, DELETION
LogEntry.objects.log_action(
user_id = request.user.pk,
content_type_id = ContentType.objects.get_for_model(self.model).pk,
object_id = object.pk,
object_repr = object_repr,
action_flag = DELETION
user_id=request.user.pk,
content_type_id=ContentType.objects.get_for_model(self.model).pk,
object_id=object.pk,
object_repr=object_repr,
action_flag=DELETION
)

def action_checkbox(self, obj):
Expand All @@ -660,8 +668,8 @@ def get_actions(self, request):
"""
# If self.actions is explicitly set to None that means that we don't
# want *any* actions enabled on this page.
from django.contrib.admin.views.main import IS_POPUP_VAR
if self.actions is None or IS_POPUP_VAR in request.GET:
from django.contrib.admin.views.main import _is_changelist_popup
if self.actions is None or _is_changelist_popup(request):
return SortedDict()

actions = []
Expand Down Expand Up @@ -878,7 +886,7 @@ def render_change_form(self, request, context, add=False, change=False, form_url
'has_add_permission': self.has_add_permission(request),
'has_change_permission': self.has_change_permission(request, obj),
'has_delete_permission': self.has_delete_permission(request, obj),
'has_file_field': True, # FIXME - this should check if form or formsets have a FileField,
'has_file_field': True, # FIXME - this should check if form or formsets have a FileField,
'has_absolute_url': hasattr(self.model, 'get_absolute_url'),
'form_url': form_url,
'opts': opts,
Expand Down Expand Up @@ -908,12 +916,11 @@ def response_add(self, request, obj, post_url_continue=None):
msg_dict = {'name': force_text(opts.verbose_name), 'obj': force_text(obj)}
# Here, we distinguish between different save types by checking for
# the presence of keys in request.POST.
if "_popup" in request.POST:
return HttpResponse(
'<!DOCTYPE html><html><head><title></title></head><body>'
'<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script></body></html>' % \
# escape() calls force_text.
(escape(pk_value), escapejs(obj)))
if IS_POPUP_VAR in request.POST:
return SimpleTemplateResponse('admin/popup_response.html', {
'pk_value': escape(pk_value),
'obj': escapejs(obj)
})

elif "_continue" in request.POST:
msg = _('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % msg_dict
Expand Down Expand Up @@ -1049,7 +1056,7 @@ def response_action(self, request, queryset):
if action_form.is_valid():
action = action_form.cleaned_data['action']
select_across = action_form.cleaned_data['select_across']
func, name, description = self.get_actions(request)[action]
func = self.get_actions(request)[action][0]

# Get the list of selected PKs. If nothing's selected, we can't
# perform an action on it, so bail. Except we want to perform
Expand Down Expand Up @@ -1158,7 +1165,7 @@ def add_view(self, request, form_url='', extra_context=None):
context = {
'title': _('Add %s') % force_text(opts.verbose_name),
'adminform': adminForm,
'is_popup': "_popup" in request.REQUEST,
'is_popup': IS_POPUP_VAR in request.REQUEST,
'media': media,
'inline_admin_formsets': inline_admin_formsets,
'errors': helpers.AdminErrorList(form, formsets),
Expand Down Expand Up @@ -1251,7 +1258,7 @@ def change_view(self, request, object_id, form_url='', extra_context=None):
'adminform': adminForm,
'object_id': object_id,
'original': obj,
'is_popup': "_popup" in request.REQUEST,
'is_popup': IS_POPUP_VAR in request.REQUEST,
'media': media,
'inline_admin_formsets': inline_admin_formsets,
'errors': helpers.AdminErrorList(form, formsets),
Expand Down Expand Up @@ -1280,7 +1287,7 @@ def changelist_view(self, request, extra_context=None):
actions = self.get_actions(request)
if actions:
# Add the action checkboxes if there are any actions available.
list_display = ['action_checkbox'] + list(list_display)
list_display = ['action_checkbox'] + list(list_display)

ChangeList = self.get_changelist(request)
try:
Expand Down Expand Up @@ -1429,7 +1436,10 @@ def delete_view(self, request, object_id, extra_context=None):
raise PermissionDenied

if obj is None:
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') % {'name': force_text(opts.verbose_name), 'key': escape(object_id)})
raise Http404(
_('%(name)s object with primary key %(key)r does not exist.') %
{'name': force_text(opts.verbose_name), 'key': escape(object_id)}
)

using = router.db_for_write(self.model)

Expand All @@ -1438,7 +1448,7 @@ def delete_view(self, request, object_id, extra_context=None):
(deleted_objects, perms_needed, protected) = get_deleted_objects(
[obj], opts, request.user, self.admin_site, using)

if request.POST: # The user has already confirmed the deletion.
if request.POST: # The user has already confirmed the deletion.
if perms_needed:
raise PermissionDenied
obj_display = force_text(obj)
Expand All @@ -1456,7 +1466,9 @@ def delete_view(self, request, object_id, extra_context=None):
(opts.app_label, opts.model_name),
current_app=self.admin_site.name)
preserved_filters = self.get_preserved_filters(request)
post_url = add_preserved_filters({'preserved_filters': preserved_filters, 'opts': opts}, post_url)
post_url = add_preserved_filters(
{'preserved_filters': preserved_filters, 'opts': opts}, post_url
)
else:
post_url = reverse('admin:index',
current_app=self.admin_site.name)
Expand Down Expand Up @@ -1522,6 +1534,7 @@ def history_view(self, request, object_id, extra_context=None):
"admin/object_history.html"
], context, current_app=self.admin_site.name)


class InlineModelAdmin(BaseModelAdmin):
"""
Options for inline editing of ``model`` instances.
Expand Down Expand Up @@ -1665,8 +1678,7 @@ def has_add_permission(self, request):
# to have the change permission for the related model in order to
# be able to do anything with the intermediate model.
return self.has_change_permission(request)
return request.user.has_perm(
self.opts.app_label + '.' + self.opts.get_add_permission())
return super(InlineModelAdmin, self).has_add_permission(request)

def has_change_permission(self, request, obj=None):
opts = self.opts
Expand All @@ -1677,8 +1689,8 @@ def has_change_permission(self, request, obj=None):
if field.rel and field.rel.to != self.parent_model:
opts = field.rel.to._meta
break
return request.user.has_perm(
opts.app_label + '.' + opts.get_change_permission())
codename = get_permission_codename('change', opts)
return request.user.has_perm("%s.%s" % (opts.app_label, codename))

def has_delete_permission(self, request, obj=None):
if self.opts.auto_created:
Expand All @@ -1687,8 +1699,7 @@ def has_delete_permission(self, request, obj=None):
# to have the change permission for the related model in order to
# be able to do anything with the intermediate model.
return self.has_change_permission(request, obj)
return request.user.has_perm(
self.opts.app_label + '.' + self.opts.get_delete_permission())
return super(InlineModelAdmin, self).has_delete_permission(request, obj)


class StackedInline(InlineModelAdmin):
Expand Down
Expand Up @@ -32,9 +32,9 @@ function showRelatedObjectLookupPopup(triggeringLink) {
name = id_to_windowname(name);
var href;
if (triggeringLink.href.search(/\?/) >= 0) {
href = triggeringLink.href + '&pop=1';
href = triggeringLink.href + '&_popup=1';
} else {
href = triggeringLink.href + '?pop=1';
href = triggeringLink.href + '?_popup=1';
}
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
Expand Down
9 changes: 9 additions & 0 deletions django/contrib/admin/templates/admin/popup_response.html
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head><title></title></head>
<body>
<script type="text/javascript">
opener.dismissAddAnotherPopup(window, "{{ pk_value }}", "{{ obj }}");
</script>
</body>
</html>
2 changes: 1 addition & 1 deletion django/contrib/admin/templates/admin/search_form.html
Expand Up @@ -6,7 +6,7 @@
<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" />
<input type="submit" value="{% trans 'Search' %}" />
{% if show_result_count %}
<span class="small quiet">{% blocktrans count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}pop=1{% endif %}">{% blocktrans with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span>
<span class="small quiet">{% blocktrans count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}_popup=1{% endif %}">{% blocktrans with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span>
{% endif %}
{% for pair in cl.params.items %}
{% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0 }}" value="{{ pair.1 }}"/>{% endifnotequal %}
Expand Down

0 comments on commit 7a47ba6

Please sign in to comment.