[1.8.x] Fixed #24289 -- Reversed usage of Field.many_to_one and one_to_many.

Thanks Carl Meyer and Tim Graham for the reviews and to all involved
in the discussion.

Backport of 18c0aaa912 from master
This commit is contained in:
Loic Bistuer 2015-02-14 01:55:36 +07:00
parent 136edac897
commit 20b621eb3c
8 changed files with 34 additions and 34 deletions

View File

@ -296,7 +296,7 @@ def _get_non_gfk_field(opts, name):
"not found" by get_field(). This could likely be cleaned up. "not found" by get_field(). This could likely be cleaned up.
""" """
field = opts.get_field(name) field = opts.get_field(name)
if field.is_relation and field.one_to_many and not field.related_model: if field.is_relation and field.many_to_one and not field.related_model:
raise FieldDoesNotExist() raise FieldDoesNotExist()
return field return field

View File

@ -27,8 +27,8 @@ class GenericForeignKey(object):
is_relation = True is_relation = True
many_to_many = False many_to_many = False
many_to_one = False many_to_one = True
one_to_many = True one_to_many = False
one_to_one = False one_to_one = False
related_model = None related_model = None
@ -258,8 +258,8 @@ class GenericRelation(ForeignObject):
auto_created = False auto_created = False
many_to_many = False many_to_many = False
many_to_one = True many_to_one = False
one_to_many = False one_to_many = True
one_to_one = False one_to_one = False
def __init__(self, to, **kwargs): def __init__(self, to, **kwargs):

View File

@ -65,7 +65,7 @@ def get_candidate_relations_to_delete(opts):
# N-N (i.e., many-to-many) relations aren't candidates for deletion. # N-N (i.e., many-to-many) relations aren't candidates for deletion.
return ( return (
f for f in candidate_model_fields f for f in candidate_model_fields
if f.auto_created and not f.concrete and (f.one_to_one or f.many_to_one) if f.auto_created and not f.concrete and (f.one_to_one or f.one_to_many)
) )

View File

@ -1475,8 +1475,8 @@ class ManyToManyRel(ForeignObjectRel):
class ForeignObject(RelatedField): class ForeignObject(RelatedField):
# Field flags # Field flags
many_to_many = False many_to_many = False
many_to_one = False many_to_one = True
one_to_many = True one_to_many = False
one_to_one = False one_to_one = False
requires_unique_target = True requires_unique_target = True
@ -1785,8 +1785,8 @@ class ForeignObject(RelatedField):
class ForeignKey(ForeignObject): class ForeignKey(ForeignObject):
# Field flags # Field flags
many_to_many = False many_to_many = False
many_to_one = False many_to_one = True
one_to_many = True one_to_many = False
one_to_one = False one_to_one = False
empty_strings_allowed = False empty_strings_allowed = False

View File

@ -388,9 +388,9 @@ class Options(object):
# and all the models may not have been loaded yet; we don't want to cache # and all the models may not have been loaded yet; we don't want to cache
# the string reference to the related_model. # the string reference to the related_model.
is_not_an_m2m_field = lambda f: not (f.is_relation and f.many_to_many) is_not_an_m2m_field = lambda f: not (f.is_relation and f.many_to_many)
is_not_a_generic_relation = lambda f: not (f.is_relation and f.many_to_one) is_not_a_generic_relation = lambda f: not (f.is_relation and f.one_to_many)
is_not_a_generic_foreign_key = lambda f: not ( is_not_a_generic_foreign_key = lambda f: not (
f.is_relation and f.one_to_many and not (hasattr(f.rel, 'to') and f.rel.to) f.is_relation and f.many_to_one and not (hasattr(f.rel, 'to') and f.rel.to)
) )
return make_immutable_fields_list( return make_immutable_fields_list(
"fields", "fields",
@ -564,7 +564,7 @@ class Options(object):
for field in fields: for field in fields:
# For backwards compatibility GenericForeignKey should not be # For backwards compatibility GenericForeignKey should not be
# included in the results. # included in the results.
if field.is_relation and field.one_to_many and field.related_model is None: if field.is_relation and field.many_to_one and field.related_model is None:
continue continue
names.add(field.name) names.add(field.name)

View File

@ -1863,16 +1863,6 @@ relation. These attribute are present on all fields; however, they will only
have meaningful values if the field is a relation type have meaningful values if the field is a relation type
(:attr:`Field.is_relation=True <Field.is_relation>`). (:attr:`Field.is_relation=True <Field.is_relation>`).
.. attribute:: Field.one_to_many
Boolean flag that is ``True`` if the field has a one-to-many relation, such
as a ``ForeignKey``; ``False`` otherwise.
.. attribute:: Field.one_to_one
Boolean flag that is ``True`` if the field has a one-to-one relation, such
as a ``OneToOneField``; ``False`` otherwise.
.. attribute:: Field.many_to_many .. attribute:: Field.many_to_many
Boolean flag that is ``True`` if the field has a many-to-many relation; Boolean flag that is ``True`` if the field has a many-to-many relation;
@ -1882,9 +1872,19 @@ have meaningful values if the field is a relation type
.. attribute:: Field.many_to_one .. attribute:: Field.many_to_one
Boolean flag that is ``True`` if the field has a many-to-one relation, such Boolean flag that is ``True`` if the field has a many-to-one relation, such
as a ``ForeignKey``; ``False`` otherwise.
.. attribute:: Field.one_to_many
Boolean flag that is ``True`` if the field has a one-to-many relation, such
as a ``GenericRelation`` or the reverse of a ``ForeignKey``; ``False`` as a ``GenericRelation`` or the reverse of a ``ForeignKey``; ``False``
otherwise. otherwise.
.. attribute:: Field.one_to_one
Boolean flag that is ``True`` if the field has a one-to-one relation, such
as a ``OneToOneField``; ``False`` otherwise.
.. attribute:: Field.related_model .. attribute:: Field.related_model
Points to the model the field relates to. For example, ``Author`` in Points to the model the field relates to. For example, ``Author`` in

View File

@ -213,7 +213,7 @@ can be made to convert your code to the new API:
for f in MyModel._meta.get_fields() for f in MyModel._meta.get_fields()
if not f.is_relation if not f.is_relation
or f.one_to_one or f.one_to_one
or (f.one_to_many and f.related_model) or (f.many_to_one and f.related_model)
] ]
* ``MyModel._meta.get_concrete_fields_with_model()``:: * ``MyModel._meta.get_concrete_fields_with_model()``::
@ -224,7 +224,7 @@ can be made to convert your code to the new API:
if f.concrete and ( if f.concrete and (
not f.is_relation not f.is_relation
or f.one_to_one or f.one_to_one
or (f.one_to_many and f.related_model) or (f.many_to_one and f.related_model)
) )
] ]
@ -240,7 +240,7 @@ can be made to convert your code to the new API:
[ [
f for f in MyModel._meta.get_fields() f for f in MyModel._meta.get_fields()
if f.many_to_one and f.auto_created if f.one_to_many and f.auto_created
] ]
* ``MyModel._meta.get_all_related_objects_with_model()``:: * ``MyModel._meta.get_all_related_objects_with_model()``::
@ -248,7 +248,7 @@ can be made to convert your code to the new API:
[ [
(f, f.model if f.model != MyModel else None) (f, f.model if f.model != MyModel else None)
for f in MyModel._meta.get_fields() for f in MyModel._meta.get_fields()
if f.many_to_one and f.auto_created if f.one_to_many and f.auto_created
] ]
* ``MyModel._meta.get_all_related_many_to_many_objects()``:: * ``MyModel._meta.get_all_related_many_to_many_objects()``::
@ -274,7 +274,7 @@ can be made to convert your code to the new API:
for field in MyModel._meta.get_fields() for field in MyModel._meta.get_fields()
# For complete backwards compatibility, you may want to exclude # For complete backwards compatibility, you may want to exclude
# GenericForeignKey from the results. # GenericForeignKey from the results.
if not (field.one_to_many and field.related_model is None) if not (field.many_to_one and field.related_model is None)
))) )))
This provides a 100% backwards compatible replacement, ensuring that both This provides a 100% backwards compatible replacement, ensuring that both

View File

@ -31,22 +31,22 @@ RELATION_FIELDS = (
GenericRelation, GenericRelation,
) )
ONE_TO_MANY_CLASSES = { MANY_TO_MANY_CLASSES = {
ManyToManyField,
}
MANY_TO_ONE_CLASSES = {
ForeignObject, ForeignObject,
ForeignKey, ForeignKey,
GenericForeignKey, GenericForeignKey,
} }
MANY_TO_ONE_CLASSES = { ONE_TO_MANY_CLASSES = {
ForeignObjectRel, ForeignObjectRel,
ManyToOneRel, ManyToOneRel,
GenericRelation, GenericRelation,
} }
MANY_TO_MANY_CLASSES = {
ManyToManyField,
}
ONE_TO_ONE_CLASSES = { ONE_TO_ONE_CLASSES = {
OneToOneField, OneToOneField,
} }