Commit 8f305563 authored by Anssi Kääriäinen's avatar Anssi Kääriäinen Committed by Tim Graham
Browse files

Renamed Field.rel attribute to remote_field

Field.rel is now deprecated. Rel objects have now also remote_field
attribute. This means that self == self.remote_field.remote_field.

In addition, made the Rel objects a bit more like Field objects. Still,
marked ManyToManyFields as null=True.
parent f9c70bb3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -180,7 +180,7 @@ class BaseModelAdminChecks(object):
                return []
            else:
                if (isinstance(field, models.ManyToManyField) and
                        not field.rel.through._meta.auto_created):
                        not field.remote_field.through._meta.auto_created):
                    return [
                        checks.Error(
                            ("The value of '%s' cannot include the ManyToManyField '%s', "
+5 −24
Original line number Diff line number Diff line
@@ -9,12 +9,10 @@ import datetime

from django.contrib.admin.options import IncorrectLookupParameters
from django.contrib.admin.utils import (
    get_limit_choices_to_from_path, get_model_from_relation,
    prepare_lookup_value, reverse_field_path,
    get_model_from_relation, prepare_lookup_value, reverse_field_path,
)
from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.db import models
from django.db.models.fields.related import ForeignObjectRel, ManyToManyField
from django.utils import timezone
from django.utils.encoding import force_text, smart_text
from django.utils.translation import ugettext_lazy as _
@@ -164,11 +162,7 @@ class FieldListFilter(ListFilter):
class RelatedFieldListFilter(FieldListFilter):
    def __init__(self, field, request, params, model, model_admin, field_path):
        other_model = get_model_from_relation(field)
        if hasattr(field, 'rel'):
            rel_name = field.rel.get_related_field().name
        else:
            rel_name = other_model._meta.pk.name
        self.lookup_kwarg = '%s__%s__exact' % (field_path, rel_name)
        self.lookup_kwarg = '%s__%s__exact' % (field_path, field.target_field.name)
        self.lookup_kwarg_isnull = '%s__isnull' % field_path
        self.lookup_val = request.GET.get(self.lookup_kwarg)
        self.lookup_val_isnull = request.GET.get(self.lookup_kwarg_isnull)
@@ -182,9 +176,7 @@ class RelatedFieldListFilter(FieldListFilter):
        self.title = self.lookup_title

    def has_output(self):
        if (isinstance(self.field, ForeignObjectRel) and
                self.field.field.null or hasattr(self.field, 'rel') and
                self.field.null):
        if self.field.null:
            extra = 1
        else:
            extra = 0
@@ -212,9 +204,7 @@ class RelatedFieldListFilter(FieldListFilter):
                }, [self.lookup_kwarg_isnull]),
                'display': val,
            }
        if (isinstance(self.field, ForeignObjectRel) and
                (self.field.field.null or isinstance(self.field.field, ManyToManyField)) or
                hasattr(self.field, 'rel') and (self.field.null or isinstance(self.field, ManyToManyField))):
        if self.field.null:
            yield {
                'selected': bool(self.lookup_val_isnull),
                'query_string': cl.get_query_string({
@@ -223,9 +213,7 @@ class RelatedFieldListFilter(FieldListFilter):
                'display': EMPTY_CHANGELIST_VALUE,
            }

FieldListFilter.register(lambda f: (
    bool(f.rel) if hasattr(f, 'rel') else
    isinstance(f, ForeignObjectRel)), RelatedFieldListFilter)
FieldListFilter.register(lambda f: f.remote_field, RelatedFieldListFilter)


class BooleanFieldListFilter(FieldListFilter):
@@ -371,13 +359,6 @@ class AllValuesFieldListFilter(FieldListFilter):
            queryset = model_admin.get_queryset(request)
        else:
            queryset = parent_model._default_manager.all()

        # optional feature: limit choices base on existing relationships
        # queryset = queryset.complex_filter(
        #    {'%s__isnull' % reverse_path: False})
        limit_choices_to = get_limit_choices_to_from_path(model, field_path)
        queryset = queryset.filter(limit_choices_to)

        self.lookup_choices = (queryset
                               .distinct()
                               .order_by(field.name)
+1 −1
Original line number Diff line number Diff line
@@ -203,7 +203,7 @@ class AdminReadonlyField(object):
                    else:
                        result_repr = linebreaksbr(result_repr)
            else:
                if isinstance(f.rel, ManyToManyRel) and value is not None:
                if isinstance(f.remote_field, ManyToManyRel) and value is not None:
                    result_repr = ", ".join(map(six.text_type, value.all()))
                else:
                    result_repr = display_for_field(value, f)
+30 −46
Original line number Diff line number Diff line
@@ -26,8 +26,6 @@ from django.core.urlresolvers import reverse
from django.db import models, router, transaction
from django.db.models.constants import LOOKUP_SEP
from django.db.models.fields import BLANK_CHOICE_DASH
from django.db.models.fields.related import ForeignObjectRel
from django.db.models.sql.constants import QUERY_TERMS
from django.forms.formsets import DELETION_FIELD_NAME, all_valid
from django.forms.models import (
    BaseInlineFormSet, inlineformset_factory, modelform_defines_fields,
@@ -154,7 +152,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
            # rendered output. formfield can be None if it came from a
            # OneToOneField with parent_link=True or a M2M intermediary.
            if formfield and db_field.name not in self.raw_id_fields:
                related_modeladmin = self.admin_site._registry.get(db_field.rel.to)
                related_modeladmin = self.admin_site._registry.get(db_field.remote_field.model)
                wrapper_kwargs = {}
                if related_modeladmin:
                    wrapper_kwargs.update(
@@ -163,7 +161,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
                        can_delete_related=related_modeladmin.has_delete_permission(request),
                    )
                formfield.widget = widgets.RelatedFieldWidgetWrapper(
                    formfield.widget, db_field.rel, self.admin_site, **wrapper_kwargs
                    formfield.widget, db_field.remote_field, self.admin_site, **wrapper_kwargs
                )

            return formfield
@@ -202,11 +200,11 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
        ordering.  Otherwise don't specify the queryset, let the field decide
        (returns None in that case).
        """
        related_admin = self.admin_site._registry.get(db_field.rel.to, None)
        related_admin = self.admin_site._registry.get(db_field.remote_field.model, None)
        if related_admin is not None:
            ordering = related_admin.get_ordering(request)
            if ordering is not None and ordering != ():
                return db_field.rel.to._default_manager.using(db).order_by(*ordering)
                return db_field.remote_field.model._default_manager.using(db).order_by(*ordering)
        return None

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
@@ -215,7 +213,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
        """
        db = kwargs.get('using')
        if db_field.name in self.raw_id_fields:
            kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel,
            kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.remote_field,
                                    self.admin_site, using=db)
        elif db_field.name in self.radio_fields:
            kwargs['widget'] = widgets.AdminRadioSelect(attrs={
@@ -236,12 +234,12 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
        """
        # If it uses an intermediary model that isn't auto created, don't show
        # a field in admin.
        if not db_field.rel.through._meta.auto_created:
        if not db_field.remote_field.through._meta.auto_created:
            return None
        db = kwargs.get('using')

        if db_field.name in self.raw_id_fields:
            kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel,
            kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.remote_field,
                                    self.admin_site, using=db)
            kwargs['help_text'] = ''
        elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
@@ -334,46 +332,32 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
                if k == lookup and v == value:
                    return True

        parts = lookup.split(LOOKUP_SEP)

        # Last term in lookup is a query term (__exact, __startswith etc)
        # This term can be ignored.
        if len(parts) > 1 and parts[-1] in QUERY_TERMS:
            parts.pop()

        # Special case -- foo__id__exact and foo__id queries are implied
        # if foo has been specifically included in the lookup list; so
        # drop __id if it is the last part. However, first we need to find
        # the pk attribute name.
        rel_name = None
        for part in parts[:-1]:
        relation_parts = []
        prev_field = None
        for part in lookup.split(LOOKUP_SEP):
            try:
                field = model._meta.get_field(part)
            except FieldDoesNotExist:
                # Lookups on non-existent fields are ok, since they're ignored
                # later.
                return True
            if hasattr(field, 'rel'):
                if field.rel is None:
                    # This property or relation doesn't exist, but it's allowed
                    # since it's ignored in ChangeList.get_filters().
                    return True
                model = field.rel.to
                if hasattr(field.rel, 'get_related_field'):
                    rel_name = field.rel.get_related_field().name
                else:
                    rel_name = None
            elif isinstance(field, ForeignObjectRel):
                model = field.related_model
                rel_name = model._meta.pk.name
            else:
                rel_name = None
        if rel_name and len(parts) > 1 and parts[-1] == rel_name:
            parts.pop()
                break
            # It is allowed to filter on values that would be found from local
            # model anyways. For example, if you filter on employee__department__id,
            # then the id value would be found already from employee__department_id.
            if not prev_field or (prev_field.concrete and
                                  field not in prev_field.get_path_info()[-1].target_fields):
                relation_parts.append(part)
            if not getattr(field, 'get_path_info', None):
                # This is not a relational field, so further parts
                # must be transforms.
                break
            prev_field = field
            model = field.get_path_info()[-1].to_opts.model

        if len(parts) == 1:
        if len(relation_parts) <= 1:
            # Either a local field filter, or no fields at all.
            return True
        clean_lookup = LOOKUP_SEP.join(parts)
        clean_lookup = LOOKUP_SEP.join(relation_parts)
        valid_lookups = [self.date_hierarchy]
        for filter_item in self.list_filter:
            if isinstance(filter_item, type) and issubclass(filter_item, SimpleListFilter):
@@ -422,7 +406,7 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
        for related_object in related_objects:
            related_model = related_object.related_model
            if (any(issubclass(model, related_model) for model in registered_models) and
                    related_object.field.rel.get_related_field() == field):
                    related_object.field.remote_field.get_related_field() == field):
                return True

        return False
@@ -1882,8 +1866,8 @@ class InlineModelAdmin(BaseModelAdmin):
            # The model was auto-created as intermediary for a
            # ManyToMany-relationship, find the target model
            for field in opts.fields:
                if field.rel and field.rel.to != self.parent_model:
                    opts = field.rel.to._meta
                if field.remote_field and field.remote_field.model != self.parent_model:
                    opts = field.remote_field.model._meta
                    break
        codename = get_permission_codename('change', opts)
        return request.user.has_perm("%s.%s" % (opts.app_label, codename))
+1 −1
Original line number Diff line number Diff line
@@ -215,7 +215,7 @@ def items_for_result(cl, result, form):
                if isinstance(value, (datetime.date, datetime.time)):
                    row_classes.append('nowrap')
            else:
                if isinstance(f.rel, models.ManyToOneRel):
                if isinstance(f.remote_field, models.ManyToOneRel):
                    field_val = getattr(result, f.name)
                    if field_val is None:
                        result_repr = EMPTY_CHANGELIST_VALUE
Loading