mirror of
https://github.com/django/django.git
synced 2024-12-28 12:06:22 +00:00
20b621eb3c
Thanks Carl Meyer and Tim Graham for the reviews and to all involved
in the discussion.
Backport of 18c0aaa912
from master
219 lines
6.8 KiB
Python
219 lines
6.8 KiB
Python
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.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(FieldFlagsTests, cls).setUpClass()
|
|
cls.fields = (
|
|
list(AllFieldsModel._meta.fields) +
|
|
list(AllFieldsModel._meta.virtual_fields)
|
|
)
|
|
|
|
cls.all_fields = (
|
|
cls.fields +
|
|
list(AllFieldsModel._meta.many_to_many) +
|
|
list(AllFieldsModel._meta.virtual_fields)
|
|
)
|
|
|
|
cls.fields_and_reverse_objects = (
|
|
cls.all_fields +
|
|
list(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.rel
|
|
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.rel
|
|
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.rel
|
|
self.assertEqual(field.model, reverse_field.related_model)
|
|
self.assertEqual(field.related_model, reverse_field.model)
|