From 8a47ba679d2da0dee74671a53ba0cd918b433e34 Mon Sep 17 00:00:00 2001 From: Michal Petrucha Date: Tue, 19 Apr 2016 22:34:08 +0200 Subject: [PATCH] Refs #16508 -- Made Model.__init__() aware of virtual fields. It's no longer necessary for GenericForeignKey (and any other virtual fields) to intercept the field's values using the pre_init signal. --- django/contrib/contenttypes/fields.py | 21 +-------------------- django/db/models/base.py | 7 +++++-- docs/releases/1.10.txt | 3 +++ 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/django/contrib/contenttypes/fields.py b/django/contrib/contenttypes/fields.py index fb62f0395b..e4bc292642 100644 --- a/django/contrib/contenttypes/fields.py +++ b/django/contrib/contenttypes/fields.py @@ -6,7 +6,7 @@ from django.contrib.contenttypes.models import ContentType from django.core import checks from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist from django.db import DEFAULT_DB_ALIAS, models, router, transaction -from django.db.models import DO_NOTHING, signals +from django.db.models import DO_NOTHING from django.db.models.base import ModelBase, make_foreign_order_accessors from django.db.models.fields.related import ( ForeignObject, ForeignObjectRel, ReverseManyToOneDescriptor, @@ -54,11 +54,6 @@ class GenericForeignKey(object): self.model = cls self.cache_attr = "_%s_cache" % name cls._meta.add_field(self, private=True) - - # 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) - setattr(cls, name, self) def get_filter_kwargs_for_object(self, obj): @@ -162,20 +157,6 @@ class GenericForeignKey(object): else: return [] - def instance_pre_init(self, signal, sender, args, kwargs, **_kwargs): - """ - Handle initializing an object with the generic FK instead of - content_type and object_id fields. - """ - if self.name in kwargs: - value = kwargs.pop(self.name) - if value is not None: - kwargs[self.ct_field] = self.get_content_type(obj=value) - kwargs[self.fk_field] = value._get_pk_val() - else: - kwargs[self.ct_field] = None - kwargs[self.fk_field] = None - def get_content_type(self, obj=None, id=None, using=None): if obj is not None: return ContentType.objects.db_manager(obj._state.db).get_for_model( diff --git a/django/db/models/base.py b/django/db/models/base.py index 94031d76a9..2a6fa081a4 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -452,11 +452,14 @@ class Model(six.with_metaclass(ModelBase)): if kwargs: for prop in list(kwargs): try: - if isinstance(getattr(self.__class__, prop), property): + # Any remaining kwargs must correspond to properties or + # virtual fields. + if (isinstance(getattr(self.__class__, prop), property) or + self._meta.get_field(prop)): if kwargs[prop] is not DEFERRED: setattr(self, prop, kwargs[prop]) del kwargs[prop] - except AttributeError: + except (AttributeError, FieldDoesNotExist): pass if kwargs: raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0]) diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index 3eac9bb311..826752996b 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -400,6 +400,9 @@ Models * A proxy model may now inherit multiple proxy models that share a common non-abstract parent class. +* ``Model.__init__()`` now sets values of virtual fields from its keyword + arguments. + Requests and Responses ~~~~~~~~~~~~~~~~~~~~~~