mirror of
https://github.com/django/django.git
synced 2025-01-05 16:06:07 +00:00
Fixed #35224 -- Made GenericForeignKey inherit from Field.
This commit is contained in:
parent
57e6336f52
commit
6002df0671
@ -11,6 +11,7 @@ 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, ForeignObject, ForeignObjectRel
|
from django.db.models import DO_NOTHING, ForeignObject, ForeignObjectRel
|
||||||
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 import Field
|
||||||
from django.db.models.fields.mixins import FieldCacheMixin
|
from django.db.models.fields.mixins import FieldCacheMixin
|
||||||
from django.db.models.fields.related import (
|
from django.db.models.fields.related import (
|
||||||
ReverseManyToOneDescriptor,
|
ReverseManyToOneDescriptor,
|
||||||
@ -24,7 +25,7 @@ from django.utils.deprecation import RemovedInDjango60Warning
|
|||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
|
||||||
class GenericForeignKey(FieldCacheMixin):
|
class GenericForeignKey(FieldCacheMixin, Field):
|
||||||
"""
|
"""
|
||||||
Provide a generic many-to-one relation through the ``content_type`` and
|
Provide a generic many-to-one relation through the ``content_type`` and
|
||||||
``object_id`` fields.
|
``object_id`` fields.
|
||||||
@ -33,35 +34,28 @@ class GenericForeignKey(FieldCacheMixin):
|
|||||||
ForwardManyToOneDescriptor) by adding itself as a model attribute.
|
ForwardManyToOneDescriptor) by adding itself as a model attribute.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Field flags
|
|
||||||
auto_created = False
|
|
||||||
concrete = False
|
|
||||||
editable = False
|
|
||||||
hidden = False
|
|
||||||
|
|
||||||
is_relation = True
|
|
||||||
many_to_many = False
|
many_to_many = False
|
||||||
many_to_one = True
|
many_to_one = True
|
||||||
one_to_many = False
|
one_to_many = False
|
||||||
one_to_one = False
|
one_to_one = False
|
||||||
related_model = None
|
|
||||||
remote_field = None
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self, ct_field="content_type", fk_field="object_id", for_concrete_model=True
|
self, ct_field="content_type", fk_field="object_id", for_concrete_model=True
|
||||||
):
|
):
|
||||||
|
super().__init__(editable=False)
|
||||||
self.ct_field = ct_field
|
self.ct_field = ct_field
|
||||||
self.fk_field = fk_field
|
self.fk_field = fk_field
|
||||||
self.for_concrete_model = for_concrete_model
|
self.for_concrete_model = for_concrete_model
|
||||||
self.editable = False
|
self.is_relation = True
|
||||||
self.rel = None
|
|
||||||
self.column = None
|
|
||||||
|
|
||||||
def contribute_to_class(self, cls, name, **kwargs):
|
def contribute_to_class(self, cls, name, **kwargs):
|
||||||
self.name = name
|
super().contribute_to_class(cls, name, private_only=True, **kwargs)
|
||||||
self.model = cls
|
# GenericForeignKey is its own descriptor.
|
||||||
cls._meta.add_field(self, private=True)
|
setattr(cls, self.attname, self)
|
||||||
setattr(cls, name, self)
|
|
||||||
|
def get_attname_column(self):
|
||||||
|
attname, column = super().get_attname_column()
|
||||||
|
return attname, None
|
||||||
|
|
||||||
def get_filter_kwargs_for_object(self, obj):
|
def get_filter_kwargs_for_object(self, obj):
|
||||||
"""See corresponding method on Field"""
|
"""See corresponding method on Field"""
|
||||||
@ -77,10 +71,6 @@ class GenericForeignKey(FieldCacheMixin):
|
|||||||
self.ct_field: ContentType.objects.get_for_model(obj).pk,
|
self.ct_field: ContentType.objects.get_for_model(obj).pk,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
model = self.model
|
|
||||||
return "%s.%s" % (model._meta.label, self.name)
|
|
||||||
|
|
||||||
def check(self, **kwargs):
|
def check(self, **kwargs):
|
||||||
return [
|
return [
|
||||||
*self._check_field_name(),
|
*self._check_field_name(),
|
||||||
@ -88,18 +78,6 @@ class GenericForeignKey(FieldCacheMixin):
|
|||||||
*self._check_content_type_field(),
|
*self._check_content_type_field(),
|
||||||
]
|
]
|
||||||
|
|
||||||
def _check_field_name(self):
|
|
||||||
if self.name.endswith("_"):
|
|
||||||
return [
|
|
||||||
checks.Error(
|
|
||||||
"Field names must not end with an underscore.",
|
|
||||||
obj=self,
|
|
||||||
id="fields.E001",
|
|
||||||
)
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def _check_object_id_field(self):
|
def _check_object_id_field(self):
|
||||||
try:
|
try:
|
||||||
self.model._meta.get_field(self.fk_field)
|
self.model._meta.get_field(self.fk_field)
|
||||||
|
Loading…
Reference in New Issue
Block a user