Возвращать null вместо id или вложенных сериализованных данных в ответе API json

Вот код models.py

class Client(models.Model):
    name = models.CharField(max_length=255, unique=True)
    company_reg_num = models.CharField(max_length=255, blank=True, null=True, unique=True)
    date_registerd_internal = models.DateField(auto_now_add=True)
    date_registerd_external = models.DateField()
    location = models.ManyToManyField(Location, null=True, blank=True, related_name='location')

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True)
    time_created = models.DateTimeField(auto_now_add=True)
    image = models.ImageField(default='default.png', upload_to='profile_imgs', null=True, blank=True)
    date_of_birth = models.DateField(blank=True, null=True)
    gender = models.CharField(choices=GENDER, max_length=12, default='Male')
    place_of_birth = models.CharField(max_length=255, blank=True, null=True)
    employer = models.ForeignKey(Client, on_delete=models.CASCADE, blank=True, null=True, related_name='employer')
    

class Shift(model.Models):
    # --snip--
    expense = models.ForeignKey(Expense, on_delete=models.CASCADE, null=True, blank=True, related_name='expense')
    time_added = models.DateTimeField(auto_now_add=True)
    employee_assigned = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True, blank=True, related_name='employee_assigned')
    location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True, blank=True)
    client = models.ForeignKey(Client, on_delete=models.CASCADE, null=True, blank=True, related_name='client')


И вот мой файл serializer.py

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = '__all__'

class ClientSerializer(serializers.ModelSerializer):
    location = LocationSerializer(read_only=True, many=True)
    class Meta:
        model = Client
        fields = '__all__'

class ShiftSerializer(serializers.ModelSerializer):
    #permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    location = LocationSerializer(read_only=True, many=False)
    employee_assigned = ProfileSerializer(many=False, read_only=True) 
    client = ClientSerializer(many=False, read_only=True)
    class Meta:
        model = Shift
        fields = '__all__'

Я использую представления на основе функций для моих api представлений, и они следующие:

@api_view(['GET', 'POST', 'PATCH'])
@csrf_exempt
@permission_classes((IsAuthenticated,))
def shift_api(request):
    if request.method == 'GET':
        if request.user.is_superuser and request.user.is_staff:
            shifts = Shift.objects.all()
            serializer = ShiftSerializer(shifts, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:

            return Response({"error": "You do not have permission to view this"}, status=status.HTTP_403_FORBIDDEN)

    elif request.method == 'POST':
        serializer = ShiftSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'PATCH':
        serializer = ShiftSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(json.dumps(serializer.data), status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'POST', 'PATCH', 'DELETE'])
def shift_detail_api(request, pk):
    try:
        shift = Shift.objects.get(pk=pk)
    except Shift.DoesNotExist:
        return Response({"error": f"no shift found for id of  {pk}"},status=status.HTTP_404_NOT_FOUND)
    if request.method == 'GET':
        serializer = ShiftSerializer(shift)
        return Response(serializer.data)
    elif request.method == 'PATCH':
        serializer = ShiftSerializer(shift, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        shift.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Когда я запрашиваю API для определенной смены по id, например 22, я получаю вложенный json-ответ следующего вида:

{
    "id": 22,
    "location": {
        "id": 3,
        "name": "Lusaka",
        "lat": -15.3875259,
        "lng": 28.3228165,
        "Address": ""
    },
    "employee_assigned": {
        "id": 11,
        "time_created": "2022-01-05T18:15:08.109892+02:00",
        "image": "/profile_pics/default.png",
        "date_of_birth": null,
        "gender": "Female",
        "place_of_birth": "Yokshire, England",
        "phone": null,
        "pay_rate": 0.0,
        "highest_qualification": null,
        "experience_summary": "",
        "user": 6,
        "employer": 4,
        "job_title": 2
    },
    "client": {
        "id": 4,
        "location": [
            {
                "id": 4,
                "name": "Kabwe",
                "lat": -14.4285061,
                "lng": 28.451357,
                "Address": ""
            }
        ],
        "name": "Kabwe Developers",
        "company_reg_num": "3LEA1E7P",
        "date_registerd_internal": "2022-01-03",
        "date_registerd_external": "2022-01-03",
        "industry_category": "SECURITY"
    },
    "shift_date": "2022-01-05",
    "start_time": "2022-01-05T18:51:31+02:00",
    "end_time": "2022-01-06T00:45:00+02:00",
    "start_of_break": null,
    "end_of_break": null,
    "break_hours": 0.0,
    "start_time_actual": "2022-01-06T18:51:57+02:00",
    "end_time_actual": "2022-01-06T20:45:00+02:00",
    
}

Но когда я хочу добавить смену с помощью метода post, используя существующего клиента и employee_assigned в базе данных, которые в данном случае равны 4 и 13, соответственно, я использую json тело с содержимым ниже:

{
    
    
    "employee_assigned": 13,
    "client": 4,
    "shift_date": "2022-01-10",
    "start_time": "2022-01-10T06:00:00+02:00",
    "end_time": "2022-01-10T14:00:00+02:00",
    "start_of_break": null,
    "end_of_break": null,
    "break_hours": 0.0,
    "start_time_actual": null,
    "end_time_actual": null,
    "clockin_location_lat": null,
    "clockin_location_lng": null,
    "clockout_location_lat": null,
    "clockout_location_lng": null,
    "hours_actual": 0.0,
    "pay_rate": 0.0,
    "charge_rate": 0.0,
    "time_added": "2022-01-12T12:49:02.047224+02:00",
    "status": "OPEN",
    "expense": null
}

Однако я получаю ответ со следующими полями


{
    "id": 52,
    "location": null,
    "employee_assigned": null,
    "client": null,
    "shift_date": "2022-01-10",
    "start_time": "2022-01-10T06:00:00+02:00",
    "end_time": "2022-01-10T14:00:00+02:00",
    "start_of_break": null,
    "end_of_break": null,
    "break_hours": 0.0,
    "start_time_actual": null,
    "end_time_actual": null,
    "clockin_location_lat": null,
    "clockin_location_lng": null,
    "clockout_location_lat": null,
    "clockout_location_lng": null,
    "hours": 8.0,
    "hours_actual": 0.0,
    "pay_rate": 0.0,
    "charge_rate": 0.0,
    "time_added": "2022-01-12T13:13:21.580793+02:00",
    "status": "OPEN",
    "expense": null
}

Так что я не получаю никаких ошибок, но я хочу, чтобы клиент и назначенный сотрудник возвращали что-то другое, чем null. Мне нужно, чтобы ответ возвращал либо id, либо вложенные сериализованные данные.

Что я могу сделать, чтобы достичь этого?

из-за того, что вы установили атрибут поля client и employee_assigned read_only в True в вашем классе сериализатора. вы должны определить два разных поля для каждого из них, как показано ниже :

employee_assigned_id = serializer.IntegerField(write_only=True)    
employee_assigned = ProfileSerializer(many=False, read_only=True) 

cilent_id = serializer.IntegerField(write_only=True)
client = ClientSerializer(many=False, read_only=True)

и затем, когда вы хотите отправить метод POST, отправьте их id, используйте employee_assigned_id, и client_id, и получите их в деталях (whit их serializer)

Вернуться на верх