Fixed #27356 -- Fixed ModelAdmin.lookup_allowed() for some nested relations.
This commit is contained in:
parent
27793431cf
commit
b27166b769
|
@ -371,16 +371,20 @@ class BaseModelAdmin(metaclass=forms.MediaDefiningClass):
|
||||||
if len(relation_parts) <= 1:
|
if len(relation_parts) <= 1:
|
||||||
# Either a local field filter, or no fields at all.
|
# Either a local field filter, or no fields at all.
|
||||||
return True
|
return True
|
||||||
clean_lookup = LOOKUP_SEP.join(relation_parts)
|
valid_lookups = {self.date_hierarchy}
|
||||||
valid_lookups = [self.date_hierarchy]
|
|
||||||
for filter_item in self.list_filter:
|
for filter_item in self.list_filter:
|
||||||
if isinstance(filter_item, type) and issubclass(filter_item, SimpleListFilter):
|
if isinstance(filter_item, type) and issubclass(filter_item, SimpleListFilter):
|
||||||
valid_lookups.append(filter_item.parameter_name)
|
valid_lookups.add(filter_item.parameter_name)
|
||||||
elif isinstance(filter_item, (list, tuple)):
|
elif isinstance(filter_item, (list, tuple)):
|
||||||
valid_lookups.append(filter_item[0])
|
valid_lookups.add(filter_item[0])
|
||||||
else:
|
else:
|
||||||
valid_lookups.append(filter_item)
|
valid_lookups.add(filter_item)
|
||||||
return clean_lookup in valid_lookups
|
|
||||||
|
# Is it a valid relational lookup?
|
||||||
|
return not {
|
||||||
|
LOOKUP_SEP.join(relation_parts),
|
||||||
|
LOOKUP_SEP.join(relation_parts + [part])
|
||||||
|
}.isdisjoint(valid_lookups)
|
||||||
|
|
||||||
def to_field_allowed(self, request, to_field):
|
def to_field_allowed(self, request, to_field):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -8,8 +8,10 @@ from django.contrib.admin.options import (
|
||||||
from django.contrib.admin.sites import AdminSite
|
from django.contrib.admin.sites import AdminSite
|
||||||
from django.contrib.admin.widgets import AdminDateWidget, AdminRadioSelect
|
from django.contrib.admin.widgets import AdminDateWidget, AdminRadioSelect
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.db import models
|
||||||
from django.forms.widgets import Select
|
from django.forms.widgets import Select
|
||||||
from django.test import SimpleTestCase, TestCase
|
from django.test import SimpleTestCase, TestCase
|
||||||
|
from django.test.utils import isolate_apps
|
||||||
|
|
||||||
from .models import Band, Concert
|
from .models import Band, Concert
|
||||||
|
|
||||||
|
@ -90,6 +92,33 @@ class ModelAdminTests(TestCase):
|
||||||
ma = BandAdmin(Band, self.site)
|
ma = BandAdmin(Band, self.site)
|
||||||
self.assertTrue(ma.lookup_allowed('name__nonexistent', 'test_value'))
|
self.assertTrue(ma.lookup_allowed('name__nonexistent', 'test_value'))
|
||||||
|
|
||||||
|
@isolate_apps('modeladmin')
|
||||||
|
def test_lookup_allowed_onetoone(self):
|
||||||
|
class Department(models.Model):
|
||||||
|
code = models.CharField(max_length=4, unique=True)
|
||||||
|
|
||||||
|
class Employee(models.Model):
|
||||||
|
department = models.ForeignKey(Department, models.CASCADE, to_field="code")
|
||||||
|
|
||||||
|
class EmployeeProfile(models.Model):
|
||||||
|
employee = models.OneToOneField(Employee, models.CASCADE)
|
||||||
|
|
||||||
|
class EmployeeInfo(models.Model):
|
||||||
|
employee = models.OneToOneField(Employee, models.CASCADE)
|
||||||
|
description = models.CharField(max_length=100)
|
||||||
|
|
||||||
|
class EmployeeProfileAdmin(ModelAdmin):
|
||||||
|
list_filter = [
|
||||||
|
'employee__employeeinfo__description',
|
||||||
|
'employee__department__code',
|
||||||
|
]
|
||||||
|
|
||||||
|
ma = EmployeeProfileAdmin(EmployeeProfile, self.site)
|
||||||
|
# Reverse OneToOneField
|
||||||
|
self.assertIs(ma.lookup_allowed('employee__employeeinfo__description', 'test_value'), True)
|
||||||
|
# OneToOneField and ForeignKey
|
||||||
|
self.assertIs(ma.lookup_allowed('employee__department__code', 'test_value'), True)
|
||||||
|
|
||||||
def test_field_arguments(self):
|
def test_field_arguments(self):
|
||||||
# If fields is specified, fieldsets_add and fieldsets_change should
|
# If fields is specified, fieldsets_add and fieldsets_change should
|
||||||
# just stick the fields into a formsets structure and return it.
|
# just stick the fields into a formsets structure and return it.
|
||||||
|
|
Loading…
Reference in New Issue