Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AssertionError on model_field with m2m #323

Closed
lerela opened this issue Mar 2, 2021 · 3 comments
Closed

AssertionError on model_field with m2m #323

lerela opened this issue Mar 2, 2021 · 3 comments
Labels
bug Something isn't working fix confirmation pending issue has been fixed and confirmation from issue reporter is pending

Comments

@lerela
Copy link

lerela commented Mar 2, 2021

Describe the bug
Sorry @tfranzel for spamming the bug reports! This looks like a regression in 0.13.2 (also in master).

If I have a simple m2m relationship:

class Reltd(models.Model):
    test = models.CharField(max_length=50)
    testm = models.ManyToManyField("TestModel")

class TestModel(models.Model):
    test_field = models.CharField(max_length=50)

and I try to serialize the m2m relationship (without any django-filter involved):

class TestSerializer(serializers.ModelSerializer):
    mult = serializers.PrimaryKeyRelatedField(
        many=True, read_only=True, source="reltd_set"
    )

    class Meta:
        model = TestModel
        fields = ['id', 'mult']

class TestViewSet(viewsets.ModelViewSet):
    queryset = TestModel.objects.all()
    serializer_class = TestSerializer
           

Then I'm getting a strange warning and an AssertionError:

Warning #1: could not resolve field on model <class 'test_spectacular.models.TestModel'> with path "reltd_set". this is likely a custom field that does some unknown magic. maybe consider annotating the field/property? defaulting to "string". (Exception: TestModel has no field named 'reltd_set')
Traceback (most recent call last):
  File "./manage.py", line 22, in <module>
    main()
  File "./manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "test_spectacular/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "test_spectacular/venv/lib/python3.8/site-packages/django/core/management/__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "test_spectacular/venv/lib/python3.8/site-packages/django/core/management/base.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "test_spectacular/venv/lib/python3.8/site-packages/django/core/management/base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/management/commands/spectacular.py", line 50, in handle
    schema = generator.get_schema(request=None, public=True)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/generators.py", line 219, in get_schema
    paths=self.parse(request, public),
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/generators.py", line 196, in parse
    operation = view.schema.get_operation(path, path_regex, method, self.registry)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 83, in get_operation
    operation['responses'] = self._get_response_bodies()
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 969, in _get_response_bodies
    return {'200': self._get_response_for_code(response_serializers, '200')}
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 1007, in _get_response_for_code
    component = self.resolve_serializer(serializer, 'response')
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 1146, in resolve_serializer
    component.schema = self._map_serializer(serializer, direction)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 669, in _map_serializer
    schema = self._map_basic_serializer(serializer, direction)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 736, in _map_basic_serializer
    schema = self._map_serializer_field(field, direction)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 488, in _map_serializer_field
    schema = self._map_serializer_field(field.child_relation, direction)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 516, in _map_serializer_field
    schema = self._map_model_field(model_field, direction)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 387, in _map_model_field
    assert isinstance(model_field, models.Field)
AssertionError

However this works if I do not use read_only=True and provide a queryset.

Also, this works as expected with 0.13.1. Error with 0.13.2 is different from master (django.core.exceptions.FieldDoesNotExist: TestModel has no field named 'reltd_set').

@tfranzel tfranzel added the bug Something isn't working label Mar 2, 2021
@tfranzel
Copy link
Owner

tfranzel commented Mar 2, 2021

@lerela all good, i'm glad someone is testing this before i release 0.14.0.

in 0.13.1 there was a bug here that threw no errors, but only produced a correct schema by accident.
in 0.13.2 there was a bugfix that corrected this but broke relations. (#274)
on master i attempted to fix the broken relation while retaining the correct solution (df6ef05)

i guess we are not done yet. these 10 lines are a whack-a-mole.

@tfranzel
Copy link
Owner

tfranzel commented Mar 5, 2021

fixed several inconsistencies that lead to problems. this includes 2 unreported "bugs" that hid behind this issue. it basically comes down to unhandled DRF internal mechanics and an under-specified interface to follow_field_source.

its a hefty change, so please check for differences

@tfranzel tfranzel added the fix confirmation pending issue has been fixed and confirmation from issue reporter is pending label Mar 5, 2021
@lerela
Copy link
Author

lerela commented Mar 5, 2021

This seems to fix the issue and I have not seen side effects − but my use cases are not so intricate. Well done 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working fix confirmation pending issue has been fixed and confirmation from issue reporter is pending
Projects
None yet
Development

No branches or pull requests

2 participants