-
Notifications
You must be signed in to change notification settings - Fork 265
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
how to represent a query parameter of type array? #267
Comments
hi @ricardogsilva, that feature was only partially exposed. i added the missing part to the external interface. you need to decorate the method with extend schema (see the doc for further instructions). @extend_schema(
parameters=[OpenApiParameter(
name='bbox',
type={'type': 'array', 'minItems': 4, 'maxItems': 6, 'items': {'type': 'number'}},
location=OpenApiParameter.QUERY,
required=False,
style='form',
explode=False,
)],
)
def list(self, request):
... EDIT: For people wanting to use |
awesome, I'll test it out soon and provide some feedback! |
I gave this a whirl, but the request body types are being rendered with non-repeating object field. I'm trying to produce a schema where the I love this library, by the way! Thank you for all of your hard work. ❤️ Version Info
Generated Request Types
Generated API endpointsThese are looking good to me! 👍 Included just for reference / debugging purposes.
Viewset# views.py
@extend_schema(
tags=["ml-ops"],
parameters=[OpenApiParameter(
name='mask',
type={'type': 'array', 'items': {'type': 'number'}},
location=OpenApiParameter.QUERY,
explode=False
)]
)
class DeviceCalibrationViewSet(
UpdateModelMixin, ListModelMixin, RetrieveModelMixin, GenericViewSet
):
serializer_class = DeviceCalibrationSerializer
queryset = DeviceCalibration.objects.all()
lookup_field = "id"
def get_queryset(self):
user = self.request.user
return DeviceCalibration.objects.filter(octoprint_device__user=user).all()
@extend_schema(
operation_id="device_calibration_update_or_create",
parameters=[OpenApiParameter(
name='mask',
type={'type': 'array', 'items': {'type': 'number'}},
location=OpenApiParameter.QUERY,
required=True,
explode=False
)]
)
@action(methods=["post"], detail=False, url_path="update-or-create")
def update_or_create(self, request):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
instance, created = serializer.update_or_create(serializer.validated_data)
response_serializer = self.get_serializer(instance)
if not created:
return Response(response_serializer.data, status=status.HTTP_202_ACCEPTED)
return Response(response_serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def perform_create(self, serializer):
serializer.save(user=self.request.user) # models.py
class DeviceCalibration(models.Model):
created_dt = models.fields.DateTimeField(auto_now_add=True)
updated_dt = models.fields.DateTimeField(auto_now=True)
octoprint_device = models.OneToOneField(
"remote_control.OctoPrintDevice", on_delete=models.CASCADE
)
fpm = models.IntegerField(null=True)
coordinates = JSONField(null=True)
mask = JSONField(null=True) |
Ah, of course I figure out how to do this 10 minutes after taking a sec to ask. 😂 For anyone else who stumbles into this issue, here are the modifications I made (compared to the code in my previous post). I've also included the outputs below. Serializer
# serializers.py
@extend_schema_field(field={'type': 'array', 'items': {'type': 'number'}})
class JSONArrayField(serializers.JSONField):
pass
class DeviceCalibrationSerializer(serializers.ModelSerializer):
mask = JSONArrayField()
class Meta:
model = DeviceCalibration
fields = [field.name for field in DeviceCalibration._meta.fields] + [
"url",
]
extra_kwargs = {
"url": {"view_name": "api:device-calibration-detail", "lookup_field": "id"},
}
def update_or_create(self, validated_data):
return DeviceCalibration.objects.update_or_create(defaults=validated_data) Viewset# views.py
@extend_schema(
tags=["ml-ops"]
)
class DeviceCalibrationViewSet(
UpdateModelMixin, ListModelMixin, RetrieveModelMixin, GenericViewSet
):
serializer_class = DeviceCalibrationSerializer
queryset = DeviceCalibration.objects.all()
lookup_field = "id"
def get_queryset(self):
user = self.request.user
return DeviceCalibration.objects.filter(octoprint_device__user=user).all()
@extend_schema(
operation_id="device_calibration_update_or_create"
)
@action(methods=["post"], detail=False, url_path="update-or-create")
def update_or_create(self, request):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
instance, created = serializer.update_or_create(serializer.validated_data)
response_serializer = self.get_serializer(instance)
if not created:
return Response(response_serializer.data, status=status.HTTP_202_ACCEPTED)
return Response(response_serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def perform_create(self, serializer):
serializer.save(user=self.request.user) Outputs🎉 Array data structures in the request/response bodies and endpoint schemas. Woo-hoo!
|
@leigh-johnson haha, thank you very much. 😄 as you figured this issue was about having arrays in the query parameters (query,header,cookie,...), which is a different issue from yours. looking at your solution, its probably as elegant as it gets and not much room for improvement. as a matter of fact i recently added the |
@ricardogsilva i'll close this issue as i'm quite confident that your problem is solved. if not feel free to comment and we'll revisit. |
Yes, go ahead, I meant having this tested out already, but life has gotten in the way 😸 If needed I will provide futher detail when I get back to working on this. Thanks a lot! |
Is there a way to make |
@fidoriel nope and there likely won't be. We do set it automatically where appropriate. Otherwise, it is omitted from the schema, in which case default handling applies. Or, of course, you apply it by hand. |
I'm working on an implementation of OGC API Features
I need to implement the
bbox
query parameter, whose schema is shown in section 7.15.3. It is modeled as an array and is further constrained byminItems
andmaxItems
.Is there a way to achieve such a schema definition with drf-spectacular? Or even a way to manually override the schema just for a specific query param?
The text was updated successfully, but these errors were encountered: