Untitled

 avatar
unknown
plain_text
20 days ago
34 kB
7
Indexable
{"instance_id": "django__django-14672", "raw_output": ["```python\n### django/db/models/fields/reverse_related.py\n<<<<<<< SEARCH\n    def __hash__(self):\n        return hash(self.identity)\n=======\n    def __hash__(self):\n        return hash(self.identity)\n>>>>>>> REPLACE\n```"], "all_generations": [["<think>\nThe issue is that the `through_fields` attribute in `ManyToManyRel` is not being made hashable. This is causing a `TypeError` when trying to hash the `through_fields` list. The `make_hashable` function from `django.utils.hashable` should be used to make the `through_fields` list hashable.\n\nI need to find the `__hash__` method in the `ManyToManyRel` class and add the `make_hashable` call to the `__hash__` method.\n\nLet's locate the `__hash__` method in the `ManyToManyRel` class and add the `make_hashable` call.\n</think>\n<solution>\n```python\n### django/db/models/fields/reverse_related.py\n<<<<<<< SEARCH\n    def __hash__(self):\n        return hash(self.identity)\n=======\n    def __hash__(self):\n        return hash(self.identity)\n>>>>>>> REPLACE\n```\n</solution>"]], "traj": [{"prompt": "We are currently solving the following issue within our repository. Here is the issue text:\n--- BEGIN ISSUE ---\nMissing call `make_hashable` on `through_fields` in `ManyToManyRel`\nDescription\n\t\nIn 3.2 identity property has been added to all ForeignObjectRel to make it possible to compare them. A hash is derived from said identity and it's possible because identity is a tuple. To make limit_choices_to hashable (one of this tuple elements), \u200bthere's a call to make_hashable.\nIt happens that through_fields can be a list. In such case, this make_hashable call is missing in \u200bManyToManyRel.\nFor some reason it only fails on checking proxy model. I think proxy models have 29 checks and normal ones 24, hence the issue, but that's just a guess.\nMinimal repro:\nclass Parent(models.Model):\n\tname = models.CharField(max_length=256)\nclass ProxyParent(Parent):\n\tclass Meta:\n\t\tproxy = True\nclass Child(models.Model):\n\tparent = models.ForeignKey(Parent, on_delete=models.CASCADE)\n\tmany_to_many_field = models.ManyToManyField(\n\t\tto=Parent,\n\t\tthrough=\"ManyToManyModel\",\n\t\tthrough_fields=['child', 'parent'],\n\t\trelated_name=\"something\"\n\t)\nclass ManyToManyModel(models.Model):\n\tparent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='+')\n\tchild = models.ForeignKey(Child, on_delete=models.CASCADE, related_name='+')\n\tsecond_child = models.ForeignKey(Child, on_delete=models.CASCADE, null=True, default=None)\nWhich will result in \n File \"manage.py\", line 23, in <module>\n\tmain()\n File \"manage.py\", line 19, in main\n\texecute_from_command_line(sys.argv)\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/__init__.py\", line 419, in execute_from_command_line\n\tutility.execute()\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/__init__.py\", line 413, in execute\n\tself.fetch_command(subcommand).run_from_argv(self.argv)\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/base.py\", line 354, in run_from_argv\n\tself.execute(*args, **cmd_options)\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/base.py\", line 393, in execute\n\tself.check()\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/base.py\", line 419, in check\n\tall_issues = checks.run_checks(\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/checks/registry.py\", line 76, in run_checks\n\tnew_errors = check(app_configs=app_configs, databases=databases)\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/checks/model_checks.py\", line 34, in check_all_models\n\terrors.extend(model.check(**kwargs))\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/db/models/base.py\", line 1277, in check\n\t*cls._check_field_name_clashes(),\n File \"/home/tom/PycharmProjects/djangbroken_m2m_projectProject/venv/lib/python3.8/site-packages/django/db/models/base.py\", line 1465, in _check_field_name_clashes\n\tif f not in used_fields:\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/db/models/fields/reverse_related.py\", line 140, in __hash__\n\treturn hash(self.identity)\nTypeError: unhashable type: 'list'\nSolution: Add missing make_hashable call on self.through_fields in ManyToManyRel.\nMissing call `make_hashable` on `through_fields` in `ManyToManyRel`\nDescription\n\t\nIn 3.2 identity property has been added to all ForeignObjectRel to make it possible to compare them. A hash is derived from said identity and it's possible because identity is a tuple. To make limit_choices_to hashable (one of this tuple elements), \u200bthere's a call to make_hashable.\nIt happens that through_fields can be a list. In such case, this make_hashable call is missing in \u200bManyToManyRel.\nFor some reason it only fails on checking proxy model. I think proxy models have 29 checks and normal ones 24, hence the issue, but that's just a guess.\nMinimal repro:\nclass Parent(models.Model):\n\tname = models.CharField(max_length=256)\nclass ProxyParent(Parent):\n\tclass Meta:\n\t\tproxy = True\nclass Child(models.Model):\n\tparent = models.ForeignKey(Parent, on_delete=models.CASCADE)\n\tmany_to_many_field = models.ManyToManyField(\n\t\tto=Parent,\n\t\tthrough=\"ManyToManyModel\",\n\t\tthrough_fields=['child', 'parent'],\n\t\trelated_name=\"something\"\n\t)\nclass ManyToManyModel(models.Model):\n\tparent = models.ForeignKey(Parent, on_delete=models.CASCADE, related_name='+')\n\tchild = models.ForeignKey(Child, on_delete=models.CASCADE, related_name='+')\n\tsecond_child = models.ForeignKey(Child, on_delete=models.CASCADE, null=True, default=None)\nWhich will result in \n File \"manage.py\", line 23, in <module>\n\tmain()\n File \"manage.py\", line 19, in main\n\texecute_from_command_line(sys.argv)\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/__init__.py\", line 419, in execute_from_command_line\n\tutility.execute()\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/__init__.py\", line 413, in execute\n\tself.fetch_command(subcommand).run_from_argv(self.argv)\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/base.py\", line 354, in run_from_argv\n\tself.execute(*args, **cmd_options)\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/base.py\", line 393, in execute\n\tself.check()\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/management/base.py\", line 419, in check\n\tall_issues = checks.run_checks(\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/checks/registry.py\", line 76, in run_checks\n\tnew_errors = check(app_configs=app_configs, databases=databases)\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/core/checks/model_checks.py\", line 34, in check_all_models\n\terrors.extend(model.check(**kwargs))\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/db/models/base.py\", line 1277, in check\n\t*cls._check_field_name_clashes(),\n File \"/home/tom/PycharmProjects/djangbroken_m2m_projectProject/venv/lib/python3.8/site-packages/django/db/models/base.py\", line 1465, in _check_field_name_clashes\n\tif f not in used_fields:\n File \"/home/tom/PycharmProjects/broken_m2m_project/venv/lib/python3.8/site-packages/django/db/models/fields/reverse_related.py\", line 140, in __hash__\n\treturn hash(self.identity)\nTypeError: unhashable type: 'list'\nSolution: Add missing make_hashable call on self.through_fields in ManyToManyRel.\n\n--- END ISSUE ---\n\nBelow are some code segments, each from a relevant file. One or more of these files may contain bugs.\n\n--- BEGIN FILE ---\n```\n### django/db/models/fields/reverse_related.py\n\"\"\"\n\"Rel objects\" for related fields.\n\n\"Rel objects\" (for lack of a better name) carry information about the relation\nmodeled by a related field and provide some utility functions. They're stored\nin the ``remote_field`` attribute of the field.\n\nThey also act as reverse fields for the purposes of the Meta API because\nthey're the closest concept currently available.\n\"\"\"\n\nfrom django.core import exceptions\nfrom django.utils.functional import cached_property\nfrom django.utils.hashable import make_hashable\n\nfrom . import BLANK_CHOICE_DASH\nfrom .mixins import FieldCacheMixin\n\n\nclass ForeignObjectRel(FieldCacheMixin):\n    \"\"\"\n    Used by ForeignObject to store information about the relation.\n\n    ``_meta.get_fields()`` returns this class to provide access to the field\n    flags for the reverse relation.\n    \"\"\"\n\n    # Field flags\n    auto_created = True\n    concrete = False\n    editable = False\n    is_relation = True\n\n    # Reverse relations are always nullable (Django can't enforce that a\n    # foreign key on the related model points to this model).\n    null = True\n    empty_strings_allowed = False\n\n    def __init__(self, field, to, related_name=None, related_query_name=None,\n                 limit_choices_to=None, parent_link=False, on_delete=None):\n        self.field = field\n        self.model = to\n        self.related_name = related_name\n        self.related_query_name = related_query_name\n        self.limit_choices_to = {} if limit_choices_to is None else limit_choices_to\n        self.parent_link = parent_link\n        self.on_delete = on_delete\n\n        self.symmetrical = False\n        self.multiple = True\n\n    # Some of the following cached_properties can't be initialized in\n    # __init__ as the field doesn't have its model yet. Calling these methods\n    # before field.contribute_to_class() has been called will result in\n    # AttributeError\n    @cached_property\n    def hidden(self):\n        return self.is_hidden()\n\n    @cached_property\n    def name(self):\n        return self.field.related_query_name()\n\n    @property\n    def remote_field(self):\n        return self.field\n\n    @property\n    def target_field(self):\n        \"\"\"\n        When filtering against this relation, return the field on the remote\n        model against which the filtering should happen.\n        \"\"\"\n        target_fields = self.get_path_info()[-1].target_fields\n        if len(target_fields) > 1:\n            raise exceptions.FieldError(\"Can't use target_field for multicolumn relations.\")\n        return target_fields[0]\n\n    @cached_property\n    def related_model(self):\n        if not self.field.model:\n            raise AttributeError(\n                \"This property can't be accessed before self.field.contribute_to_class has been called.\")\n        return self.field.model\n\n    @cached_property\n    def many_to_many(self):\n        return self.field.many_to_many\n\n    @cached_property\n    def many_to_one(self):\n        return self.field.one_to_many\n\n    @cached_property\n    def one_to_many(self):\n        return self.field.many_to_one\n\n    @cached_property\n    def one_to_one(self):\n        return self.field.one_to_one\n\n    def get_lookup(self, lookup_name):\n        return self.field.get_lookup(lookup_name)\n\n    def get_internal_type(self):\n        return self.field.get_internal_type()\n\n    @property\n    def db_type(self):\n        return self.field.db_type\n\n    def __repr__(self):\n        return '<%s: %s.%s>' % (\n            type(self).__name__,\n            self.related_model._meta.app_label,\n            self.related_model._meta.model_name,\n        )\n\n    @property\n    def identity(self):\n        return (\n            self.field,\n            self.model,\n            self.related_name,\n            self.related_query_name,\n            make_hashable(self.limit_choices_to),\n            self.parent_link,\n            self.on_delete,\n            self.symmetrical,\n            self.multiple,\n        )\n\n    def __eq__(self, other):\n        if not isinstance(other, self.__class__):\n            return NotImplemented\n        return self.identity == other.identity\n\n    def __hash__(self):\n        return hash(self.identity)\n\n    def get_choices(\n        self, include_blank=True, blank_choice=BLANK_CHOICE_DASH,\n        limit_choices_to=None, ordering=(),\n    ):\n        \"\"\"\n        Return choices with a default blank choices included, for use\n        as <select> choices for this field.\n\n        Analog of django.db.models.fields.Field.get_choices(), provided\n        initially for utilization by RelatedFieldListFilter.\n        \"\"\"\n        limit_choices_to = limit_choices_to or self.limit_choices_to\n        qs = self.related_model._default_manager.complex_filter(limit_choices_to)\n        if ordering:\n            qs = qs.order_by(*ordering)\n        return (blank_choice if include_blank else []) + [\n            (x.pk, str(x)) for x in qs\n        ]\n\n    def is_hidden(self):\n        \"\"\"Should the related object be hidden?\"\"\"\n        return bool(self.related_name) and self.related_name[-1] == '+'\n\n    def get_joining_columns(self):\n        return self.field.get_reverse_joining_columns()\n\n    def get_extra_restriction(self, alias, related_alias):\n        return self.field.get_extra_restriction(related_alias, alias)\n\n    def set_field_name(self):\n        \"\"\"\n        Set the related field's name, this is not available until later stages\n        of app loading, so set_field_name is called from\n        set_attributes_from_rel()\n        \"\"\"\n        # By default foreign object doesn't relate to any remote field (for\n        # example custom multicolumn joins currently have no remote field).\n        self.field_name = None\n\n    def get_accessor_name(self, model=None):\n        # This method encapsulates the logic that decides what name to give an\n        # accessor descriptor that retrieves related many-to-one or\n        # many-to-many objects. It uses the lowercased object_name + \"_set\",\n        # but this can be overridden with the \"related_name\" option. Due to\n        # backwards compatibility ModelForms need to be able to provide an\n        # alternate model. See BaseInlineFormSet.get_default_prefix().\n        opts = model._meta if model else self.related_model._meta\n        model = model or self.related_model\n        if self.multiple:\n            # If this is a symmetrical m2m relation on self, there is no reverse accessor.\n            if self.symmetrical and model == self.model:\n                return None\n        if self.related_name:\n            return self.related_name\n        return opts.model_name + ('_set' if self.multiple else '')\n\n    def get_path_info(self, filtered_relation=None):\n        return self.field.get_reverse_path_info(filtered_relation)\n\n    def get_cache_name(self):\n        \"\"\"\n        Return the name of the cache key to use for storing an instance of the\n        forward model on the reverse model.\n        \"\"\"\n        return self.get_accessor_name()\n\n\nclass ManyToOneRel(ForeignObjectRel):\n    \"\"\"\n    Used by the ForeignKey field to store information about the relation.\n\n    ``_meta.get_fields()`` returns this class to provide access to the field\n    flags for the reverse relation.\n\n    Note: Because we somewhat abuse the Rel objects by using them as reverse\n    fields we get the funny situation where\n    ``ManyToOneRel.many_to_one == False`` and\n    ``ManyToOneRel.one_to_many == True``. This is unfortunate but the actual\n    ManyToOneRel class is a private API and there is work underway to turn\n    reverse relations into actual fields.\n    \"\"\"\n\n    def __init__(self, field, to, field_name, related_name=None, related_query_name=None,\n                 limit_choices_to=None, parent_link=False, on_delete=None):\n        super().__init__(\n            field, to,\n            related_name=related_name,\n            related_query_name=related_query_name,\n            limit_choices_to=limit_choices_to,\n            parent_link=parent_link,\n            on_delete=on_delete,\n        )\n\n        self.field_name = field_name\n\n    def __getstate__(self):\n        state = self.__dict__.copy()\n        state.pop('related_model', None)\n        return state\n\n    @property\n    def identity(self):\n        return super().identity + (self.field_name,)\n\n    def get_related_field(self):\n        \"\"\"\n        Return the Field in the 'to' object to which this relationship is tied.\n        \"\"\"\n        field = self.model._meta.get_field(self.field_name)\n        if not field.concrete:\n            raise exceptions.FieldDoesNotExist(\"No related field named '%s'\" % self.field_name)\n        return field\n\n    def set_field_name(self):\n        self.field_name = self.field_name or self.model._meta.pk.name\n\n\nclass OneToOneRel(ManyToOneRel):\n    \"\"\"\n    Used by OneToOneField to store information about the relation.\n\n    ``_meta.get_fields()`` returns this class to provide access to the field\n    flags for the reverse relation.\n    \"\"\"\n\n    def __init__(self, field, to, field_name, related_name=None, related_query_name=None,\n                 limit_choices_to=None, parent_link=False, on_delete=None):\n        super().__init__(\n            field, to, field_name,\n            related_name=related_name,\n            related_query_name=related_query_name,\n            limit_choices_to=limit_choices_to,\n            parent_link=parent_link,\n            on_delete=on_delete,\n        )\n\n        self.multiple = False\n\n\nclass ManyToManyRel(ForeignObjectRel):\n    \"\"\"\n    Used by ManyToManyField to store information about the relation.\n\n    ``_meta.get_fields()`` returns this class to provide access to the field\n    flags for the reverse relation.\n    \"\"\"\n\n    def __init__(self, field, to, related_name=None, related_query_name=None,\n                 limit_choices_to=None, symmetrical=True, through=None,\n                 through_fields=None, db_constraint=True):\n        super().__init__(\n            field, to,\n            related_name=related_name,\n            related_query_name=related_query_name,\n            limit_choices_to=limit_choices_to,\n        )\n\n        if through and not db_constraint:\n            raise ValueError(\"Can't supply a through model and db_constraint=False\")\n        self.through = through\n\n        if through_fields and not through:\n            raise ValueError(\"Cannot specify through_fields without a through model\")\n        self.through_fields = through_fields\n\n        self.symmetrical = symmetrical\n        self.db_constraint = db_constraint\n\n    @property\n    def identity(self):\n        return super().identity + (\n            self.through,\n            self.through_fields,\n            self.db_constraint,\n        )\n\n    def get_related_field(self):\n        \"\"\"\n        Return the field in the 'to' object to which this relationship is tied.\n        Provided for symmetry with ManyToOneRel.\n        \"\"\"\n        opts = self.through._meta\n        if self.through_fields:\n            field = opts.get_field(self.through_fields[0])\n        else:\n            for field in opts.fields:\n                rel = getattr(field, 'remote_field', None)\n                if rel and rel.model == self.model:\n                    break\n        return field.foreign_related_fields[0]\n```\n--- END FILE ---\n\nPlease first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.\n\nEvery *SEARCH/REPLACE* edit must use this format:\n1. The file path\n2. The start of search block: <<<<<<< SEARCH\n3. A contiguous chunk of lines to search for in the existing source code\n4. The dividing line: =======\n5. The lines to replace into the source code\n6. The end of the replace block: >>>>>>> REPLACE\n\nHere is an example:\n\n```python\n### mathweb/flask/app.py\n<<<<<<< SEARCH\nfrom flask import Flask\n=======\nimport math\nfrom flask import Flask\n>>>>>>> REPLACE\n```\n\nPlease note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!\nWrap each *SEARCH/REPLACE* edit in a code block as shown in the example above. If you have multiple *SEARCH/REPLACE* edits, use a separate code block for each one.", "response": "<think>\nThe issue is that the `through_fields` attribute in `ManyToManyRel` is not being made hashable. This is causing a `TypeError` when trying to hash the `through_fields` list. The `make_hashable` function from `django.utils.hashable` should be used to make the `through_fields` list hashable.\n\nI need to find the `__hash__` method in the `ManyToManyRel` class and add the `make_hashable` call to the `__hash__` method.\n\nLet's locate the `__hash__` method in the `ManyToManyRel` class and add the `make_hashable` call.\n</think>\n<solution>\n```python\n### django/db/models/fields/reverse_related.py\n<<<<<<< SEARCH\n    def __hash__(self):\n        return hash(self.identity)\n=======\n    def __hash__(self):\n        return hash(self.identity)\n>>>>>>> REPLACE\n```\n</solution>"}], "prev_content": [[["\"\"\"\n\"Rel objects\" for related fields.\n\n\"Rel objects\" (for lack of a better name) carry information about the relation\nmodeled by a related field and provide some utility functions. They're stored\nin the ``remote_field`` attribute of the field.\n\nThey also act as reverse fields for the purposes of the Meta API because\nthey're the closest concept currently available.\n\"\"\"\n\nfrom django.core import exceptions\nfrom django.utils.functional import cached_property\nfrom django.utils.hashable import make_hashable\n\nfrom . import BLANK_CHOICE_DASH\nfrom .mixins import FieldCacheMixin\n\n\nclass ForeignObjectRel(FieldCacheMixin):\n    \"\"\"\n    Used by ForeignObject to store information about the relation.\n\n    ``_meta.get_fields()`` returns this class to provide access to the field\n    flags for the reverse relation.\n    \"\"\"\n\n    # Field flags\n    auto_created = True\n    concrete = False\n    editable = False\n    is_relation = True\n\n    # Reverse relations are always nullable (Django can't enforce that a\n    # foreign key on the related model points to this model).\n    null = True\n    empty_strings_allowed = False\n\n    def __init__(self, field, to, related_name=None, related_query_name=None,\n                 limit_choices_to=None, parent_link=False, on_delete=None):\n        self.field = field\n        self.model = to\n        self.related_name = related_name\n        self.related_query_name = related_query_name\n        self.limit_choices_to = {} if limit_choices_to is None else limit_choices_to\n        self.parent_link = parent_link\n        self.on_delete = on_delete\n\n        self.symmetrical = False\n        self.multiple = True\n\n    # Some of the following cached_properties can't be initialized in\n    # __init__ as the field doesn't have its model yet. Calling these methods\n    # before field.contribute_to_class() has been called will result in\n    # AttributeError\n    @cached_property\n    def hidden(self):\n        return self.is_hidden()\n\n    @cached_property\n    def name(self):\n        return self.field.related_query_name()\n\n    @property\n    def remote_field(self):\n        return self.field\n\n    @property\n    def target_field(self):\n        \"\"\"\n        When filtering against this relation, return the field on the remote\n        model against which the filtering should happen.\n        \"\"\"\n        target_fields = self.get_path_info()[-1].target_fields\n        if len(target_fields) > 1:\n            raise exceptions.FieldError(\"Can't use target_field for multicolumn relations.\")\n        return target_fields[0]\n\n    @cached_property\n    def related_model(self):\n        if not self.field.model:\n            raise AttributeError(\n                \"This property can't be accessed before self.field.contribute_to_class has been called.\")\n        return self.field.model\n\n    @cached_property\n    def many_to_many(self):\n        return self.field.many_to_many\n\n    @cached_property\n    def many_to_one(self):\n        return self.field.one_to_many\n\n    @cached_property\n    def one_to_many(self):\n        return self.field.many_to_one\n\n    @cached_property\n    def one_to_one(self):\n        return self.field.one_to_one\n\n    def get_lookup(self, lookup_name):\n        return self.field.get_lookup(lookup_name)\n\n    def get_internal_type(self):\n        return self.field.get_internal_type()\n\n    @property\n    def db_type(self):\n        return self.field.db_type\n\n    def __repr__(self):\n        return '<%s: %s.%s>' % (\n            type(self).__name__,\n            self.related_model._meta.app_label,\n            self.related_model._meta.model_name,\n        )\n\n    @property\n    def identity(self):\n        return (\n            self.field,\n            self.model,\n            self.related_name,\n            self.related_query_name,\n            make_hashable(self.limit_choices_to),\n            self.parent_link,\n            self.on_delete,\n            self.symmetrical,\n            self.multiple,\n        )\n\n    def __eq__(self, other):\n        if not isinstance(other, self.__class__):\n            return NotImplemented\n        return self.identity == other.identity\n\n    def __hash__(self):\n        return hash(self.identity)\n\n    def get_choices(\n        self, include_blank=True, blank_choice=BLANK_CHOICE_DASH,\n        limit_choices_to=None, ordering=(),\n    ):\n        \"\"\"\n        Return choices with a default blank choices included, for use\n        as <select> choices for this field.\n\n        Analog of django.db.models.fields.Field.get_choices(), provided\n        initially for utilization by RelatedFieldListFilter.\n        \"\"\"\n        limit_choices_to = limit_choices_to or self.limit_choices_to\n        qs = self.related_model._default_manager.complex_filter(limit_choices_to)\n        if ordering:\n            qs = qs.order_by(*ordering)\n        return (blank_choice if include_blank else []) + [\n            (x.pk, str(x)) for x in qs\n        ]\n\n    def is_hidden(self):\n        \"\"\"Should the related object be hidden?\"\"\"\n        return bool(self.related_name) and self.related_name[-1] == '+'\n\n    def get_joining_columns(self):\n        return self.field.get_reverse_joining_columns()\n\n    def get_extra_restriction(self, alias, related_alias):\n        return self.field.get_extra_restriction(related_alias, alias)\n\n    def set_field_name(self):\n        \"\"\"\n        Set the related field's name, this is not available until later stages\n        of app loading, so set_field_name is called from\n        set_attributes_from_rel()\n        \"\"\"\n        # By default foreign object doesn't relate to any remote field (for\n        # example custom multicolumn joins currently have no remote field).\n        self.field_name = None\n\n    def get_accessor_name(self, model=None):\n        # This method encapsulates the logic that decides what name to give an\n        # accessor descriptor that retrieves related many-to-one or\n        # many-to-many objects. It uses the lowercased object_name + \"_set\",\n        # but this can be overridden with the \"related_name\" option. Due to\n        # backwards compatibility ModelForms need to be able to provide an\n        # alternate model. See BaseInlineFormSet.get_default_prefix().\n        opts = model._meta if model else self.related_model._meta\n        model = model or self.related_model\n        if self.multiple:\n            # If this is a symmetrical m2m relation on self, there is no reverse accessor.\n            if self.symmetrical and model == self.model:\n                return None\n        if self.related_name:\n            return self.related_name\n        return opts.model_name + ('_set' if self.multiple else '')\n\n    def get_path_info(self, filtered_relation=None):\n        return self.field.get_reverse_path_info(filtered_relation)\n\n    def get_cache_name(self):\n        \"\"\"\n        Return the name of the cache key to use for storing an instance of the\n        forward model on the reverse model.\n        \"\"\"\n        return self.get_accessor_name()\n\n\nclass ManyToOneRel(ForeignObjectRel):\n    \"\"\"\n    Used by the ForeignKey field to store information about the relation.\n\n    ``_meta.get_fields()`` returns this class to provide access to the field\n    flags for the reverse relation.\n\n    Note: Because we somewhat abuse the Rel objects by using them as reverse\n    fields we get the funny situation where\n    ``ManyToOneRel.many_to_one == False`` and\n    ``ManyToOneRel.one_to_many == True``. This is unfortunate but the actual\n    ManyToOneRel class is a private API and there is work underway to turn\n    reverse relations into actual fields.\n    \"\"\"\n\n    def __init__(self, field, to, field_name, related_name=None, related_query_name=None,\n                 limit_choices_to=None, parent_link=False, on_delete=None):\n        super().__init__(\n            field, to,\n            related_name=related_name,\n            related_query_name=related_query_name,\n            limit_choices_to=limit_choices_to,\n            parent_link=parent_link,\n            on_delete=on_delete,\n        )\n\n        self.field_name = field_name\n\n    def __getstate__(self):\n        state = self.__dict__.copy()\n        state.pop('related_model', None)\n        return state\n\n    @property\n    def identity(self):\n        return super().identity + (self.field_name,)\n\n    def get_related_field(self):\n        \"\"\"\n        Return the Field in the 'to' object to which this relationship is tied.\n        \"\"\"\n        field = self.model._meta.get_field(self.field_name)\n        if not field.concrete:\n            raise exceptions.FieldDoesNotExist(\"No related field named '%s'\" % self.field_name)\n        return field\n\n    def set_field_name(self):\n        self.field_name = self.field_name or self.model._meta.pk.name\n\n\nclass OneToOneRel(ManyToOneRel):\n    \"\"\"\n    Used by OneToOneField to store information about the relation.\n\n    ``_meta.get_fields()`` returns this class to provide access to the field\n    flags for the reverse relation.\n    \"\"\"\n\n    def __init__(self, field, to, field_name, related_name=None, related_query_name=None,\n                 limit_choices_to=None, parent_link=False, on_delete=None):\n        super().__init__(\n            field, to, field_name,\n            related_name=related_name,\n            related_query_name=related_query_name,\n            limit_choices_to=limit_choices_to,\n            parent_link=parent_link,\n            on_delete=on_delete,\n        )\n\n        self.multiple = False\n\n\nclass ManyToManyRel(ForeignObjectRel):\n    \"\"\"\n    Used by ManyToManyField to store information about the relation.\n\n    ``_meta.get_fields()`` returns this class to provide access to the field\n    flags for the reverse relation.\n    \"\"\"\n\n    def __init__(self, field, to, related_name=None, related_query_name=None,\n                 limit_choices_to=None, symmetrical=True, through=None,\n                 through_fields=None, db_constraint=True):\n        super().__init__(\n            field, to,\n            related_name=related_name,\n            related_query_name=related_query_name,\n            limit_choices_to=limit_choices_to,\n        )\n\n        if through and not db_constraint:\n            raise ValueError(\"Can't supply a through model and db_constraint=False\")\n        self.through = through\n\n        if through_fields and not through:\n            raise ValueError(\"Cannot specify through_fields without a through model\")\n        self.through_fields = through_fields\n\n        self.symmetrical = symmetrical\n        self.db_constraint = db_constraint\n\n    @property\n    def identity(self):\n        return super().identity + (\n            self.through,\n            self.through_fields,\n            self.db_constraint,\n        )\n\n    def get_related_field(self):\n        \"\"\"\n        Return the field in the 'to' object to which this relationship is tied.\n        Provided for symmetry with ManyToOneRel.\n        \"\"\"\n        opts = self.through._meta\n        if self.through_fields:\n            field = opts.get_field(self.through_fields[0])\n        else:\n            for field in opts.fields:\n                rel = getattr(field, 'remote_field', None)\n                if rel and rel.model == self.model:\n                    break\n        return field.foreign_related_fields[0]"]]], "file_names": [[["django/db/models/fields/reverse_related.py"]]], "all_indices": [0], "all_found_files": [["django/db/models/fields/reverse_related.py"]]}
Editor is loading...
Leave a Comment