profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/chaosk/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Krzysztof Socha chaosk Sherpany Poznań, Poland https://ecksd.ee

chaosk/brabeion 1

a badges app for Django

chaosk/django-activity-stream 1

Generate generic activity streams from the actions on your site. Users can follow any actor's activities for personalized streams.

chaosk/django-faq 1

A Frequently Asked Question (FAQ) management application built with Django.

chaosk/aldryn-django-cms 0

An opinionated Django CMS setup bundled as an Aldryn Addon

chaosk/aldryn-events 0

An events publishing application for Aldryn and django CMS – part of the Essential Addons.

chaosk/aldryn-faq 0

Add questions and answers for Aldryn and django CMS – part of the Essential Addons.

issue commenttfranzel/drf-spectacular

Show scopes per view in swagger UI

so you have the correct settings as far as i can tell and also redoc is showing the scopes as expected, then this looks like a feature request/bug for Swagger UI https://github.com/swagger-api/swagger-ui . we only use the swagger UI without modification.

i'm not aware on how to make swagger UI show the required scopes.

krzysieqq

comment created time in 3 hours

issue commenttfranzel/drf-spectacular

function based views @api_view and request.POST (form based) parameters

hi,

you cannot explicitly replace request body object, but you can get very close with this (1&2):

@extend_schema(
    examples=[
        OpenApiExample('Serializer C Example RO',value={"field": 111})
    ],
    responses={
        (200, 'application/json'): OpenApiTypes.OBJECT,  # or anything else
    }
)

you can also manually specify a schema. there several ways to override the response and raw dict is one of them. you have complete freedom there (2):

https://github.com/tfranzel/drf-spectacular/blob/6f12e8d9310ca2aaa833a1167d0d5f7795e2d635/tests/test_extend_schema.py#L160-L186

of course the more manual you go, you alos loose a lot of benefits. i hope this answers your question

axilaris

comment created time in 3 hours

issue commenttfranzel/drf-spectacular

function based views @api_view and request.POST (form based) parameters

Hello,

I have been digging quite a bit on how to provide a minimal POST json data API with specs and hitting the same question (despite all the great documentation and content, sorry if it is obvious).

Is there a way to extend_schema with a Request Body Object? (that way we could provide the schema of the body via the 'content' similarly to the examples in https://swagger.io/specification/#request-body-object. Or I am mistaken and there is no way to actually provide a schema for the request body)

Or, by design should the schema of the json body be defined by a serializer and provided to the extend_schema? https://www.django-rest-framework.org/api-guide/serializers/#declaring-serializers And if yes, is there a lighter weight way of providing the schema instead of Python? (e.g. via text)

A compromise might also be to drop trying to type the json body and provide an OpenApiExample with a json string instead.

  1. I would volunteer to add the recommended solution to the FAQ https://drf-spectacular.readthedocs.io/en/latest/faq.html ;)

I saw nowadays many API not using parameters anymore but json body instead, e.g. Twitter API v2 is using a json body in POST (e.g. following, while v1 was using header parameters (e.g. post tweet).

Thanks!

axilaris

comment created time in 8 hours

issue commenttfranzel/drf-spectacular

Show scopes per view in swagger UI

I know thath schema is the same, so why swagger doesn't show me oauth2 scope when redoc shows. Screens bellow image image

I've defined scopes before use. When I import in shell from oauth2_provider.settings import oauth2_settings oauth2_settings.SCOPES shows scopes defined in settings:

{'read': 'Reading scope',
 'write': 'Writing scope',
 'operator': 'operator'}

my spectacular settings in admin:

SPECTACULAR_SETTINGS = {
    "VERSION": API_VERSION,
    "SERVE_PUBLIC": True,
    "SERVE_INCLUDE_SCHEMA": False,
    "CAMELIZE_NAMES": True,
    "OAUTH2_FLOWS": ["password"],
    # 'OAUTH2_AUTHORIZATION_URL': f"{SERVER_NAME}/users/auth/authorize/",
    "OAUTH2_TOKEN_URL": f"{SERVER_NAME}/users/auth/token/",
    "OAUTH2_REFRESH_URL": f"{SERVER_NAME}/users/auth/token/",
    # "OAUTH2_SCOPES": ['read', 'write', 'operator', 'animator', 'supplier'], # OAUTH2_PROVIDER['SCOPES'],
    "SWAGGER_UI_SETTINGS": {
        "deepLinking": True,
        "displayOperationId": True,
        "showExtensions": True,
        "showCommonExtensions": True,
        "persistAuthorization": True,
    },
    # Split components into request and response parts where appropriate
    'COMPONENT_SPLIT_REQUEST': True,
    # Aid client generator targets that have trouble with read-only properties.
    # 'COMPONENT_NO_READ_ONLY_REQUIRED': False,
    # Create separate components for PATCH endpoints (without required list)
    'COMPONENT_SPLIT_PATCH': False,
    # Adds "blank" and "null" enum choices where appropriate. disable on client generation issues
    # 'ENUM_ADD_EXPLICIT_BLANK_NULL_CHOICE': True,
}

Spectacular version 0.13.2

krzysieqq

comment created time in 21 hours

issue closedtfranzel/drf-spectacular

function based views @api_view and request.POST (form based) parameters

I am going through a migration process from 1.11 to 3.1.5. And I found out drf-spectacular may provide a way to do this API migration.

I'ved got the question posted here in detail: https://stackoverflow.com/questions/65918969/django-rest-framework-custom-post-url-endpoints-with-defined-parameter-request?noredirect=1#comment116622930_65918969

Basically, I'd like to find a way to create REST API using drf-spectacular that is equivalent to this:

url.py url(r'^api/test_token$', api.test_token, name='test_token'),

api.py

@api_view(['POST'])
def test_token(request):
    # ----- YAML below for Swagger -----
    """
    description: test_token
    parameters:
      - name: token
        type: string
        required: true
        location: form       
    """
    token = request.POST['token']

    return Response("test_token success", status=status.HTTP_200_OK)

In the documentation, there is mentioned how to handle @api_view https://drf-spectacular.readthedocs.io/en/latest/customization.html#

Many libraries use @api_view or APIView instead of ViewSet or GenericAPIView. In those cases, introspection has very little to work with. The purpose of this extension is to augment or switch out the encountered view (only for schema generation). Simply extending the discovered class class Fixed(self.target_class) with a queryset or serializer_class attribute will often solve most issues.

I am not sure how its done, could someone give some guidance how to get this to work ? Thanks.

closed time in a day

axilaris

issue commenttfranzel/drf-spectacular

Show scopes per view in swagger UI

hi, i suppose this happens because scopes are listed in the views, but not declared in the security section. currently, there is no collection happening here. only pre-defined values are used.

by setting oauth2_provider.settings.oauth2_settings.SCOPES you can pre-populate the security section and scopes should show up as expected.

fyi: the schema is identical for redoc and swagger views.

krzysieqq

comment created time in a day

Pull request review commenttfranzel/drf-spectacular

Fixed issue #314 - include information about view/serializer in warnings

 def resolve_serializer(self, serializer, direction) -> ResolvedComponent:             f'https://github.com/tfranzel/drf-spectacular/issues '         )         serializer = force_instance(serializer)--        component = ResolvedComponent(-            name=self._get_serializer_name(serializer, direction),-            type=ResolvedComponent.SCHEMA,-            object=serializer,-        )-        if component in self.registry:-            return self.registry[component]  # return component with schema--        self.registry.register(component)-        component.schema = self._map_serializer(serializer, direction)-        # 4 cases:-        #   1. polymorphic container component -> use-        #   2. concrete component with properties -> use-        #   3. concrete component without properties -> prob. transactional so discard-        #   4. explicit list component -> demultiplexed at usage location so discard-        keep_component = (-            any(nest_tag in component.schema for nest_tag in ['oneOf', 'allOf', 'anyOf'])-            or component.schema.get('properties', {})-        )-        if not keep_component:-            del self.registry[component]-            return ResolvedComponent(None, None)  # sentinel-        return component+        with add_trace_message(serializer.__class__.__name__):

my OCD complains here due to increasing indent and obfuscating the git blame, but what can you do if that is the proper thing to do.

spookylukey

comment created time in a day

Pull request review commenttfranzel/drf-spectacular

Fixed issue #314 - include information about view/serializer in warnings

 def generate_schema(route, viewset=None, view=None, view_function=None):     from rest_framework import routers     from rest_framework.viewsets import ViewSetMixin +    from drf_spectacular.drainage import add_trace_message     from drf_spectacular.generators import SchemaGenerator      patterns = []+    trace_message = ''     if viewset:         assert issubclass(viewset, ViewSetMixin)         router = routers.SimpleRouter()         router.register(route, viewset, basename=route)         patterns = router.urls+        trace_message = viewset.__name__     elif view:         patterns = [path(route, view.as_view())]+        trace_message = view.__name__     elif view_function:         patterns = [path(route, view_function)]+        trace_message = view_function.__name__ -    generator = SchemaGenerator(patterns=patterns)-    schema = generator.get_schema(request=None, public=True)-    validate_schema(schema)  # make sure generated schemas are always valid-    return schema+    with add_trace_message(trace_message):

usage of the context manager and manual traces can be dropped in favor of the other solution. this also keeps the tests closer to reality

spookylukey

comment created time in a day

Pull request review commenttfranzel/drf-spectacular

Fixed issue #314 - include information about view/serializer in warnings

 def _resolve_path_parameters(self, variables):                         description = get_pk_description(model, model_field)                 except django_exceptions.FieldDoesNotExist:                     warn(-                        f'could not derive type of path parameter "{variable}" because '-                        f'model "{model}" did contain no such field. consider annotating '-                        f'parameter with @extend_schema. defaulting to "string".'+                        f'{self.view.__class__.__name__}: could not derive type of path '

prefix can be dropped again (see other comment)

spookylukey

comment created time in a day

Pull request review commenttfranzel/drf-spectacular

Fixed issue #314 - include information about view/serializer in warnings

 def get_view_model(view):         return view.get_queryset().model     except Exception as exc:         warn(-            f'failed to obtain model through view\'s queryset due to raised exception. '-            f'prevent this either by setting "queryset = Model.objects.none()" on the view, '-            f'having an empty fallback in get_queryset() or by using @extend_schema. '+            f'{view.__class__.__name__}: failed to obtain model through view\'s queryset due to '

prefix can be dropped again (see other comment)

spookylukey

comment created time in a day

Pull request review commenttfranzel/drf-spectacular

Fixed issue #314 - include information about view/serializer in warnings

 def _get_serializer(self):                     return view.serializer_class                 else:                     error(-                        f'Unable to guess serializer for {view.__class__.__name__}. This is graceful '+                        f'{view.__class__.__name__}: unable to guess serializer. This is graceful '

prefix can be dropped again (see other comment)

spookylukey

comment created time in a day

Pull request review commenttfranzel/drf-spectacular

Fixed issue #314 - include information about view/serializer in warnings

 def _resolve_path_parameters(self, variables):                 schema = resolved_parameter['schema']             elif get_view_model(self.view) is None:                 warn(-                    f'could not derive type of path parameter "{variable}" because because it '-                    f'is untyped and obtaining queryset from {self.view.__class__} failed. '-                    f'consider adding a type to the path (e.g. <int:{variable}>) or annotating '-                    f'the parameter type with @extend_schema. defaulting to "string".'+                    f'{self.view.__class__.__name__}: could not derive type of path parameter '

prefix can be dropped again (see other comment)

spookylukey

comment created time in a day

issue openedtfranzel/drf-spectacular

Show scopes per view in swagger UI

Hi, I need to show in swagger oauth2 scope per view. In my view I declarated required_scopes = ['custom_scope'], but In Swagger, I don't see any information about it.

Redoc correctly showing me a line with AUTHORIZATIONS: oauth2 (custom_scope)

Can swagger or redoc views shows defined class permission fg. permission_classes = [IsModerator] or I need to use scope for showing that in swagger/redoc UI?

created time in a day

Pull request review commenttfranzel/drf-spectacular

Fixed issue #314 - include information about view/serializer in warnings

 def _resolve_path_parameters(self, variables):                 schema = resolved_parameter['schema']             elif get_view_model(self.view) is None:                 warn(-                    f'could not derive type of path parameter "{variable}" because because it '-                    f'is untyped and obtaining queryset from {self.view.__class__} failed. '-                    f'consider adding a type to the path (e.g. <int:{variable}>) or annotating '-                    f'the parameter type with @extend_schema. defaulting to "string".'+                    f'{self.view.__class__.__name__}: could not derive type of path parameter '

prefix can be dropped again (see other comment)

spookylukey

comment created time in a day

issue commenttfranzel/drf-spectacular

AssertionError on model_field with m2m

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

lerela

comment created time in 2 days

issue commenttfranzel/drf-spectacular

AssertionError on model_field with m2m

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

lerela

comment created time in 2 days

push eventtfranzel/drf-spectacular

T. Franzel

commit sha 6f12e8d9310ca2aaa833a1167d0d5f7795e2d635

bugfix forward/reverse model traversal #323

view details

push time in 2 days

issue commenttfranzel/drf-spectacular

Ability to use PolymorphicProxySerializer in extend_schema_field

@tfranzel I tried the fix on my project - it works like a charm! Thank you!

dkrukouski

comment created time in 3 days

issue commenttfranzel/drf-spectacular

Missing swagger_fake_view attribute

This is just wonderful, thank you very much!

d2718nis

comment created time in 3 days

push eventtfranzel/drf-spectacular

T. Franzel

commit sha d8c416af7127cf9e5d5a9b6fc4cb3d08b6a2cbf1

fix nested serializer detection & smarter metadata extraction #319

view details

push time in 4 days

issue commenttfranzel/drf-spectacular

Missing swagger_fake_view attribute

Hi! i was hesitant to do this before as it felt like a cop-out, but i realize now that sometimes you are simply stuck there and all other option are worse. i mean we do generate mock requests with an anon user, but apparently that is not enough the cover all cases.

so added the feature finally. :rocket:

d2718nis

comment created time in 5 days

push eventtfranzel/drf-spectacular

T. Franzel

commit sha 8c48c49125e6c802bb0707ee8aff50c7abb18760

add drf-yasg compatibility feature 'swagger_fake_view' #321

view details

push time in 5 days

issue closedtfranzel/drf-spectacular

Wrong django-filter types

django-filter fields can have a different type from the underlying model field they operate against. drf-spectacular incorrectly makes the schema type match the model field instead of the filter.

Take the following filter for example:

class UserFilter(django_filters.FilterSet):
    has_logged_in = django_filters.BooleanFilter(field_name='last_login', lookup_expr='isnull')

last_login is a datetime model field but the filter field is boolean. Currently the schema has the type for has_logged_in as datetime which is incorrect.

The reason, I believe, is this part of the code: https://github.com/tfranzel/drf-spectacular/blob/243445f719e574ef8b292428070f93d62e647ddd/drf_spectacular/contrib/django_filters.py#L57-L60

The model field type is preferred over the actual filter type.

I don't understand why the model field is even used here. Is it to get additional information? Since the filter itself has a clear type I don't think the mode field type is ever relevant.

closed time in 5 days

markopy

issue closedtfranzel/drf-spectacular

no way to specify parser_classes for views in a viewset

Describe the bug I've got a DocumentViewset that's used to both upload and retrieve files. For the create and update actions, the only sensible parser is MultiPartParser, but all other actions should accept json. So I don't want to set parser_classes on the whole viewset and it looks like there is no such thing as get_parser_classes akin to what can be used for serializers in drf.

There is an annotation in drf that can be used for function based views to override parser_classes, but that won't work for single views in viewsets afaict.

Maybe in this case it would make sense to have an override for parser_classes in extend_schema just like for request/response serializers?

An example:

class DocumentViewSet(viewsets.ModelViewSet):
    permission_classes = (DocumentPermission,)
    queryset = Document.objects.all()
    
    def get_parser_classes(self):
        if self.action == 'create':
            return [MultiPartParser]
        else:
            return [JSONParser]
        
    def get_serializer_class(self):
        if self.action in ('create', 'partial_update', 'update'):
            return DocumentEditSerializer
        elif self.action == 'retrieve':
            return DocumentDetailSerializer
        else:
            return DocumentListSerializer

    def perform_create(self, serializer):
        kwargs = {
            'creator': self.request.user,
            'company': self.request.user.company
        }

        serializer.save(**kwargs)

The resulting schema for the above includes all three of the default parsers:

   operationId: documents_create
      description: ''
      tags:
      - documents
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DocumentEditRequest'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/DocumentEditRequest'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/DocumentEditRequest'

closed time in 5 days

NANASHI0X74

issue commenttfranzel/drf-spectacular

no way to specify parser_classes for views in a viewset

looks like the schema generated is correct now- I added the following annotation to the class:

@extend_schema_view(
    create=extend_schema(request={'multipart/form-data': DocumentEditSerializer})
)
class DocumentViewSet(viewsets.ModelViewSet):

And the schema generated is:

  /documents/
    post:         
      operationId: documents_create
      description: ''
      tags:                                              
      - documents        
      requestBody:  
        content:
          multipart/form-data:         
            schema:  
              $ref: '#/components/schemas/DocumentEditRequest'

'#/components/schemas/DocumentEditRequest':

    DocumentEditRequest:                                      
      type: object                          
      properties:                                   
        creator:                                              
          type: integer       
          nullable: true                                      
        company:                                              
          type: integer
          nullable: true                                      
        name:                 
          type: string
          maxLength: 255                                      
        description:                   
          type: string       
          nullable: true   
          maxLength: 255                                 
        filepath:                                          
          type: string   
          format: binary                   
          nullable: true           
NANASHI0X74

comment created time in 5 days

issue commenttfranzel/drf-spectacular

AssertionError on model_field with m2m

@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.

lerela

comment created time in 5 days

issue openedtfranzel/drf-spectacular

AssertionError on model_field with m2m

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').

created time in 5 days

issue closedtfranzel/drf-spectacular

'NoneType' object has no attribute 'Meta' with django-filter and through m2m model

Describe the bug Using django-filter backend with a through relationship fails with 0.13.2. Not sure that's the exact issue but this does not happen without the "through".

To Reproduce Models:

class Reltd(models.Model):
    test = models.CharField(max_length=50)

class TestModel(models.Model):
    reltd = models.ManyToManyField(Reltd, through="TestModelReltd")

class TestModelReltd(models.Model):
    tm = models.ForeignKey(TestModel, on_delete=models.PROTECT)
    rl = models.ForeignKey(Reltd, on_delete=models.PROTECT)

Views:

class MyFilter(filters.FilterSet):
    reltd = filters.ModelMultipleChoiceFilter(
        field_name="reltd", label="reltd"
    )

    class Meta:
        model = TestModel
        fields = ["reltd"]

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

    filter_backends = [
        filters.DjangoFilterBackend,
    ]
    filter_class = MyFilter 

Error:

  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 61, in get_operation
    parameters = self._get_parameters()
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 190, in _get_parameters
    **dict_helper(self._get_filter_parameters()),
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 365, in _get_filter_parameters
    parameters += filter_extension.get_schema_operation_parameters(self)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/contrib/django_filters.py", line 43, in get_schema_operation_parameters
    result += self.resolve_filter_field(
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/contrib/django_filters.py", line 95, in resolve_filter_field
    schema = auto_schema._map_model_field(model_field, direction=None)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 407, in _map_model_field
    return self._map_serializer_field(field, direction)
  File "test_spectacular/venv/lib/python3.8/site-packages/drf_spectacular/openapi.py", line 480, 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 494, in _map_serializer_field
    model = field.parent.parent.Meta.model
AttributeError: 'NoneType' object has no attribute 'Meta'

This happens in 0.12, 0.13.0, 0.13.1 & 0.13.2 as field.parent.parent seems to be None in this case.

Expected behavior No issue.

closed time in 5 days

lerela

issue commenttfranzel/drf-spectacular

'NoneType' object has no attribute 'Meta' with django-filter and through m2m model

That makes total sense. Sane fallbacks are totally fine! Thanks again for all your great work (this solves that issue).

lerela

comment created time in 5 days

issue commenttfranzel/drf-spectacular

'NoneType' object has no attribute 'Meta' with django-filter and through m2m model

@lerela indeed this was a very special case that surfaced nowhere else. i far exceeded the time i have for django-filter because the library keeps on generating more edge cases. i opted to catch errors from now on to not break schema generation because of django-filter.

lerela

comment created time in 5 days