Refs #12663 -- Added tests for methods in db.models.options.
Thanks Russell Keith-Magee and Tim Graham for reviews.
This commit is contained in:
parent
01399fa0aa
commit
d862fae5bb
1
AUTHORS
1
AUTHORS
|
@ -517,6 +517,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
Matthias Pronk <django@masida.nl>
|
Matthias Pronk <django@masida.nl>
|
||||||
Jyrki Pulliainen <jyrki.pulliainen@gmail.com>
|
Jyrki Pulliainen <jyrki.pulliainen@gmail.com>
|
||||||
Thejaswi Puthraya <thejaswi.puthraya@gmail.com>
|
Thejaswi Puthraya <thejaswi.puthraya@gmail.com>
|
||||||
|
Daniel Pyrathon <pirosb3@gmail.com>
|
||||||
Johann Queuniet <johann.queuniet@adh.naellia.eu>
|
Johann Queuniet <johann.queuniet@adh.naellia.eu>
|
||||||
Ram Rachum <ram@rachum.com>
|
Ram Rachum <ram@rachum.com>
|
||||||
Jan Rademaker
|
Jan Rademaker
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
|
|
||||||
|
class Relation(models.Model):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractPerson(models.Model):
|
||||||
|
# DATA fields
|
||||||
|
data_abstract = models.CharField(max_length=10)
|
||||||
|
fk_abstract = models.ForeignKey(Relation, related_name='fk_abstract_rel')
|
||||||
|
|
||||||
|
# M2M fields
|
||||||
|
m2m_abstract = models.ManyToManyField(Relation, related_name='m2m_abstract_rel')
|
||||||
|
friends_abstract = models.ManyToManyField('self', related_name='friends_abstract', symmetrical=True)
|
||||||
|
following_abstract = models.ManyToManyField('self', related_name='followers_abstract', symmetrical=False)
|
||||||
|
|
||||||
|
# VIRTUAL fields
|
||||||
|
data_not_concrete_abstract = models.ForeignObject(
|
||||||
|
Relation,
|
||||||
|
from_fields=['abstract_non_concrete_id'],
|
||||||
|
to_fields=['id'],
|
||||||
|
related_name='fo_abstract_rel',
|
||||||
|
)
|
||||||
|
|
||||||
|
# GFK fields
|
||||||
|
content_type_abstract = models.ForeignKey(ContentType, related_name='+')
|
||||||
|
object_id_abstract = models.PositiveIntegerField()
|
||||||
|
content_object_abstract = GenericForeignKey('content_type_abstract', 'object_id_abstract')
|
||||||
|
|
||||||
|
# GR fields
|
||||||
|
generic_relation_abstract = GenericRelation(Relation)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class BasePerson(AbstractPerson):
|
||||||
|
# DATA fields
|
||||||
|
data_base = models.CharField(max_length=10)
|
||||||
|
fk_base = models.ForeignKey(Relation, related_name='fk_base_rel')
|
||||||
|
|
||||||
|
# M2M fields
|
||||||
|
m2m_base = models.ManyToManyField(Relation, related_name='m2m_base_rel')
|
||||||
|
friends_base = models.ManyToManyField('self', related_name='friends_base', symmetrical=True)
|
||||||
|
following_base = models.ManyToManyField('self', related_name='followers_base', symmetrical=False)
|
||||||
|
|
||||||
|
# VIRTUAL fields
|
||||||
|
data_not_concrete_base = models.ForeignObject(
|
||||||
|
Relation,
|
||||||
|
from_fields=['base_non_concrete_id'],
|
||||||
|
to_fields=['id'],
|
||||||
|
related_name='fo_base_rel',
|
||||||
|
)
|
||||||
|
|
||||||
|
# GFK fields
|
||||||
|
content_type_base = models.ForeignKey(ContentType, related_name='+')
|
||||||
|
object_id_base = models.PositiveIntegerField()
|
||||||
|
content_object_base = GenericForeignKey('content_type_base', 'object_id_base')
|
||||||
|
|
||||||
|
# GR fields
|
||||||
|
generic_relation_base = GenericRelation(Relation)
|
||||||
|
|
||||||
|
|
||||||
|
class Person(BasePerson):
|
||||||
|
# DATA fields
|
||||||
|
data_inherited = models.CharField(max_length=10)
|
||||||
|
fk_inherited = models.ForeignKey(Relation, related_name='fk_concrete_rel')
|
||||||
|
|
||||||
|
# M2M Fields
|
||||||
|
m2m_inherited = models.ManyToManyField(Relation, related_name='m2m_concrete_rel')
|
||||||
|
friends_inherited = models.ManyToManyField('self', related_name='friends_concrete', symmetrical=True)
|
||||||
|
following_inherited = models.ManyToManyField('self', related_name='followers_concrete', symmetrical=False)
|
||||||
|
|
||||||
|
# VIRTUAL fields
|
||||||
|
data_not_concrete_inherited = models.ForeignObject(
|
||||||
|
Relation,
|
||||||
|
from_fields=['model_non_concrete_id'],
|
||||||
|
to_fields=['id'],
|
||||||
|
related_name='fo_concrete_rel',
|
||||||
|
)
|
||||||
|
|
||||||
|
# GFK fields
|
||||||
|
content_type_concrete = models.ForeignKey(ContentType, related_name='+')
|
||||||
|
object_id_concrete = models.PositiveIntegerField()
|
||||||
|
content_object_concrete = GenericForeignKey('content_type_concrete', 'object_id_concrete')
|
||||||
|
|
||||||
|
# GR fields
|
||||||
|
generic_relation_concrete = GenericRelation(Relation)
|
||||||
|
|
||||||
|
|
||||||
|
class ProxyPerson(Person):
|
||||||
|
class Meta:
|
||||||
|
proxy = True
|
||||||
|
|
||||||
|
|
||||||
|
class Relating(models.Model):
|
||||||
|
|
||||||
|
# ForeignKey to BasePerson
|
||||||
|
baseperson = models.ForeignKey(BasePerson, related_name='relating_baseperson')
|
||||||
|
baseperson_hidden = models.ForeignKey(BasePerson, related_name='+')
|
||||||
|
|
||||||
|
# ForeignKey to Person
|
||||||
|
person = models.ForeignKey(Person, related_name='relating_person')
|
||||||
|
person_hidden = models.ForeignKey(Person, related_name='+')
|
||||||
|
|
||||||
|
# ForeignKey to ProxyPerson
|
||||||
|
proxyperson = models.ForeignKey(ProxyPerson, related_name='relating_proxyperson')
|
||||||
|
proxyperson_hidden = models.ForeignKey(ProxyPerson, related_name='+')
|
||||||
|
|
||||||
|
# ManyToManyField to BasePerson
|
||||||
|
basepeople = models.ManyToManyField(BasePerson, related_name='relating_basepeople')
|
||||||
|
basepeople_hidden = models.ManyToManyField(BasePerson, related_name='+')
|
||||||
|
|
||||||
|
# ManyToManyField to Person
|
||||||
|
people = models.ManyToManyField(Person, related_name='relating_people')
|
||||||
|
people_hidden = models.ManyToManyField(Person, related_name='+')
|
|
@ -0,0 +1,656 @@
|
||||||
|
from django import test
|
||||||
|
|
||||||
|
from django.db.models.fields import related, CharField, Field
|
||||||
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||||
|
|
||||||
|
from .models import (
|
||||||
|
AbstractPerson, BasePerson, Person, Relating, Relation
|
||||||
|
)
|
||||||
|
|
||||||
|
TEST_RESULTS = {
|
||||||
|
'fields': {
|
||||||
|
Person: [
|
||||||
|
'id',
|
||||||
|
'data_abstract',
|
||||||
|
'fk_abstract_id',
|
||||||
|
'data_not_concrete_abstract',
|
||||||
|
'content_type_abstract_id',
|
||||||
|
'object_id_abstract',
|
||||||
|
'data_base',
|
||||||
|
'fk_base_id',
|
||||||
|
'data_not_concrete_base',
|
||||||
|
'content_type_base_id',
|
||||||
|
'object_id_base',
|
||||||
|
'baseperson_ptr_id',
|
||||||
|
'data_inherited',
|
||||||
|
'fk_inherited_id',
|
||||||
|
'data_not_concrete_inherited',
|
||||||
|
'content_type_concrete_id',
|
||||||
|
'object_id_concrete',
|
||||||
|
],
|
||||||
|
BasePerson: [
|
||||||
|
'id',
|
||||||
|
'data_abstract',
|
||||||
|
'fk_abstract_id',
|
||||||
|
'data_not_concrete_abstract',
|
||||||
|
'content_type_abstract_id',
|
||||||
|
'object_id_abstract',
|
||||||
|
'data_base',
|
||||||
|
'fk_base_id',
|
||||||
|
'data_not_concrete_base',
|
||||||
|
'content_type_base_id',
|
||||||
|
'object_id_base',
|
||||||
|
],
|
||||||
|
AbstractPerson: [
|
||||||
|
'data_abstract',
|
||||||
|
'fk_abstract_id',
|
||||||
|
'data_not_concrete_abstract',
|
||||||
|
'content_type_abstract_id',
|
||||||
|
'object_id_abstract',
|
||||||
|
],
|
||||||
|
Relating: [
|
||||||
|
'id',
|
||||||
|
'baseperson_id',
|
||||||
|
'baseperson_hidden_id',
|
||||||
|
'person_id',
|
||||||
|
'person_hidden_id',
|
||||||
|
'proxyperson_id',
|
||||||
|
'proxyperson_hidden_id',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'local_fields': {
|
||||||
|
Person: [
|
||||||
|
'baseperson_ptr_id',
|
||||||
|
'data_inherited',
|
||||||
|
'fk_inherited_id',
|
||||||
|
'data_not_concrete_inherited',
|
||||||
|
'content_type_concrete_id',
|
||||||
|
'object_id_concrete',
|
||||||
|
],
|
||||||
|
BasePerson: [
|
||||||
|
'id',
|
||||||
|
'data_abstract',
|
||||||
|
'fk_abstract_id',
|
||||||
|
'data_not_concrete_abstract',
|
||||||
|
'content_type_abstract_id',
|
||||||
|
'object_id_abstract',
|
||||||
|
'data_base',
|
||||||
|
'fk_base_id',
|
||||||
|
'data_not_concrete_base',
|
||||||
|
'content_type_base_id',
|
||||||
|
'object_id_base',
|
||||||
|
],
|
||||||
|
AbstractPerson: [
|
||||||
|
'data_abstract',
|
||||||
|
'fk_abstract_id',
|
||||||
|
'data_not_concrete_abstract',
|
||||||
|
'content_type_abstract_id',
|
||||||
|
'object_id_abstract',
|
||||||
|
],
|
||||||
|
Relating: [
|
||||||
|
'id',
|
||||||
|
'baseperson_id',
|
||||||
|
'baseperson_hidden_id',
|
||||||
|
'person_id',
|
||||||
|
'person_hidden_id',
|
||||||
|
'proxyperson_id',
|
||||||
|
'proxyperson_hidden_id',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'local_concrete_fields': {
|
||||||
|
Person: [
|
||||||
|
'baseperson_ptr_id',
|
||||||
|
'data_inherited',
|
||||||
|
'fk_inherited_id',
|
||||||
|
'content_type_concrete_id',
|
||||||
|
'object_id_concrete',
|
||||||
|
],
|
||||||
|
BasePerson: [
|
||||||
|
'id',
|
||||||
|
'data_abstract',
|
||||||
|
'fk_abstract_id',
|
||||||
|
'content_type_abstract_id',
|
||||||
|
'object_id_abstract',
|
||||||
|
'data_base',
|
||||||
|
'fk_base_id',
|
||||||
|
'content_type_base_id',
|
||||||
|
'object_id_base',
|
||||||
|
],
|
||||||
|
AbstractPerson: [
|
||||||
|
'data_abstract',
|
||||||
|
'fk_abstract_id',
|
||||||
|
'content_type_abstract_id',
|
||||||
|
'object_id_abstract',
|
||||||
|
],
|
||||||
|
Relating: [
|
||||||
|
'id',
|
||||||
|
'baseperson_id',
|
||||||
|
'baseperson_hidden_id',
|
||||||
|
'person_id',
|
||||||
|
'person_hidden_id',
|
||||||
|
'proxyperson_id',
|
||||||
|
'proxyperson_hidden_id',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'many_to_many': {
|
||||||
|
Person: [
|
||||||
|
'm2m_abstract',
|
||||||
|
'friends_abstract',
|
||||||
|
'following_abstract',
|
||||||
|
'm2m_base',
|
||||||
|
'friends_base',
|
||||||
|
'following_base',
|
||||||
|
'm2m_inherited',
|
||||||
|
'friends_inherited',
|
||||||
|
'following_inherited',
|
||||||
|
],
|
||||||
|
BasePerson: [
|
||||||
|
'm2m_abstract',
|
||||||
|
'friends_abstract',
|
||||||
|
'following_abstract',
|
||||||
|
'm2m_base',
|
||||||
|
'friends_base',
|
||||||
|
'following_base',
|
||||||
|
],
|
||||||
|
AbstractPerson: [
|
||||||
|
'm2m_abstract',
|
||||||
|
'friends_abstract',
|
||||||
|
'following_abstract',
|
||||||
|
],
|
||||||
|
Relating: [
|
||||||
|
'basepeople',
|
||||||
|
'basepeople_hidden',
|
||||||
|
'people',
|
||||||
|
'people_hidden',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'many_to_many_with_model': {
|
||||||
|
Person: [
|
||||||
|
BasePerson,
|
||||||
|
BasePerson,
|
||||||
|
BasePerson,
|
||||||
|
BasePerson,
|
||||||
|
BasePerson,
|
||||||
|
BasePerson,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
],
|
||||||
|
BasePerson: [
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
],
|
||||||
|
AbstractPerson: [
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
],
|
||||||
|
Relating: [
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'get_all_related_objects_with_model': {
|
||||||
|
Person: (
|
||||||
|
('relating_baseperson', BasePerson),
|
||||||
|
('relating_person', None),
|
||||||
|
),
|
||||||
|
BasePerson: (
|
||||||
|
('person', None),
|
||||||
|
('relating_baseperson', None),
|
||||||
|
),
|
||||||
|
Relation: (
|
||||||
|
('fk_abstract_rel', None),
|
||||||
|
('fo_abstract_rel', None),
|
||||||
|
('fk_base_rel', None),
|
||||||
|
('fo_base_rel', None),
|
||||||
|
('fk_concrete_rel', None),
|
||||||
|
('fo_concrete_rel', None),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'get_all_related_objects_with_model_local': {
|
||||||
|
Person: (
|
||||||
|
('relating_person', None),
|
||||||
|
),
|
||||||
|
BasePerson: (
|
||||||
|
('person', None),
|
||||||
|
('relating_baseperson', None)
|
||||||
|
),
|
||||||
|
Relation: (
|
||||||
|
('fk_abstract_rel', None),
|
||||||
|
('fo_abstract_rel', None),
|
||||||
|
('fk_base_rel', None),
|
||||||
|
('fo_base_rel', None),
|
||||||
|
('fk_concrete_rel', None),
|
||||||
|
('fo_concrete_rel', None),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'get_all_related_objects_with_model_hidden': {
|
||||||
|
BasePerson: (
|
||||||
|
('model_meta:baseperson_friends_base', None),
|
||||||
|
('model_meta:baseperson_friends_base', None),
|
||||||
|
('model_meta:baseperson_m2m_base', None),
|
||||||
|
('model_meta:baseperson_following_base', None),
|
||||||
|
('model_meta:baseperson_following_base', None),
|
||||||
|
('model_meta:baseperson_m2m_abstract', None),
|
||||||
|
('model_meta:baseperson_friends_abstract', None),
|
||||||
|
('model_meta:baseperson_friends_abstract', None),
|
||||||
|
('model_meta:baseperson_following_abstract', None),
|
||||||
|
('model_meta:baseperson_following_abstract', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:relating_basepeople', None),
|
||||||
|
('model_meta:relating_basepeople_hidden', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
),
|
||||||
|
Person: (
|
||||||
|
('model_meta:baseperson_friends_base', BasePerson),
|
||||||
|
('model_meta:baseperson_friends_base', BasePerson),
|
||||||
|
('model_meta:baseperson_m2m_base', BasePerson),
|
||||||
|
('model_meta:baseperson_following_base', BasePerson),
|
||||||
|
('model_meta:baseperson_following_base', BasePerson),
|
||||||
|
('model_meta:baseperson_m2m_abstract', BasePerson),
|
||||||
|
('model_meta:baseperson_friends_abstract', BasePerson),
|
||||||
|
('model_meta:baseperson_friends_abstract', BasePerson),
|
||||||
|
('model_meta:baseperson_following_abstract', BasePerson),
|
||||||
|
('model_meta:baseperson_following_abstract', BasePerson),
|
||||||
|
('model_meta:relating_basepeople', BasePerson),
|
||||||
|
('model_meta:relating_basepeople_hidden', BasePerson),
|
||||||
|
('model_meta:relating', BasePerson),
|
||||||
|
('model_meta:relating', BasePerson),
|
||||||
|
('model_meta:person_m2m_inherited', None),
|
||||||
|
('model_meta:person_friends_inherited', None),
|
||||||
|
('model_meta:person_friends_inherited', None),
|
||||||
|
('model_meta:person_following_inherited', None),
|
||||||
|
('model_meta:person_following_inherited', None),
|
||||||
|
('model_meta:relating_people', None),
|
||||||
|
('model_meta:relating_people_hidden', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
),
|
||||||
|
Relation: (
|
||||||
|
('model_meta:baseperson_m2m_base', None),
|
||||||
|
('model_meta:baseperson_m2m_abstract', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:person_m2m_inherited', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'get_all_related_objects_with_model_hidden_local': {
|
||||||
|
BasePerson: (
|
||||||
|
('model_meta:baseperson_friends_base', None),
|
||||||
|
('model_meta:baseperson_friends_base', None),
|
||||||
|
('model_meta:baseperson_m2m_base', None),
|
||||||
|
('model_meta:baseperson_following_base', None),
|
||||||
|
('model_meta:baseperson_following_base', None),
|
||||||
|
('model_meta:baseperson_m2m_abstract', None),
|
||||||
|
('model_meta:baseperson_friends_abstract', None),
|
||||||
|
('model_meta:baseperson_friends_abstract', None),
|
||||||
|
('model_meta:baseperson_following_abstract', None),
|
||||||
|
('model_meta:baseperson_following_abstract', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:relating_basepeople', None),
|
||||||
|
('model_meta:relating_basepeople_hidden', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
),
|
||||||
|
Person: (
|
||||||
|
('model_meta:person_m2m_inherited', None),
|
||||||
|
('model_meta:person_friends_inherited', None),
|
||||||
|
('model_meta:person_friends_inherited', None),
|
||||||
|
('model_meta:person_following_inherited', None),
|
||||||
|
('model_meta:person_following_inherited', None),
|
||||||
|
('model_meta:relating_people', None),
|
||||||
|
('model_meta:relating_people_hidden', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
),
|
||||||
|
Relation: (
|
||||||
|
('model_meta:baseperson_m2m_base', None),
|
||||||
|
('model_meta:baseperson_m2m_abstract', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:person_m2m_inherited', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'get_all_related_objects_with_model_proxy': {
|
||||||
|
BasePerson: (
|
||||||
|
('person', None),
|
||||||
|
('relating_baseperson', None),
|
||||||
|
),
|
||||||
|
Person: (
|
||||||
|
('relating_baseperson', BasePerson),
|
||||||
|
('relating_person', None), ('relating_proxyperson', None),
|
||||||
|
),
|
||||||
|
Relation: (
|
||||||
|
('fk_abstract_rel', None), ('fo_abstract_rel', None),
|
||||||
|
('fk_base_rel', None), ('fo_base_rel', None),
|
||||||
|
('fk_concrete_rel', None), ('fo_concrete_rel', None),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'get_all_related_objects_with_model_proxy_hidden': {
|
||||||
|
BasePerson: (
|
||||||
|
('model_meta:baseperson_friends_base', None),
|
||||||
|
('model_meta:baseperson_friends_base', None),
|
||||||
|
('model_meta:baseperson_m2m_base', None),
|
||||||
|
('model_meta:baseperson_following_base', None),
|
||||||
|
('model_meta:baseperson_following_base', None),
|
||||||
|
('model_meta:baseperson_m2m_abstract', None),
|
||||||
|
('model_meta:baseperson_friends_abstract', None),
|
||||||
|
('model_meta:baseperson_friends_abstract', None),
|
||||||
|
('model_meta:baseperson_following_abstract', None),
|
||||||
|
('model_meta:baseperson_following_abstract', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:relating_basepeople', None),
|
||||||
|
('model_meta:relating_basepeople_hidden', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
),
|
||||||
|
Person: (
|
||||||
|
('model_meta:baseperson_friends_base', BasePerson),
|
||||||
|
('model_meta:baseperson_friends_base', BasePerson),
|
||||||
|
('model_meta:baseperson_m2m_base', BasePerson),
|
||||||
|
('model_meta:baseperson_following_base', BasePerson),
|
||||||
|
('model_meta:baseperson_following_base', BasePerson),
|
||||||
|
('model_meta:baseperson_m2m_abstract', BasePerson),
|
||||||
|
('model_meta:baseperson_friends_abstract', BasePerson),
|
||||||
|
('model_meta:baseperson_friends_abstract', BasePerson),
|
||||||
|
('model_meta:baseperson_following_abstract', BasePerson),
|
||||||
|
('model_meta:baseperson_following_abstract', BasePerson),
|
||||||
|
('model_meta:relating_basepeople', BasePerson),
|
||||||
|
('model_meta:relating_basepeople_hidden', BasePerson),
|
||||||
|
('model_meta:relating', BasePerson),
|
||||||
|
('model_meta:relating', BasePerson),
|
||||||
|
('model_meta:person_m2m_inherited', None),
|
||||||
|
('model_meta:person_friends_inherited', None),
|
||||||
|
('model_meta:person_friends_inherited', None),
|
||||||
|
('model_meta:person_following_inherited', None),
|
||||||
|
('model_meta:person_following_inherited', None),
|
||||||
|
('model_meta:relating_people', None),
|
||||||
|
('model_meta:relating_people_hidden', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
('model_meta:relating', None),
|
||||||
|
),
|
||||||
|
Relation: (
|
||||||
|
('model_meta:baseperson_m2m_base', None),
|
||||||
|
('model_meta:baseperson_m2m_abstract', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:baseperson', None),
|
||||||
|
('model_meta:person_m2m_inherited', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:person', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
('model_meta:proxyperson', None),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'get_all_related_many_to_many_with_model': {
|
||||||
|
BasePerson: (
|
||||||
|
('friends_abstract_rel_+', None),
|
||||||
|
('followers_abstract', None),
|
||||||
|
('friends_base_rel_+', None),
|
||||||
|
('followers_base', None),
|
||||||
|
('relating_basepeople', None),
|
||||||
|
('+', None),
|
||||||
|
),
|
||||||
|
Person: (
|
||||||
|
('friends_abstract_rel_+', BasePerson),
|
||||||
|
('followers_abstract', BasePerson),
|
||||||
|
('friends_base_rel_+', BasePerson),
|
||||||
|
('followers_base', BasePerson),
|
||||||
|
('relating_basepeople', BasePerson),
|
||||||
|
('+', BasePerson),
|
||||||
|
('friends_inherited_rel_+', None),
|
||||||
|
('followers_concrete', None),
|
||||||
|
('relating_people', None),
|
||||||
|
('+', None),
|
||||||
|
),
|
||||||
|
Relation: (
|
||||||
|
('m2m_abstract_rel', None),
|
||||||
|
('m2m_base_rel', None),
|
||||||
|
('m2m_concrete_rel', None),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
'get_all_related_many_to_many_local': {
|
||||||
|
BasePerson: [
|
||||||
|
'friends_abstract_rel_+',
|
||||||
|
'followers_abstract',
|
||||||
|
'friends_base_rel_+',
|
||||||
|
'followers_base',
|
||||||
|
'relating_basepeople',
|
||||||
|
'+',
|
||||||
|
],
|
||||||
|
Person: [
|
||||||
|
'friends_inherited_rel_+',
|
||||||
|
'followers_concrete',
|
||||||
|
'relating_people',
|
||||||
|
'+',
|
||||||
|
],
|
||||||
|
Relation: [
|
||||||
|
'm2m_abstract_rel',
|
||||||
|
'm2m_base_rel',
|
||||||
|
'm2m_concrete_rel',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'virtual_fields': {
|
||||||
|
AbstractPerson: [
|
||||||
|
'generic_relation_abstract',
|
||||||
|
'content_object_abstract',
|
||||||
|
],
|
||||||
|
BasePerson: [
|
||||||
|
'generic_relation_base',
|
||||||
|
'content_object_base',
|
||||||
|
'generic_relation_abstract',
|
||||||
|
'content_object_abstract',
|
||||||
|
],
|
||||||
|
Person: [
|
||||||
|
'content_object_concrete',
|
||||||
|
'generic_relation_concrete',
|
||||||
|
'generic_relation_base',
|
||||||
|
'content_object_base',
|
||||||
|
'generic_relation_abstract',
|
||||||
|
'content_object_abstract',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class OptionsBaseTests(test.TestCase):
|
||||||
|
|
||||||
|
def _map_rq_names(self, res):
|
||||||
|
return tuple([(o.field.related_query_name(), m) for o, m in res])
|
||||||
|
|
||||||
|
def _map_names(self, res):
|
||||||
|
return tuple([(f.name, m) for f, m in res])
|
||||||
|
|
||||||
|
|
||||||
|
class DataTests(OptionsBaseTests):
|
||||||
|
|
||||||
|
def test_fields(self):
|
||||||
|
for model, expected_result in TEST_RESULTS['fields'].items():
|
||||||
|
fields = model._meta.fields
|
||||||
|
self.assertEqual([f.attname for f in fields], expected_result)
|
||||||
|
|
||||||
|
def test_local_fields(self):
|
||||||
|
is_data_field = lambda f: isinstance(f, Field) and not isinstance(f, related.ManyToManyField)
|
||||||
|
|
||||||
|
for model, expected_result in TEST_RESULTS['local_fields'].items():
|
||||||
|
fields = model._meta.local_fields
|
||||||
|
self.assertEqual([f.attname for f in fields], expected_result)
|
||||||
|
self.assertTrue(all([f.model is model for f in fields]))
|
||||||
|
self.assertTrue(all([is_data_field(f) for f in fields]))
|
||||||
|
|
||||||
|
def test_local_concrete_fields(self):
|
||||||
|
for model, expected_result in TEST_RESULTS['local_concrete_fields'].items():
|
||||||
|
fields = model._meta.local_concrete_fields
|
||||||
|
self.assertEqual([f.attname for f in fields], expected_result)
|
||||||
|
self.assertTrue(all([f.column is not None for f in fields]))
|
||||||
|
|
||||||
|
|
||||||
|
class M2MTests(OptionsBaseTests):
|
||||||
|
|
||||||
|
def test_many_to_many(self):
|
||||||
|
for model, expected_result in TEST_RESULTS['many_to_many'].items():
|
||||||
|
fields = model._meta.many_to_many
|
||||||
|
self.assertEqual([f.attname for f in fields], expected_result)
|
||||||
|
self.assertTrue(all([isinstance(f.rel, related.ManyToManyRel) for f in fields]))
|
||||||
|
|
||||||
|
def test_many_to_many_with_model(self):
|
||||||
|
for model, expected_result in TEST_RESULTS['many_to_many_with_model'].items():
|
||||||
|
models = [model for field, model in model._meta.get_m2m_with_model()]
|
||||||
|
self.assertEqual(models, expected_result)
|
||||||
|
|
||||||
|
|
||||||
|
class RelatedObjectsTests(OptionsBaseTests):
|
||||||
|
def setUp(self):
|
||||||
|
self.key_name = lambda r: r[0]
|
||||||
|
|
||||||
|
def test_related_objects(self):
|
||||||
|
result_key = 'get_all_related_objects_with_model'
|
||||||
|
for model, expected in TEST_RESULTS[result_key].items():
|
||||||
|
objects = model._meta.get_all_related_objects_with_model()
|
||||||
|
self.assertEqual(self._map_rq_names(objects), expected)
|
||||||
|
|
||||||
|
def test_related_objects_local(self):
|
||||||
|
result_key = 'get_all_related_objects_with_model_local'
|
||||||
|
for model, expected in TEST_RESULTS[result_key].items():
|
||||||
|
objects = model._meta.get_all_related_objects_with_model(local_only=True)
|
||||||
|
self.assertEqual(self._map_rq_names(objects), expected)
|
||||||
|
|
||||||
|
def test_related_objects_include_hidden(self):
|
||||||
|
result_key = 'get_all_related_objects_with_model_hidden'
|
||||||
|
for model, expected in TEST_RESULTS[result_key].items():
|
||||||
|
objects = model._meta.get_all_related_objects_with_model(include_hidden=True)
|
||||||
|
self.assertEqual(
|
||||||
|
sorted(self._map_names(objects), key=self.key_name),
|
||||||
|
sorted(expected, key=self.key_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_related_objects_include_hidden_local_only(self):
|
||||||
|
result_key = 'get_all_related_objects_with_model_hidden_local'
|
||||||
|
for model, expected in TEST_RESULTS[result_key].items():
|
||||||
|
objects = model._meta.get_all_related_objects_with_model(
|
||||||
|
include_hidden=True, local_only=True)
|
||||||
|
self.assertEqual(
|
||||||
|
sorted(self._map_names(objects), key=self.key_name),
|
||||||
|
sorted(expected, key=self.key_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_related_objects_proxy(self):
|
||||||
|
result_key = 'get_all_related_objects_with_model_proxy'
|
||||||
|
for model, expected in TEST_RESULTS[result_key].items():
|
||||||
|
objects = model._meta.get_all_related_objects_with_model(
|
||||||
|
include_proxy_eq=True)
|
||||||
|
self.assertEqual(self._map_rq_names(objects), expected)
|
||||||
|
|
||||||
|
def test_related_objects_proxy_hidden(self):
|
||||||
|
result_key = 'get_all_related_objects_with_model_proxy_hidden'
|
||||||
|
for model, expected in TEST_RESULTS[result_key].items():
|
||||||
|
objects = model._meta.get_all_related_objects_with_model(
|
||||||
|
include_proxy_eq=True, include_hidden=True)
|
||||||
|
self.assertEqual(
|
||||||
|
sorted(self._map_names(objects), key=self.key_name),
|
||||||
|
sorted(expected, key=self.key_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RelatedM2MTests(OptionsBaseTests):
|
||||||
|
|
||||||
|
def test_related_m2m_with_model(self):
|
||||||
|
result_key = 'get_all_related_many_to_many_with_model'
|
||||||
|
for model, expected in TEST_RESULTS[result_key].items():
|
||||||
|
objects = model._meta.get_all_related_m2m_objects_with_model()
|
||||||
|
self.assertEqual(self._map_rq_names(objects), expected)
|
||||||
|
|
||||||
|
def test_related_m2m_local_only(self):
|
||||||
|
result_key = 'get_all_related_many_to_many_local'
|
||||||
|
for model, expected in TEST_RESULTS[result_key].items():
|
||||||
|
objects = model._meta.get_all_related_many_to_many_objects(local_only=True)
|
||||||
|
self.assertEqual([o.field.related_query_name() for o in objects], expected)
|
||||||
|
|
||||||
|
def test_related_m2m_asymmetrical(self):
|
||||||
|
m2m = Person._meta.many_to_many
|
||||||
|
self.assertTrue('following_base' in [f.attname for f in m2m])
|
||||||
|
related_m2m = Person._meta.get_all_related_many_to_many_objects()
|
||||||
|
self.assertTrue('followers_base' in [o.field.related_query_name() for o in related_m2m])
|
||||||
|
|
||||||
|
def test_related_m2m_symmetrical(self):
|
||||||
|
m2m = Person._meta.many_to_many
|
||||||
|
self.assertTrue('friends_base' in [f.attname for f in m2m])
|
||||||
|
related_m2m = Person._meta.get_all_related_many_to_many_objects()
|
||||||
|
self.assertIn('friends_inherited_rel_+', [o.field.related_query_name() for o in related_m2m])
|
||||||
|
|
||||||
|
|
||||||
|
class VirtualFieldsTests(OptionsBaseTests):
|
||||||
|
|
||||||
|
def test_virtual_fields(self):
|
||||||
|
for model, expected_names in TEST_RESULTS['virtual_fields'].items():
|
||||||
|
objects = model._meta.virtual_fields
|
||||||
|
self.assertEqual(sorted([f.name for f in objects]), sorted(expected_names))
|
||||||
|
|
||||||
|
|
||||||
|
class GetFieldByNameTests(OptionsBaseTests):
|
||||||
|
|
||||||
|
def test_get_data_field(self):
|
||||||
|
field_info = Person._meta.get_field_by_name('data_abstract')
|
||||||
|
self.assertEqual(field_info[1:], (BasePerson, True, False))
|
||||||
|
self.assertIsInstance(field_info[0], CharField)
|
||||||
|
|
||||||
|
def test_get_m2m_field(self):
|
||||||
|
field_info = Person._meta.get_field_by_name('m2m_base')
|
||||||
|
self.assertEqual(field_info[1:], (BasePerson, True, True))
|
||||||
|
self.assertIsInstance(field_info[0], related.ManyToManyField)
|
||||||
|
|
||||||
|
def test_get_related_object(self):
|
||||||
|
field_info = Person._meta.get_field_by_name('relating_baseperson')
|
||||||
|
self.assertEqual(field_info[1:], (BasePerson, False, False))
|
||||||
|
self.assertIsInstance(field_info[0], related.RelatedObject)
|
||||||
|
|
||||||
|
def test_get_related_m2m(self):
|
||||||
|
field_info = Person._meta.get_field_by_name('relating_people')
|
||||||
|
self.assertEqual(field_info[1:], (None, False, True))
|
||||||
|
self.assertIsInstance(field_info[0], related.RelatedObject)
|
||||||
|
|
||||||
|
def test_get_virtual_field(self):
|
||||||
|
field_info = Person._meta.get_field_by_name('content_object_base')
|
||||||
|
self.assertEqual(field_info[1:], (None, True, False))
|
||||||
|
self.assertIsInstance(field_info[0], GenericForeignKey)
|
Loading…
Reference in New Issue