Search code examples
djangodjango-modelsdjango-rest-frameworkdrf-spectacular

Difficulty Sending List of Working Hours as Multipart Data Using Swagger in Django DRF


I'm currently facing an issue when attempting to send data in the correct format using Swagger in Django Rest Framework (DRF). The specific challenge is with sending a list of working hours as multipart data. Below is a simplified version of my code:


# models.py
class Facility(models.Model):
    name = models.CharField(max_length=255)
    # ... other fields

class WorkingHours(models.Model):
    linkedFacility = models.ForeignKey(Facility, on_delete=models.CASCADE, related_name='workingHours')
    dayOfWeek = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(7)])
    startTime = models.TimeField()
    endTime = models.TimeField()

# serializers.py
class WorkingHoursSerializer(serializers.ModelSerializer):
    class Meta:
        model = WorkingHours
        fields = ('dayOfWeek', 'startTime', 'endTime')

class FacilitySerializer(serializers.ModelSerializer):
    workingHours = WorkingHoursSerializer(many=True, read_only=True)

    class Meta:
        model = Facility
        fields = ('id', 'name', 'workingHours')
curl -X 'POST' \
  'http://127.0.0.1:8000/api/v1/facilities/' \
  -H 'accept: application/json' \
  -H 'Content-Type: multipart/form-data' \
  -H 'X-CSRFTOKEN: ot91cIAOrwhjDMU0LtAFhAce1vVxODO5JVQqTRrFumPjyHImS6e0dHqDqseqMbVI' \
  -F 'name=first' \
  -F 'price=300' \
  -F 'phoneNumber=+3821312231213' \
  -F 'coordinates=POINT(44.7866 20.4489)' \
  -F '[email protected];type=image/jpeg' \
  -F '[email protected];type=image/jpeg' \
  -F 'workingHours={
  "dayOfWeek": 7,
  "startTime": "string",
  "endTime": "string"
},{
  "dayOfWeek": 6,
  "startTime": "string",
  "endTime": "string"
}'

In Swagger (I'm using drf-spectacular), when attempting to send a POST request to create a new Facility along with a list of related WorkingHours, the format of the request data appears to be causing issues. Specifically, the Swagger interface is struggling to handle the correct format for lists of working hours.

Any insights or suggestions on how to address this issue would be greatly appreciated!

I'm seeking guidance on the appropriate format for sending lists of working hours as multipart data, especially considering the limitations or peculiarities when using Swagger.


Solution

  • Resolve issue with get_value override:

    class WorkingHoursCreateSerializer(serializers.ModelSerializer):
        class Meta:
            model = WorkingHours
            fields = ('linkedFacility', 'dayOfWeek', 'startTime', 'endTime',)
            read_only_fields = ('linkedFacility',)
    
    
    class WorkingHoursListCustom(serializers.ListSerializer):
        child = WorkingHoursCreateSerializer()
    
        def get_value(self, dictionary):
            field_name = self.field_name
            raw_value = dictionary.get(field_name, None)
    
            if raw_value is None:
                return super().get_value(dictionary)
    
            try:
                result = html.parse_html_list(dictionary, prefix=field_name, default=empty)
                if result == empty:
                    # If parsing as a list fails, try evaluating as a literal
                    evaluated_value = eval(raw_value)
                    if isinstance(evaluated_value, tuple):
                        # Convert tuple to list
                        return list(evaluated_value)
                    else:
                        return evaluated_value
                else:
                    return result
            except Exception as e:
                # Handle the exception, for example, raise a ValidationError
                raise ValidationError(f"Invalid value for {field_name}: {raw_value}. Error: {e}")