mirror of https://github.com/django/django.git
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.
This commit is contained in:
parent
8a55982e70
commit
8a47ba679d
|
@ -6,7 +6,7 @@ from django.contrib.contenttypes.models import ContentType
|
||||||
from django.core import checks
|
from django.core import checks
|
||||||
from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist
|
from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist
|
||||||
from django.db import DEFAULT_DB_ALIAS, models, router, transaction
|
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.base import ModelBase, make_foreign_order_accessors
|
||||||
from django.db.models.fields.related import (
|
from django.db.models.fields.related import (
|
||||||
ForeignObject, ForeignObjectRel, ReverseManyToOneDescriptor,
|
ForeignObject, ForeignObjectRel, ReverseManyToOneDescriptor,
|
||||||
|
@ -54,11 +54,6 @@ class GenericForeignKey(object):
|
||||||
self.model = cls
|
self.model = cls
|
||||||
self.cache_attr = "_%s_cache" % name
|
self.cache_attr = "_%s_cache" % name
|
||||||
cls._meta.add_field(self, private=True)
|
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)
|
setattr(cls, name, self)
|
||||||
|
|
||||||
def get_filter_kwargs_for_object(self, obj):
|
def get_filter_kwargs_for_object(self, obj):
|
||||||
|
@ -162,20 +157,6 @@ class GenericForeignKey(object):
|
||||||
else:
|
else:
|
||||||
return []
|
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):
|
def get_content_type(self, obj=None, id=None, using=None):
|
||||||
if obj is not None:
|
if obj is not None:
|
||||||
return ContentType.objects.db_manager(obj._state.db).get_for_model(
|
return ContentType.objects.db_manager(obj._state.db).get_for_model(
|
||||||
|
|
|
@ -452,11 +452,14 @@ class Model(six.with_metaclass(ModelBase)):
|
||||||
if kwargs:
|
if kwargs:
|
||||||
for prop in list(kwargs):
|
for prop in list(kwargs):
|
||||||
try:
|
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:
|
if kwargs[prop] is not DEFERRED:
|
||||||
setattr(self, prop, kwargs[prop])
|
setattr(self, prop, kwargs[prop])
|
||||||
del kwargs[prop]
|
del kwargs[prop]
|
||||||
except AttributeError:
|
except (AttributeError, FieldDoesNotExist):
|
||||||
pass
|
pass
|
||||||
if kwargs:
|
if kwargs:
|
||||||
raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
|
raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
|
||||||
|
|
|
@ -400,6 +400,9 @@ Models
|
||||||
* A proxy model may now inherit multiple proxy models that share a common
|
* A proxy model may now inherit multiple proxy models that share a common
|
||||||
non-abstract parent class.
|
non-abstract parent class.
|
||||||
|
|
||||||
|
* ``Model.__init__()`` now sets values of virtual fields from its keyword
|
||||||
|
arguments.
|
||||||
|
|
||||||
Requests and Responses
|
Requests and Responses
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue