0

Here dummy code to show my problem:

In my django models.py I have something like:

class MyModel(Model):
    test_field = SlugField(blank=True, null=False)
    # some other not-null not-blank fields here   

     def save(self, *args, **kwargs):
         self.test_field = .... # Setting with a value calculated form the other not-null not-blank fields
        

Here my serializer:

from rest_framework import serializers
class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = [ ...., 'test_field',  ]

In my views.py something like:

def post_endpoint(request):

    data = JSONParser().parse(request)
    serializer = MyModelSerializer(data=data)
    if serializer.is_valid():
        ....

        serializer.save()
        return JsonResponse(serializer.data, status=201)

This is working as expected: I can send an object to my post_endpoint without my test_field and I get my result with test_field set as expected. serializer.is_valid() returns True in that case.

The problem? I need that same functionality but with a FloatField instead of SlugField. But I noticed serializer.is_valid() returns False in that case and I get a "This field may not be null." in serializer.errors in my view function.

How is FloatField different from SlugField ? How can I get the expected functionality also with FloatField?

djangorestframework==3.14.0 Django==4.0.5

Alfonso_MA
  • 537
  • 5
  • 26
  • Why parsing the request to send it to serializer? Try `serializer = MyModelSerializer(data=request.data)` in your `post_endpoint` method. – Kiran Parajuli Jun 13 '23 at 03:30
  • "This field may not be null." indicates, that field in serializer does not allow you to pass None for that field. It's not related to `blank=True` parameter in your model, it's related to `null=True`. If you want to pass None, you should ensure your field in model have `null=True` – Alexandr Zayets Jun 14 '23 at 07:46

1 Answers1

0

I have give it a try but it's working perfectly fine:

model

from django.db import models

class MyModel(models.Model):
    test_field_slug = models.SlugField(null=True, blank=True)
    test_field_float = models.FloatField(null=True, blank=True)
    test_field_str = models.CharField(max_length=255)

    def __str__(self):
        return self.test_field_str

    class Meta:
        verbose_name = "My Model"
        verbose_name_plural = "My Models"

serializer

from rest_framework import serializers
from app1.models import MyModel


class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = "__all__"

view

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from app1.serializers import MyModelSerializer


class MyModelView(APIView):
    def post(self, request):
        serializer = MyModelSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

urls

from django.urls import path
from app1.views import MyModelView


urlpatterns = [
    path('my-model/', MyModelView.as_view())
]

request

❯ curl http://localhost:8000/my-model/ -d abc | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    49  100    46  100     3  13360    871 --:--:-- --:--:-- --:--:-- 16333
{
  "test_field_str": [
    "This field is required."
  ]
}
❯ curl http://localhost:8000/my-model/ -d test_field_str=abc | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    96  100    78  100    18   4551   1050 --:--:-- --:--:-- --:--:--  6000
{
  "id": 1,
  "test_field_slug": null,
  "test_field_float": null,
  "test_field_str": "abc"
}

One thing I've noticed strage in your code is the JSON parsing of request for serializer input data. This is not required as log as you follow the procedure like above.

Kiran Parajuli
  • 820
  • 6
  • 14