mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[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:
		@@ -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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user