Commit 8a47ba67 authored by Michal Petrucha's avatar Michal Petrucha Committed by Tim Graham
Browse files

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.
parent 8a55982e
Loading
Loading
Loading
Loading
+1 −20
Original line number Diff line number Diff line
@@ -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(
+5 −2
Original line number Diff line number Diff line
@@ -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])
+3 −0
Original line number Diff line number Diff line
@@ -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
~~~~~~~~~~~~~~~~~~~~~~