summaryrefslogtreecommitdiff
path: root/tests/schema/fields.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/schema/fields.py')
-rw-r--r--tests/schema/fields.py54
1 files changed, 54 insertions, 0 deletions
diff --git a/tests/schema/fields.py b/tests/schema/fields.py
new file mode 100644
index 0000000000..596671a6bc
--- /dev/null
+++ b/tests/schema/fields.py
@@ -0,0 +1,54 @@
+from django.db.models.fields.related import (
+ create_many_to_many_intermediary_model,
+ ManyToManyField, ManyToManyRel, RelatedField,
+ RECURSIVE_RELATIONSHIP_CONSTANT, ReverseManyRelatedObjectsDescriptor,
+)
+from django.utils.functional import curry
+
+
+class CustomManyToManyField(RelatedField):
+ """
+ Ticket #24104 - Need to have a custom ManyToManyField,
+ which is not an inheritor of ManyToManyField.
+ """
+
+ def __init__(self, to, db_constraint=True, swappable=True, **kwargs):
+ try:
+ to._meta
+ except AttributeError:
+ to = str(to)
+ kwargs['verbose_name'] = kwargs.get('verbose_name', None)
+ kwargs['rel'] = ManyToManyRel(
+ to,
+ related_name=kwargs.pop('related_name', None),
+ related_query_name=kwargs.pop('related_query_name', None),
+ limit_choices_to=kwargs.pop('limit_choices_to', None),
+ symmetrical=kwargs.pop('symmetrical', to == RECURSIVE_RELATIONSHIP_CONSTANT),
+ through=kwargs.pop('through', None),
+ through_fields=kwargs.pop('through_fields', None),
+ db_constraint=db_constraint,
+ )
+ self.swappable = swappable
+ self.db_table = kwargs.pop('db_table', None)
+ if kwargs['rel'].through is not None:
+ assert self.db_table is None, "Cannot specify a db_table if an intermediary model is used."
+ super(CustomManyToManyField, self).__init__(**kwargs)
+
+ def contribute_to_class(self, cls, name):
+ if self.rel.symmetrical and (self.rel.to == "self" or self.rel.to == cls._meta.object_name):
+ self.rel.related_name = "%s_rel_+" % name
+ super(CustomManyToManyField, self).contribute_to_class(cls, name)
+ if not self.rel.through and not cls._meta.abstract and not cls._meta.swapped:
+ self.rel.through = create_many_to_many_intermediary_model(self, cls)
+ setattr(cls, self.name, ReverseManyRelatedObjectsDescriptor(self))
+ self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta)
+
+ def get_internal_type(self):
+ return 'ManyToManyField'
+
+ # Copy those methods from ManyToManyField because they don't call super() internally
+ contribute_to_related_class = ManyToManyField.__dict__['contribute_to_related_class']
+ set_attributes_from_rel = ManyToManyField.__dict__['set_attributes_from_rel']
+ _get_m2m_attr = ManyToManyField.__dict__['_get_m2m_attr']
+ _get_m2m_reverse_attr = ManyToManyField.__dict__['_get_m2m_reverse_attr']
+ _get_m2m_db_table = ManyToManyField.__dict__['_get_m2m_db_table']