Loading django/contrib/contenttypes/generic.py +4 −4 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ from django.db.models.fields.related import ForeignObject, ForeignObjectRel from django.db.models.related import PathInfo from django.db.models.sql.where import Constraint from django.forms import ModelForm, ALL_FIELDS from django.forms.models import (BaseModelFormSet, modelformset_factory, save_instance, from django.forms.models import (BaseModelFormSet, modelformset_factory, modelform_defines_fields) from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets from django.contrib.contenttypes.models import ContentType Loading Loading @@ -46,10 +46,10 @@ class GenericForeignKey(six.with_metaclass(RenameGenericForeignKeyMethods)): self.cache_attr = "_%s_cache" % name cls._meta.add_virtual_field(self) # For some reason I don't totally understand, using weakrefs here doesn't work. signals.pre_init.connect(self.instance_pre_init, sender=cls, weak=False) # Only run pre-initialization field assignment on non-abstract models if not cls._meta.abstract: signals.pre_init.connect(self.instance_pre_init, sender=cls) # Connect myself as the descriptor for this field setattr(cls, name, self) def instance_pre_init(self, signal, sender, args, kwargs, **_kwargs): Loading django/db/models/fields/files.py +3 −1 Original line number Diff line number Diff line Loading @@ -358,6 +358,8 @@ class ImageField(FileField): # Attach update_dimension_fields so that dimension fields declared # after their corresponding image field don't stay cleared by # Model.__init__, see bug #11196. # Only run post-initialization dimension update on non-abstract models if not cls._meta.abstract: signals.post_init.connect(self.update_dimension_fields, sender=cls) def update_dimension_fields(self, instance, force=False, *args, **kwargs): Loading tests/generic_relations/models.py +23 −7 Original line number Diff line number Diff line Loading @@ -32,28 +32,35 @@ class TaggedItem(models.Model): def __str__(self): return self.tag class ValuableTaggedItem(TaggedItem): value = models.PositiveIntegerField() @python_2_unicode_compatible class Comparison(models.Model): """ A model that tests having multiple GenericForeignKeys """ class AbstractComparison(models.Model): comparative = models.CharField(max_length=50) content_type1 = models.ForeignKey(ContentType, related_name="comparative1_set") object_id1 = models.PositiveIntegerField() first_obj = generic.GenericForeignKey(ct_field="content_type1", fk_field="object_id1") @python_2_unicode_compatible class Comparison(AbstractComparison): """ A model that tests having multiple GenericForeignKeys. One is defined through an inherited abstract model and one defined directly on this class. """ content_type2 = models.ForeignKey(ContentType, related_name="comparative2_set") object_id2 = models.PositiveIntegerField() first_obj = generic.GenericForeignKey(ct_field="content_type1", fk_field="object_id1") other_obj = generic.GenericForeignKey(ct_field="content_type2", fk_field="object_id2") def __str__(self): return "%s is %s than %s" % (self.first_obj, self.comparative, self.other_obj) @python_2_unicode_compatible class Animal(models.Model): common_name = models.CharField(max_length=150) Loading @@ -67,6 +74,7 @@ class Animal(models.Model): def __str__(self): return self.common_name @python_2_unicode_compatible class Vegetable(models.Model): name = models.CharField(max_length=150) Loading @@ -77,6 +85,7 @@ class Vegetable(models.Model): def __str__(self): return self.name @python_2_unicode_compatible class Mineral(models.Model): name = models.CharField(max_length=150) Loading @@ -87,18 +96,22 @@ class Mineral(models.Model): def __str__(self): return self.name class GeckoManager(models.Manager): def get_queryset(self): return super(GeckoManager, self).get_queryset().filter(has_tail=True) class Gecko(models.Model): has_tail = models.BooleanField(default=False) objects = GeckoManager() # To test fix for #11263 class Rock(Mineral): tags = generic.GenericRelation(TaggedItem) class ManualPK(models.Model): id = models.IntegerField(primary_key=True) tags = generic.GenericRelation(TaggedItem) Loading @@ -110,14 +123,17 @@ class ForProxyModelModel(models.Model): obj = generic.GenericForeignKey(for_concrete_model=False) title = models.CharField(max_length=255, null=True) class ForConcreteModelModel(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() obj = generic.GenericForeignKey() class ConcreteRelatedModel(models.Model): bases = generic.GenericRelation(ForProxyModelModel, for_concrete_model=False) class ProxyRelatedModel(ConcreteRelatedModel): class Meta: proxy = True tests/model_fields/models.py +38 −11 Original line number Diff line number Diff line Loading @@ -18,13 +18,16 @@ class Foo(models.Model): a = models.CharField(max_length=10) d = models.DecimalField(max_digits=5, decimal_places=3) def get_foo(): return Foo.objects.get(id=1) class Bar(models.Model): b = models.CharField(max_length=10) a = models.ForeignKey(Foo, default=get_foo) class Whiz(models.Model): CHOICES = ( ('Group 1', ( Loading @@ -41,35 +44,44 @@ class Whiz(models.Model): ) c = models.IntegerField(choices=CHOICES, null=True) class BigD(models.Model): d = models.DecimalField(max_digits=38, decimal_places=30) class BigS(models.Model): s = models.SlugField(max_length=255) class BigInt(models.Model): value = models.BigIntegerField() null_value = models.BigIntegerField(null=True, blank=True) class Post(models.Model): title = models.CharField(max_length=100) body = models.TextField() class NullBooleanModel(models.Model): nbfield = models.NullBooleanField() class BooleanModel(models.Model): bfield = models.BooleanField(default=None) string = models.CharField(max_length=10, default='abc') class FksToBooleans(models.Model): """Model wih FKs to models with {Null,}BooleanField's, #15040""" bf = models.ForeignKey(BooleanModel) nbf = models.ForeignKey(NullBooleanModel) class RenamedField(models.Model): modelname = models.IntegerField(name="fieldname", choices=((1, 'One'),)) class VerboseNameField(models.Model): id = models.AutoField("verbose pk", primary_key=True) field1 = models.BigIntegerField("verbose field1") Loading Loading @@ -99,11 +111,13 @@ class VerboseNameField(models.Model): field21 = models.TimeField("verbose field21") field22 = models.URLField("verbose field22") # This model isn't used in any test, just here to ensure it validates successfully. # See ticket #16570. class DecimalLessThanOne(models.Model): d = models.DecimalField(max_digits=3, decimal_places=3) class DataModel(models.Model): short_data = models.BinaryField(max_length=10, default=b'\x08') data = models.BinaryField() Loading @@ -111,6 +125,7 @@ class DataModel(models.Model): ############################################################################### # FileField class Document(models.Model): myfile = models.FileField(upload_to='unused') Loading @@ -127,6 +142,7 @@ if Image: def __init__(self, *args, **kwargs): self.was_opened = False super(TestImageFieldFile, self).__init__(*args, **kwargs) def open(self): self.was_opened = True super(TestImageFieldFile, self).open() Loading @@ -146,15 +162,26 @@ if Image: name = models.CharField(max_length=50) mugshot = TestImageField(storage=temp_storage, upload_to='tests') class PersonWithHeight(models.Model): class AbsctractPersonWithHeight(models.Model): """ Model that defines an ImageField with only one dimension field. Abstract model that defines an ImageField with only one dimension field to make sure the dimension update is correctly run on concrete subclass instance post-initialization. """ name = models.CharField(max_length=50) mugshot = TestImageField(storage=temp_storage, upload_to='tests', height_field='mugshot_height') mugshot_height = models.PositiveSmallIntegerField() class Meta: abstract = True class PersonWithHeight(AbsctractPersonWithHeight): """ Concrete model that subclass an abctract one with only on dimension field. """ name = models.CharField(max_length=50) class PersonWithHeightAndWidth(models.Model): """ Model that defines height and width fields after the ImageField. Loading tests/model_fields/test_imagefield.py +3 −3 Original line number Diff line number Diff line Loading @@ -134,7 +134,7 @@ class ImageFieldTests(ImageFieldTestMixin, TestCase): p = self.PersonModel.objects.get(name="Joan") path = p.mugshot.path shutil.move(path, path + '.moved') p2 = self.PersonModel.objects.get(name="Joan") self.PersonModel.objects.get(name="Joan") def test_delete_when_missing(self): """ Loading Loading
django/contrib/contenttypes/generic.py +4 −4 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ from django.db.models.fields.related import ForeignObject, ForeignObjectRel from django.db.models.related import PathInfo from django.db.models.sql.where import Constraint from django.forms import ModelForm, ALL_FIELDS from django.forms.models import (BaseModelFormSet, modelformset_factory, save_instance, from django.forms.models import (BaseModelFormSet, modelformset_factory, modelform_defines_fields) from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets from django.contrib.contenttypes.models import ContentType Loading Loading @@ -46,10 +46,10 @@ class GenericForeignKey(six.with_metaclass(RenameGenericForeignKeyMethods)): self.cache_attr = "_%s_cache" % name cls._meta.add_virtual_field(self) # For some reason I don't totally understand, using weakrefs here doesn't work. signals.pre_init.connect(self.instance_pre_init, sender=cls, weak=False) # Only run pre-initialization field assignment on non-abstract models if not cls._meta.abstract: signals.pre_init.connect(self.instance_pre_init, sender=cls) # Connect myself as the descriptor for this field setattr(cls, name, self) def instance_pre_init(self, signal, sender, args, kwargs, **_kwargs): Loading
django/db/models/fields/files.py +3 −1 Original line number Diff line number Diff line Loading @@ -358,6 +358,8 @@ class ImageField(FileField): # Attach update_dimension_fields so that dimension fields declared # after their corresponding image field don't stay cleared by # Model.__init__, see bug #11196. # Only run post-initialization dimension update on non-abstract models if not cls._meta.abstract: signals.post_init.connect(self.update_dimension_fields, sender=cls) def update_dimension_fields(self, instance, force=False, *args, **kwargs): Loading
tests/generic_relations/models.py +23 −7 Original line number Diff line number Diff line Loading @@ -32,28 +32,35 @@ class TaggedItem(models.Model): def __str__(self): return self.tag class ValuableTaggedItem(TaggedItem): value = models.PositiveIntegerField() @python_2_unicode_compatible class Comparison(models.Model): """ A model that tests having multiple GenericForeignKeys """ class AbstractComparison(models.Model): comparative = models.CharField(max_length=50) content_type1 = models.ForeignKey(ContentType, related_name="comparative1_set") object_id1 = models.PositiveIntegerField() first_obj = generic.GenericForeignKey(ct_field="content_type1", fk_field="object_id1") @python_2_unicode_compatible class Comparison(AbstractComparison): """ A model that tests having multiple GenericForeignKeys. One is defined through an inherited abstract model and one defined directly on this class. """ content_type2 = models.ForeignKey(ContentType, related_name="comparative2_set") object_id2 = models.PositiveIntegerField() first_obj = generic.GenericForeignKey(ct_field="content_type1", fk_field="object_id1") other_obj = generic.GenericForeignKey(ct_field="content_type2", fk_field="object_id2") def __str__(self): return "%s is %s than %s" % (self.first_obj, self.comparative, self.other_obj) @python_2_unicode_compatible class Animal(models.Model): common_name = models.CharField(max_length=150) Loading @@ -67,6 +74,7 @@ class Animal(models.Model): def __str__(self): return self.common_name @python_2_unicode_compatible class Vegetable(models.Model): name = models.CharField(max_length=150) Loading @@ -77,6 +85,7 @@ class Vegetable(models.Model): def __str__(self): return self.name @python_2_unicode_compatible class Mineral(models.Model): name = models.CharField(max_length=150) Loading @@ -87,18 +96,22 @@ class Mineral(models.Model): def __str__(self): return self.name class GeckoManager(models.Manager): def get_queryset(self): return super(GeckoManager, self).get_queryset().filter(has_tail=True) class Gecko(models.Model): has_tail = models.BooleanField(default=False) objects = GeckoManager() # To test fix for #11263 class Rock(Mineral): tags = generic.GenericRelation(TaggedItem) class ManualPK(models.Model): id = models.IntegerField(primary_key=True) tags = generic.GenericRelation(TaggedItem) Loading @@ -110,14 +123,17 @@ class ForProxyModelModel(models.Model): obj = generic.GenericForeignKey(for_concrete_model=False) title = models.CharField(max_length=255, null=True) class ForConcreteModelModel(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() obj = generic.GenericForeignKey() class ConcreteRelatedModel(models.Model): bases = generic.GenericRelation(ForProxyModelModel, for_concrete_model=False) class ProxyRelatedModel(ConcreteRelatedModel): class Meta: proxy = True
tests/model_fields/models.py +38 −11 Original line number Diff line number Diff line Loading @@ -18,13 +18,16 @@ class Foo(models.Model): a = models.CharField(max_length=10) d = models.DecimalField(max_digits=5, decimal_places=3) def get_foo(): return Foo.objects.get(id=1) class Bar(models.Model): b = models.CharField(max_length=10) a = models.ForeignKey(Foo, default=get_foo) class Whiz(models.Model): CHOICES = ( ('Group 1', ( Loading @@ -41,35 +44,44 @@ class Whiz(models.Model): ) c = models.IntegerField(choices=CHOICES, null=True) class BigD(models.Model): d = models.DecimalField(max_digits=38, decimal_places=30) class BigS(models.Model): s = models.SlugField(max_length=255) class BigInt(models.Model): value = models.BigIntegerField() null_value = models.BigIntegerField(null=True, blank=True) class Post(models.Model): title = models.CharField(max_length=100) body = models.TextField() class NullBooleanModel(models.Model): nbfield = models.NullBooleanField() class BooleanModel(models.Model): bfield = models.BooleanField(default=None) string = models.CharField(max_length=10, default='abc') class FksToBooleans(models.Model): """Model wih FKs to models with {Null,}BooleanField's, #15040""" bf = models.ForeignKey(BooleanModel) nbf = models.ForeignKey(NullBooleanModel) class RenamedField(models.Model): modelname = models.IntegerField(name="fieldname", choices=((1, 'One'),)) class VerboseNameField(models.Model): id = models.AutoField("verbose pk", primary_key=True) field1 = models.BigIntegerField("verbose field1") Loading Loading @@ -99,11 +111,13 @@ class VerboseNameField(models.Model): field21 = models.TimeField("verbose field21") field22 = models.URLField("verbose field22") # This model isn't used in any test, just here to ensure it validates successfully. # See ticket #16570. class DecimalLessThanOne(models.Model): d = models.DecimalField(max_digits=3, decimal_places=3) class DataModel(models.Model): short_data = models.BinaryField(max_length=10, default=b'\x08') data = models.BinaryField() Loading @@ -111,6 +125,7 @@ class DataModel(models.Model): ############################################################################### # FileField class Document(models.Model): myfile = models.FileField(upload_to='unused') Loading @@ -127,6 +142,7 @@ if Image: def __init__(self, *args, **kwargs): self.was_opened = False super(TestImageFieldFile, self).__init__(*args, **kwargs) def open(self): self.was_opened = True super(TestImageFieldFile, self).open() Loading @@ -146,15 +162,26 @@ if Image: name = models.CharField(max_length=50) mugshot = TestImageField(storage=temp_storage, upload_to='tests') class PersonWithHeight(models.Model): class AbsctractPersonWithHeight(models.Model): """ Model that defines an ImageField with only one dimension field. Abstract model that defines an ImageField with only one dimension field to make sure the dimension update is correctly run on concrete subclass instance post-initialization. """ name = models.CharField(max_length=50) mugshot = TestImageField(storage=temp_storage, upload_to='tests', height_field='mugshot_height') mugshot_height = models.PositiveSmallIntegerField() class Meta: abstract = True class PersonWithHeight(AbsctractPersonWithHeight): """ Concrete model that subclass an abctract one with only on dimension field. """ name = models.CharField(max_length=50) class PersonWithHeightAndWidth(models.Model): """ Model that defines height and width fields after the ImageField. Loading
tests/model_fields/test_imagefield.py +3 −3 Original line number Diff line number Diff line Loading @@ -134,7 +134,7 @@ class ImageFieldTests(ImageFieldTestMixin, TestCase): p = self.PersonModel.objects.get(name="Joan") path = p.mugshot.path shutil.move(path, path + '.moved') p2 = self.PersonModel.objects.get(name="Joan") self.PersonModel.objects.get(name="Joan") def test_delete_when_missing(self): """ Loading