Не удается вставить json-запрос в модель Django с внешними ключами

У меня есть таблица Main с некоторыми данными, включая внешние ключи к другим моделям. У меня возникла проблема с добавлением данных в эту модель из JSON запроса. Некоторые поля в запросе могут быть 'None', некоторые могут отсутствовать.

models.py

from django.db import models


class Systems(models.Model):
    class Meta:
        db_table = 'systems'

    system = models.CharField(max_length=100, unique=True)
    active = models.BooleanField(default=True)

    def __str__(self):
        return self.system


class Location(models.Model):
    class Meta:
        db_table = 'location'

    location = models.CharField(max_length=100, unique=True)
    active = models.BooleanField(default=True)

    def __str__(self):
        return self.location


class RepairPlace(models.Model):
    class Meta:
        db_table = 'repair_place'

    place = models.CharField(max_length=100, unique=True)
    active = models.BooleanField(default=True)

    def __str__(self):
        return self.place


class Equipments(models.Model):
    class Meta:
        db_table = 'equipments'

    equipment = models.CharField(max_length=100, unique=True)
    equipment_system = models.ForeignKey(Systems, on_delete=models.RESTRICT)
    active = models.BooleanField(default=True)

    def __str__(self):
        return self.equipment


class Employees(models.Model):

    class Meta:
        db_table = 'employees'
        unique_together = ('last_name', 'first_name', 'middle_name')

    last_name = models.CharField(max_length=100)
    first_name = models.CharField(max_length=100)
    middle_name = models.CharField(max_length=100, null=True, blank=True)
    organization = models.CharField(max_length=100, null=True, blank=True)
    active = models.BooleanField(default=True)

    def __str__(self):
        result = self.last_name + ' ' + self.first_name + ' ' + self.middle_name
        return result

class Main(models.Model):
    class Meta:
        db_table = 'main'

    object = models.ForeignKey(Location, on_delete=models.RESTRICT, related_name="location_name"')
    name = models.ForeignKey(Equipments, on_delete=models.RESTRICT, related_name="equipment_name")
    serial = models.CharField(max_length=100, null=True, blank=True)
    system = models.ForeignKey(Systems, on_delete=models.RESTRICT, related_name="system_name")
    accepted_dt = models.DateField(null=True, blank=True)
    shipped_repair_dt = models.DateField(null=True, blank=True)
    accepted_repair_dt = models.DateField(null=True, blank=True)
    issued_object = models.ForeignKey(Location, on_delete=models.RESTRICT, related_name='issued_location_name', null=True, blank=True)
    serial2 = models.CharField(max_length=100, null=True, blank=True)
    issued_dt = models.DateField(null=True, blank=True)
    repair_place = models.ForeignKey(RepairPlace, on_delete=models.RESTRICT, related_name="repair_name", null=True, blank=True)
    comments = models.TextField(max_length=500, null=True, blank=True)
    responsible_employee = models.ForeignKey(Employees, on_delete=models.RESTRICT, related_name="employee_name", null=True, blank=True)


logistic_serializers.py



class SystemsSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Systems
        fields = '__all__'


class LocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Location
        fields = '__all__'


class RepairPlaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.RepairPlace
        fields = '__all__'


class EquipmentsSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Equipments
        depth = 1
        fields = '__all__'


class EmployeesSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Employees
        fields = '__all__'


class MainSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Main
        depth = 1
        fields = ("id", "serial", "accepted_dt", "shipped_repair_dt", "accepted_repair_dt",
                  "serial2", "issued_dt", "comments", "object", "name", "system", "issued_object",
                  "repair_place", "responsible_employee")


class MainSerializerPost(serializers.ModelSerializer):
    name = EquipmentsSerializer()
    system = SystemsSerializer()
    issued_object = LocationSerializer()
    object = LocationSerializer()
    repair_place = RepairPlaceSerializer()
    responsible_employee = EmployeesSerializer()

    class Meta:
        model = models.Main
        depth = 1
        #fields = "__all__"
        fields = ("serial", "accepted_dt", "shipped_repair_dt", "accepted_repair_dt",
                  "serial2", "issued_dt", "comments", "object", "name", "system", "issued_object",
                  "repair_place", "responsible_employee")

views.py

from .models import Main, Location, Systems, Equipments, RepairPlace, Employees
from . import logistic_serializers
from rest_framework.response import Response
from rest_framework.views import APIView

class MainView_1(APIView):
        def post(self, request):
          print(request.data)
          serializer = logistic_serializers.MainSerializerPost(data=request.data)
          if serializer.is_valid():
              print(serializer.validated_data)
              serializer.save()
              return Response(serializer.data, status=status.HTTP_201_CREATED)
          print('Serializer is invalid')
          print(serializer.errors)
          return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class MainView_2(APIView):
        def post(self, request):
          print(request.data)
          serializer = logistic_serializers.MainSerializer(data=request.data)
          if serializer.is_valid():
              print(serializer.validated_data)
              serializer.save()
              return Response(serializer.data, status=status.HTTP_201_CREATED)
          print('Serializer is invalid')
          print(serializer.errors)
          return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class MainView_3(APIView):
        def post(self, request):
          arguments = {}
          fields = ['serial', 'serial2', 'comments', 'accepted_dt',
                  'shipped_repair_dt', 'accepted_repair_dt', 'issued_dt']
          fk_fields = ['object', 'name', 'system', 'issued_object',
                     'repair_place', 'responsible_employee']
          for field in fields:
            print(request.data.get(field))
            if request.data.get(field):
                arguments[field] = request.data.get(field)
          for field in fk_fields:
            try:
                if request.data.get(field).get("id"):
                    arguments[field+'_id'] = request.data.get(field).get("id")
            except:
                pass
          print(arguments)
          query = Main.objects.create(**arguments)
          try:
            query.save()
            return Response(status=status.HTTP_201_CREATED)
          except:
            return Response(query.errors, status=status.HTTP_400_BAD_REQUEST)

Из фронтенда я получаю запрос следующего вида - {"serial": "346", "accepted_dt": "2022-04-19", "serial2": "null", "comments": 0, "object": { "id": 61, "location": "test", "active": "True"}, "name": { "id": 2, "equipment": "SI3000", "active": "True", "equipment_system": { "id": 1, "system": "SI2000", "active": "True"}}, "system": { "id": 9, "system": "112", "active": "True"}}, "issued_object": "None", "repair_place": "Нет", "ответственный_сотрудник": "Нет"}

Я перепробовал множество вариантов.

Если я использую MainView_1, он возвращает:

Serializer is invalid
{'object': {'location': [ErrorDetail(string='Location with this location already exists.', code='unique')]}, 'name': {'equipment': [ErrorDetail(string='Equipment with this equipment already exists.', code='unique')]}, 'system': {'system': [ErrorDetail(string='Systems with this system already exists.', code='unique')]}, 'issued_object': {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}, 'repair_place': {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}, 'responsible_employee': {'non_field_errors': [ErrorDetail(string='Invalid data. Expected a dictionary, but got str.', code='invalid')]}}

Похоже, что он пытается проверить связанные модели для записи в них, но мне не нужно ничего вставлять в связанные модели. Я просто хочу записать ID связанных объектов.

Если я использую MainView_2, он возвращает:

serialized.validated_data - OrderedDict([('serial', '346'), ('accepted_dt', datetime.date(2022, 4, 19)), ('serial2', 'null'), ('comments', '0')])

and error - django.db.utils.IntegrityError: null value in column "name_id" of relation "main" violates not-null constraint
DETAIL:  Failing row contains (50, 346, 2022-04-19, null, null, null, null, 0, null, null, null, null, null, null).

Похоже, что он не может сериализовать данные из объектов с внешним ключом.

Я решил эту проблему ручным разбором в MainView_3

Это работает, но я думаю, что это не очень хорошее решение.

Если кто-то знает, как решить мою проблему с помощью сериализаторов, я буду благодарен.

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