123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- from django import test
- from django.contrib.contenttypes.fields import (
- GenericForeignKey, GenericRelation,
- )
- from django.db import models
- from django.db.models.fields.related import (
- ForeignKey, ForeignObject, ForeignObjectRel, ManyToManyField, ManyToOneRel,
- OneToOneField,
- )
- from .models import AllFieldsModel
- NON_CONCRETE_FIELDS = (
- ForeignObject,
- GenericForeignKey,
- GenericRelation,
- )
- NON_EDITABLE_FIELDS = (
- models.BinaryField,
- GenericForeignKey,
- GenericRelation,
- )
- RELATION_FIELDS = (
- ForeignKey,
- ForeignObject,
- ManyToManyField,
- OneToOneField,
- GenericForeignKey,
- GenericRelation,
- )
- MANY_TO_MANY_CLASSES = {
- ManyToManyField,
- }
- MANY_TO_ONE_CLASSES = {
- ForeignObject,
- ForeignKey,
- GenericForeignKey,
- }
- ONE_TO_MANY_CLASSES = {
- ForeignObjectRel,
- ManyToOneRel,
- GenericRelation,
- }
- ONE_TO_ONE_CLASSES = {
- OneToOneField,
- }
- FLAG_PROPERTIES = (
- 'concrete',
- 'editable',
- 'is_relation',
- 'model',
- 'hidden',
- 'one_to_many',
- 'many_to_one',
- 'many_to_many',
- 'one_to_one',
- 'related_model',
- )
- FLAG_PROPERTIES_FOR_RELATIONS = (
- 'one_to_many',
- 'many_to_one',
- 'many_to_many',
- 'one_to_one',
- )
- class FieldFlagsTests(test.SimpleTestCase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls.fields = [
- *AllFieldsModel._meta.fields,
- *AllFieldsModel._meta.private_fields,
- ]
- cls.all_fields = [
- *cls.fields,
- *AllFieldsModel._meta.many_to_many,
- *AllFieldsModel._meta.private_fields,
- ]
- cls.fields_and_reverse_objects = [
- *cls.all_fields,
- *AllFieldsModel._meta.related_objects,
- ]
- def test_each_field_should_have_a_concrete_attribute(self):
- self.assertTrue(all(f.concrete.__class__ == bool for f in self.fields))
- def test_each_field_should_have_an_editable_attribute(self):
- self.assertTrue(all(f.editable.__class__ == bool for f in self.all_fields))
- def test_each_field_should_have_a_has_rel_attribute(self):
- self.assertTrue(all(f.is_relation.__class__ == bool for f in self.all_fields))
- def test_each_object_should_have_auto_created(self):
- self.assertTrue(
- all(f.auto_created.__class__ == bool for f in self.fields_and_reverse_objects)
- )
- def test_non_concrete_fields(self):
- for field in self.fields:
- if type(field) in NON_CONCRETE_FIELDS:
- self.assertFalse(field.concrete)
- else:
- self.assertTrue(field.concrete)
- def test_non_editable_fields(self):
- for field in self.all_fields:
- if type(field) in NON_EDITABLE_FIELDS:
- self.assertFalse(field.editable)
- else:
- self.assertTrue(field.editable)
- def test_related_fields(self):
- for field in self.all_fields:
- if type(field) in RELATION_FIELDS:
- self.assertTrue(field.is_relation)
- else:
- self.assertFalse(field.is_relation)
- def test_field_names_should_always_be_available(self):
- for field in self.fields_and_reverse_objects:
- self.assertTrue(field.name)
- def test_all_field_types_should_have_flags(self):
- for field in self.fields_and_reverse_objects:
- for flag in FLAG_PROPERTIES:
- self.assertTrue(hasattr(field, flag), "Field %s does not have flag %s" % (field, flag))
- if field.is_relation:
- true_cardinality_flags = sum(
- getattr(field, flag) is True
- for flag in FLAG_PROPERTIES_FOR_RELATIONS
- )
- # If the field has a relation, there should be only one of the
- # 4 cardinality flags available.
- self.assertEqual(1, true_cardinality_flags)
- def test_cardinality_m2m(self):
- m2m_type_fields = [
- f for f in self.all_fields
- if f.is_relation and f.many_to_many
- ]
- # Test classes are what we expect
- self.assertEqual(MANY_TO_MANY_CLASSES, {f.__class__ for f in m2m_type_fields})
- # Ensure all m2m reverses are m2m
- for field in m2m_type_fields:
- reverse_field = field.remote_field
- self.assertTrue(reverse_field.is_relation)
- self.assertTrue(reverse_field.many_to_many)
- self.assertTrue(reverse_field.related_model)
- def test_cardinality_o2m(self):
- o2m_type_fields = [
- f for f in self.fields_and_reverse_objects
- if f.is_relation and f.one_to_many
- ]
- # Test classes are what we expect
- self.assertEqual(ONE_TO_MANY_CLASSES, {f.__class__ for f in o2m_type_fields})
- # Ensure all o2m reverses are m2o
- for field in o2m_type_fields:
- if field.concrete:
- reverse_field = field.remote_field
- self.assertTrue(reverse_field.is_relation and reverse_field.many_to_one)
- def test_cardinality_m2o(self):
- m2o_type_fields = [
- f for f in self.fields_and_reverse_objects
- if f.is_relation and f.many_to_one
- ]
- # Test classes are what we expect
- self.assertEqual(MANY_TO_ONE_CLASSES, {f.__class__ for f in m2o_type_fields})
- # Ensure all m2o reverses are o2m
- for obj in m2o_type_fields:
- if hasattr(obj, 'field'):
- reverse_field = obj.field
- self.assertTrue(reverse_field.is_relation and reverse_field.one_to_many)
- def test_cardinality_o2o(self):
- o2o_type_fields = [
- f for f in self.all_fields
- if f.is_relation and f.one_to_one
- ]
- # Test classes are what we expect
- self.assertEqual(ONE_TO_ONE_CLASSES, {f.__class__ for f in o2o_type_fields})
- # Ensure all o2o reverses are o2o
- for obj in o2o_type_fields:
- if hasattr(obj, 'field'):
- reverse_field = obj.field
- self.assertTrue(reverse_field.is_relation and reverse_field.one_to_one)
- def test_hidden_flag(self):
- incl_hidden = set(AllFieldsModel._meta.get_fields(include_hidden=True))
- no_hidden = set(AllFieldsModel._meta.get_fields())
- fields_that_should_be_hidden = (incl_hidden - no_hidden)
- for f in incl_hidden:
- self.assertEqual(f in fields_that_should_be_hidden, f.hidden)
- def test_model_and_reverse_model_should_equal_on_relations(self):
- for field in AllFieldsModel._meta.get_fields():
- is_concrete_forward_field = field.concrete and field.related_model
- if is_concrete_forward_field:
- reverse_field = field.remote_field
- self.assertEqual(field.model, reverse_field.related_model)
- self.assertEqual(field.related_model, reverse_field.model)
- def test_null(self):
- # null isn't well defined for a ManyToManyField, but changing it to
- # True causes backwards compatibility problems (#25320).
- self.assertFalse(AllFieldsModel._meta.get_field('m2m').null)
- self.assertTrue(AllFieldsModel._meta.get_field('reverse2').null)
|