[Django]-How to save foreign keys using django-rest-framework

1👍

Actually the problem is here:

def post(request, pk):
    if request.user.is_authenticated:
        unit = get_object_or_404(Unit, id=pk)
        serializers = SavedSerializer(data=unit)  <-- Here

You are passing a unit instance, but it should be request.data, like this:

serializers = SavedSerializer(data=request.data)

( I am unsure about what you are doing, if you already have PK, then why are you even using serializer? because you don’t need it as you already have the unit, and you can access current user from request.user, which you are already doing. And I don’t think you should use @staticmethod, you can declare the post method like this: def post(self, request, pk) and remove static method decorator)

👤ruddra

6👍

Your code is using serializer only for validation, but it is possible use it to insert or update new objects on database calling serializer.save().

To save foreign keys using django-rest-framework you must put a related field on serializer to deal with it. Use PrimaryKeyRelatedField.

serializers.py

class SavedSerializer(serializers.ModelSerializer):
    unit_id = serializers.PrimaryKeyRelatedField(
        source='unit',
        queryset=Unit.objects.all()
    )
    unit = UnitSerializer(read_only=True)

    class Meta:
        model = SavedUnit
        fields = [
            'id',
            'unit_id',
            'unit'
        ]

views.py

class SavedUnitView(APIView):
    permission_classes = (permissions.IsAuthenticated,) # For not handling authorization mannually

    def post(request):
        serializer = SavedSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)  # Trigger Bad Request if errors exist
        serializer.save(user=request.user)         # Passing the current user
        return Response(serializer.data, status=status.HTTP_201_CREATED)

Now, the id of the unit will be passed in the request body like this

POST /saved-units/
Accept: application/json
Content-Type: application/json
Authorization: Token your-api-token

{ 
    "unit_id": 5  # Id of an existing Unit
}

Leave a comment