From a51eb82f6b68ec7620f6e4ab432fda058bbd953e Mon Sep 17 00:00:00 2001 From: Koding Date: Sat, 21 Mar 2015 15:44:11 +0000 Subject: [PATCH] Fix some Django 1.8 compatibility issues. --- djadmin2/permissions.py | 10 ++++++++-- djadmin2/types.py | 2 +- djadmin2/utils.py | 25 +++++++++++++++++-------- djadmin2/viewmixins.py | 2 +- djadmin2/views.py | 7 ++++--- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/djadmin2/permissions.py b/djadmin2/permissions.py index 849d465..08acbd2 100644 --- a/djadmin2/permissions.py +++ b/djadmin2/permissions.py @@ -82,10 +82,16 @@ def model_permission(permission): assert model_class, ( 'Cannot apply model permissions on a view that does not ' 'have a `.model` or `.queryset` property.') - + + try: + # django 1.8+ + model_name = model_class._meta.model_name + except AttributeError: + model_name = model_class._meta.module_name + permission_name = permission.format( app_label=model_class._meta.app_label, - model_name=model_class._meta.module_name) + model_name=model_name) return request.user.has_perm(permission_name, obj) return has_permission diff --git a/djadmin2/types.py b/djadmin2/types.py index 79a18d7..5c6f8ec 100644 --- a/djadmin2/types.py +++ b/djadmin2/types.py @@ -188,7 +188,7 @@ class ModelAdmin2(with_metaclass(ModelAdminBase2)): form_class = (self.update_form_class if self.update_form_class else self.form_class) if form_class is None: - form_class = modelform_factory(self.model) + form_class = modelform_factory(self.model, fields='__all__') kwargs.update({ 'inlines': self.inlines, 'form_class': form_class, diff --git a/djadmin2/utils.py b/djadmin2/utils.py index 9321270..df7a91e 100644 --- a/djadmin2/utils.py +++ b/djadmin2/utils.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- from __future__ import division, absolute_import, unicode_literals +from collections import defaultdict + from django.db.models import ProtectedError from django.db.models import ManyToManyRel from django.db.models.deletion import Collector -from django.db.models.related import RelatedObject +from django.db.models.fields.related import ForeignObjectRel from django.utils import six from django.utils.encoding import force_bytes, force_text @@ -20,7 +22,7 @@ def lookup_needs_distinct(opts, lookup_path): field_name = lookup_path.split('__', 1)[0] field = opts.get_field_by_name(field_name)[0] condition1 = hasattr(field, 'rel') and isinstance(field.rel, ManyToManyRel) - condition2 = isinstance(field, RelatedObject) and not field.field.unique + condition2 = isinstance(field, ForeignObjectRel) and not field.field.unique return condition1 or condition2 @@ -104,25 +106,32 @@ class NestedObjects(Collector): This is adopted from the Django core. django-admin2 mandates that code doesn't depend on imports from django.contrib.admin. - https://github.com/django/django/blob/1.5.1/django/contrib/admin/util.py#L144-L199 + https://github.com/django/django/blob/1.8c1/django/contrib/admin/utils.py#L160-L221 """ + + def __init__(self, *args, **kwargs): super(NestedObjects, self).__init__(*args, **kwargs) self.edges = {} # {from_instance: [to_instances]} self.protected = set() + self.model_count = defaultdict(int) def add_edge(self, source, target): self.edges.setdefault(source, []).append(target) - def collect(self, objs, source_attr=None, **kwargs): + def collect(self, objs, source=None, source_attr=None, **kwargs): for obj in objs: - if source_attr: - self.add_edge(getattr(obj, source_attr), obj) + if source_attr and not source_attr.endswith('+'): + related_name = source_attr % { + 'class': source._meta.model_name, + 'app_label': source._meta.app_label, + } + self.add_edge(getattr(obj, related_name), obj) else: self.add_edge(None, obj) + self.model_count[obj._meta.verbose_name_plural] += 1 try: - return super(NestedObjects, self).collect( - objs, source_attr=source_attr, **kwargs) + return super(NestedObjects, self).collect(objs, source_attr=source_attr, **kwargs) except ProtectedError as e: self.protected.update(e.protected_objects) diff --git a/djadmin2/viewmixins.py b/djadmin2/viewmixins.py index f3dc8c4..09ef357 100644 --- a/djadmin2/viewmixins.py +++ b/djadmin2/viewmixins.py @@ -141,7 +141,7 @@ class AdminModel2Mixin(Admin2Mixin): def get_form_class(self): if self.form_class is not None: return self.form_class - return modelform_factory(self.get_model()) + return modelform_factory(self.get_model(), fields='__all__') class Admin2ModelFormMixin(object): diff --git a/djadmin2/views.py b/djadmin2/views.py index 76b2d41..9a27989 100644 --- a/djadmin2/views.py +++ b/djadmin2/views.py @@ -13,7 +13,7 @@ from django.contrib.auth.views import (logout as auth_logout, login as auth_login) from django.contrib.contenttypes.models import ContentType from django.core.urlresolvers import reverse, reverse_lazy -from django.db import models +from django.db import models, router from django.db.models.fields import FieldDoesNotExist from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 @@ -461,8 +461,9 @@ class ModelDeleteView(AdminModel2Mixin, generic.DeleteView): opts = utils.model_options(obj) return '%s: %s' % (force_text(capfirst(opts.verbose_name)), force_text(obj)) - - collector = utils.NestedObjects(using=None) + + using = router.db_for_write(self.get_object()._meta.model) + collector = utils.NestedObjects(using=using) collector.collect([self.get_object()]) context.update({ 'deletable_objects': collector.nested(_format_callback)