mirror of
				https://github.com/django/django.git
				synced 2025-11-04 05:35:37 +00:00 
			
		
		
		
	Fixed #25622 -- Accounted for generic relations in the admin to field validation
Thanks to Jonathan Liuti for the report and Tim Graham for the review.
This commit is contained in:
		
							parent
							
								
									96fe90f535
								
							
						
					
					
						commit
						9dcfecb7c6
					
				
					 5 changed files with 40 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -413,8 +413,10 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
 | 
			
		|||
        )
 | 
			
		||||
        for related_object in related_objects:
 | 
			
		||||
            related_model = related_object.related_model
 | 
			
		||||
            remote_field = related_object.field.remote_field
 | 
			
		||||
            if (any(issubclass(model, related_model) for model in registered_models) and
 | 
			
		||||
                    related_object.field.remote_field.get_related_field() == field):
 | 
			
		||||
                    hasattr(remote_field, 'get_related_field') and
 | 
			
		||||
                    remote_field.get_related_field() == field):
 | 
			
		||||
                return True
 | 
			
		||||
 | 
			
		||||
        return False
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,3 +48,6 @@ Bugfixes
 | 
			
		|||
* Fixed a regression in ``URLValidator`` that allowed URLs with consecutive
 | 
			
		||||
  dots in the domain section (like ``http://example..com/``) to pass
 | 
			
		||||
  (:ticket:`25620`).
 | 
			
		||||
 | 
			
		||||
* Fixed a crash with ``GenericRelation`` and
 | 
			
		||||
  ``BaseModelAdmin.to_field_allowed`` (:ticket:`25622`).
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,18 +31,19 @@ from .models import (
 | 
			
		|||
    EmptyModelHidden, EmptyModelMixin, EmptyModelVisible, ExplicitlyProvidedPK,
 | 
			
		||||
    ExternalSubscriber, Fabric, FancyDoodad, FieldOverridePost,
 | 
			
		||||
    FilteredManager, FooAccount, FoodDelivery, FunkyTag, Gadget, Gallery,
 | 
			
		||||
    Grommet, ImplicitlyGeneratedPK, Ingredient, InlineReference, InlineReferer,
 | 
			
		||||
    Inquisition, Language, Link, MainPrepopulated, ModelWithStringPrimaryKey,
 | 
			
		||||
    NotReferenced, OldSubscriber, OtherStory, Paper, Parent,
 | 
			
		||||
    ParentWithDependentChildren, Person, Persona, Picture, Pizza, Plot,
 | 
			
		||||
    PlotDetails, PluggableSearchPerson, Podcast, Post, PrePopulatedPost,
 | 
			
		||||
    PrePopulatedPostLargeSlug, PrePopulatedSubPost, Promo, Question, Recipe,
 | 
			
		||||
    Recommendation, Recommender, ReferencedByInline, ReferencedByParent,
 | 
			
		||||
    RelatedPrepopulated, Report, Reservation, Restaurant,
 | 
			
		||||
    RowLevelChangePermissionModel, Section, ShortMessage, Simple, Sketch,
 | 
			
		||||
    State, Story, StumpJoke, Subscriber, SuperVillain, Telegram, Thing,
 | 
			
		||||
    Topping, UnchangeableObject, UndeletableObject, UnorderedObject,
 | 
			
		||||
    UserMessenger, Villain, Vodcast, Whatsit, Widget, Worker, WorkHour,
 | 
			
		||||
    GenRelReference, Grommet, ImplicitlyGeneratedPK, Ingredient,
 | 
			
		||||
    InlineReference, InlineReferer, Inquisition, Language, Link,
 | 
			
		||||
    MainPrepopulated, ModelWithStringPrimaryKey, NotReferenced, OldSubscriber,
 | 
			
		||||
    OtherStory, Paper, Parent, ParentWithDependentChildren, Person, Persona,
 | 
			
		||||
    Picture, Pizza, Plot, PlotDetails, PluggableSearchPerson, Podcast, Post,
 | 
			
		||||
    PrePopulatedPost, PrePopulatedPostLargeSlug, PrePopulatedSubPost, Promo,
 | 
			
		||||
    Question, Recipe, Recommendation, Recommender, ReferencedByGenRel,
 | 
			
		||||
    ReferencedByInline, ReferencedByParent, RelatedPrepopulated, Report,
 | 
			
		||||
    Reservation, Restaurant, RowLevelChangePermissionModel, Section,
 | 
			
		||||
    ShortMessage, Simple, Sketch, State, Story, StumpJoke, Subscriber,
 | 
			
		||||
    SuperVillain, Telegram, Thing, Topping, UnchangeableObject,
 | 
			
		||||
    UndeletableObject, UnorderedObject, UserMessenger, Villain, Vodcast,
 | 
			
		||||
    Whatsit, Widget, Worker, WorkHour,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -944,6 +945,8 @@ site.register(ReferencedByParent)
 | 
			
		|||
site.register(ChildOfReferer)
 | 
			
		||||
site.register(ReferencedByInline)
 | 
			
		||||
site.register(InlineReferer, InlineRefererAdmin)
 | 
			
		||||
site.register(ReferencedByGenRel)
 | 
			
		||||
site.register(GenRelReference)
 | 
			
		||||
 | 
			
		||||
# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
 | 
			
		||||
# That way we cover all four cases:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -938,3 +938,14 @@ class ExplicitlyProvidedPK(models.Model):
 | 
			
		|||
 | 
			
		||||
class ImplicitlyGeneratedPK(models.Model):
 | 
			
		||||
    name = models.IntegerField(unique=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Models for #25622
 | 
			
		||||
class ReferencedByGenRel(models.Model):
 | 
			
		||||
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
 | 
			
		||||
    object_id = models.PositiveIntegerField()
 | 
			
		||||
    content_object = GenericForeignKey('content_type', 'object_id')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GenRelReference(models.Model):
 | 
			
		||||
    references = GenericRelation(ReferencedByGenRel)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -725,6 +725,14 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
 | 
			
		|||
        response = self.client.get(reverse('admin:admin_views_referencedbyinline_changelist'), {TO_FIELD_VAR: 'name'})
 | 
			
		||||
        self.assertEqual(response.status_code, 200)
 | 
			
		||||
 | 
			
		||||
        # #25622 - Specifying a field of a model only referred by a generic
 | 
			
		||||
        # relation should raise DisallowedModelAdminToField.
 | 
			
		||||
        url = reverse('admin:admin_views_referencedbygenrel_changelist')
 | 
			
		||||
        with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls:
 | 
			
		||||
            response = self.client.get(url, {TO_FIELD_VAR: 'object_id'})
 | 
			
		||||
            self.assertEqual(response.status_code, 400)
 | 
			
		||||
            self.assertEqual(len(calls), 1)
 | 
			
		||||
 | 
			
		||||
        # We also want to prevent the add, change, and delete views from
 | 
			
		||||
        # leaking a disallowed field value.
 | 
			
		||||
        with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue