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

Can't extract type from GeneratedField #1166

Open
ckarli opened this issue Feb 6, 2024 · 1 comment
Open

Can't extract type from GeneratedField #1166

ckarli opened this issue Feb 6, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@ckarli
Copy link

ckarli commented Feb 6, 2024

Describe the bug
Types can't be extracted from newly added GeneratedField. Field must be added explicitly to the serializer with the correct type as defined in the "output_field". Otherwise it gives the error below.

backend-1 | Traceback (most recent call last):
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/contrib/staticfiles/handlers.py", line 80, in call
backend-1 | return self.application(environ, start_response)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/sentry_sdk/integrations/django/init.py", line 165, in sentry_patched_wsgi_handler
backend-1 | return SentryWsgiMiddleware(bound_old_app, use_x_forwarded_for)(
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/sentry_sdk/integrations/wsgi.py", line 115, in call
backend-1 | reraise(*_capture_exception(hub))
backend-1 | File "/usr/local/lib/python3.12/site-packages/sentry_sdk/_compat.py", line 127, in reraise
backend-1 | raise value
backend-1 | File "/usr/local/lib/python3.12/site-packages/sentry_sdk/integrations/wsgi.py", line 108, in call
backend-1 | rv = self.app(
backend-1 | ^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/core/handlers/wsgi.py", line 124, in call
backend-1 | response = self.get_response(request)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/sentry_sdk/integrations/django/init.py", line 460, in sentry_patched_get_response
backend-1 | rv = old_get_response(self, request)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 140, in get_response
backend-1 | response = self._middleware_chain(request)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 57, in inner
backend-1 | response = response_for_exception(request, exc)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 140, in response_for_exception
backend-1 | response = handle_uncaught_exception(
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 181, in handle_uncaught_exception
backend-1 | return debug.technical_500_response(request, *exc_info)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django_extensions/management/technical_response.py", line 40, in null_technical_500_response
backend-1 | raise exc_value.with_traceback(tb)
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
backend-1 | response = get_response(request)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
backend-1 | response = wrapped_callback(request, *callback_args, **callback_kwargs)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py", line 84, in sentry_wrapped_callback
backend-1 | return callback(request, *args, **kwargs)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
backend-1 | return view_func(request, *args, **kwargs)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/django/views/generic/base.py", line 104, in view
backend-1 | return self.dispatch(request, *args, **kwargs)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 509, in dispatch
backend-1 | response = self.handle_exception(exc)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 469, in handle_exception
backend-1 | self.raise_uncaught_exception(exc)
backend-1 | File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
backend-1 | raise exc
backend-1 | File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 506, in dispatch
backend-1 | response = handler(request, *args, **kwargs)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/views.py", line 84, in get
backend-1 | return self._get_schema_response(request)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/views.py", line 92, in _get_schema_response
backend-1 | data=generator.get_schema(request=request, public=self.serve_public),
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/generators.py", line 281, in get_schema
backend-1 | paths=self.parse(request, public),
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/generators.py", line 252, in parse
backend-1 | operation = view.schema.get_operation(
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/openapi.py", line 99, in get_operation
backend-1 | request_body = self._get_request_body()
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/openapi.py", line 1295, in _get_request_body
backend-1 | schema, partial_request_body_required = self._get_request_for_media_type(serializer, direction)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/openapi.py", line 1327, in _get_request_for_media_type
backend-1 | component = self.resolve_serializer(serializer, direction)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/openapi.py", line 1605, in resolve_serializer
backend-1 | component.schema = self._map_serializer(serializer, direction, bypass_extensions)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/openapi.py", line 927, in _map_serializer
backend-1 | schema = self._map_basic_serializer(serializer, direction)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/openapi.py", line 1026, in _map_basic_serializer
backend-1 | schema = self._map_serializer_field(field, direction)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/openapi.py", line 904, in _map_serializer_field
backend-1 | schema = self._map_model_field(field.model_field, direction)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | File "/usr/local/lib/python3.12/site-packages/drf_spectacular/openapi.py", line 612, in _map_model_field
backend-1 | return self._map_serializer_field(field_cls(), direction)
backend-1 | ^^^^^^^^^^^^^^^^^^^^^^^
backend-1 | TypeError: DecimalField.init() missing 2 required positional arguments: 'max_digits' and 'decimal_places'

To Reproduce

class Invoice(models.Model):
    #...omitting amount_from and xrate_from fields
    amount= models.GeneratedField(
        expression=F("amount_from") * F("xrate_from"),
        output_field=models.DecimalField(max_digits=19, decimal_places=4),
        db_persist=True,
    )

Use GeneratedField in a model, and use this model in a ModelSerializer's fields parameter.

class InvoiceSerializer(serializers.ModelSerializer):

class Meta:
    model = Invoice
    fields = ("amount",)

Expected behavior
Field type must be inferred from output_field

@tfranzel
Copy link
Owner

tfranzel commented Feb 6, 2024

Interesting. I was not aware of that new field type. Will have to investigate on how to handle the field. Seems like output_field is pretty much the only option for extraction.

@tfranzel tfranzel added the enhancement New feature or request label Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants