mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			224 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
		
			7.1 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.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)
 |