Django REST API endpoints URL paths

I have a Django 4.2 app with Postgres DB and REST API. My urls.py contains this path in urlpatterns:

path('create/<int:pk>/<str:name>/', ComponentCreate.as_view(), name='create-component')

ComponentCreate in views.py relates to a simple DB table (component) with id as integer primary key and name as the only other column.

views.py has:

class ComponentCreate(generics.CreateAPIView):
    queryset = Component.objects.all(),
    serializer_class = ComponentSerializer
    lookup_field = "id"

models.py has:

class Component(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=255, blank=True, null=True)
    class Meta:
        managed = True
        db_table = 'component'

serializers.py has:

class ComponentSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField()
    name = serializers.CharField()

    class Meta:
        model = Component
        fields = ('id', 'name')

I am trying to use the API to add a row to the component table using e.g. as below (where app is called SystemTestDB):

curl -X POST http://127.0.0.1:8000/SystemTestDB/create/2/whatever/

However this fails with response:

{"id":["This field is required."],"name":["This field is required."]}

I have other endpoints which do work correctly e.g. with path:

path('delete/<int:pk>/', ComponentDelete.as_view(), name='delete-component')

In that case evidently id is being passed via int:pk, whilst in the failing case neither id nor name are set in the Request.

Have I set the URL path incorrectly, or is there something wrong with model/view/serializer ?

Remove the custom fields, by this you make them mandatory:

class ComponentSerializer(serializers.ModelSerializer):
    # id = serializers.IntegerField()
    # name = serializers.CharField()

    class Meta:
        model = Component
        fields = ('id', 'name')

or if you really want to customize, set required=False [drf-doc]:

class ComponentSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField(required=False)

    class Meta:
        model = Component
        fields = ('id', 'name')

in the model you set the id as AutoField, or just hide it:

class Component(models.Model):
    id = models.AutoField(primary_key=True)
    # …
Вернуться на верх