как сохранить внешние ключи используя django-rest-framework - PullRequest
0 голосов
/ 26 декабря 2018

Я новичок в Django и пытаюсь сохранить внешние ключи Unit и current_user в полученном pk на базе базы данных, но каждый раз, когда я пытаюсь это сделать, но сталкиваюсь с двумя типами ошибок, serializers.is_valid() вызывает ошибку исключения илиСериализатор возвращает "Invalid data. Expected a dictionary, but got Unit."

Я попробовал очень уродливый способ обойти сериализаторы путем избавления, но я понял, что ee8452a4-2a82-4804-a010-cf2f5a41e006 должен быть экземпляром SavedUnit.unit. Я также пыталсясохранение внешнего ключа напрямую, используя SavedUnit.objects.create() без удачи

model.py

class SavedUnit(models.Model):
    """
    Saving units for later models
    relationship with units and users
    """
    id = models.UUIDField(primary_key=True, default=hex_uuid, editable=False)
    unit = models.ForeignKey(Unit, on_delete=models.CASCADE)
    user = models.ForeignKey('accounts.User', on_delete=models.CASCADE, related_name='user')
    published_at = models.DateTimeField(auto_now_add=True)

serializers.py

class SavedSerializer(serializers.ModelSerializer):
    unit = UnitSerializer()
    class Meta:
        model = SavedUnit
        fields = [
            'id',
            'unit'
        ]

views.py

class SavedUnitView(APIView):
    """
    Query all the unites saved
    """
    @staticmethod
    def get_unit(request, pk):
        try:
            return Unit.objects.get(pk=pk)
        except Unit.DoesNotExist:
            return Response(status=status.HTTP_400_BAD_REQUEST)
    @staticmethod
    def post(request, pk):
        if request.user.is_authenticated:
            unit = get_object_or_404(Unit, id=pk)
            serializers = SavedSerializer(data=unit)
            if serializers.is_valid(raise_exception=True):
                created = SavedUnit.objects.get_or_create(
                    user=request.user,
                    unit=unit)
                return Response(status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_401_UNAUTHORIZED)
    def get(self, request):
        units = SavedUnit.objects.filter(user=self.request.user.id)
        try:
            serializers = SavedSerializer(units, many=True)
            return Response(serializers.data, status=status.HTTP_200_OK)
        except Unit.DoesNotExist:
            return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)

Ответы [ 2 ]

0 голосов
/ 26 декабря 2018

Ваш код использует сериализатор только для проверки, но его можно использовать для вставки или обновления новых объектов в базе данных, вызывая serializer.save().

Чтобы сохранить внешние ключи с помощью django-rest-framework, вы должны поставитьсоответствующее поле на сериализаторе, чтобы справиться с этим.Используйте 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)

Теперь идентификатор устройства будет передан в теле запроса, как это

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

{ 
    "unit_id": 5  # Id of an existing Unit
}
0 голосов
/ 26 декабря 2018

На самом деле проблема здесь:

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

Вы передаете экземпляр объекта, но это должен быть request.data, например:

serializers = SavedSerializer(data=request.data)

(я не уверен насчетчто вы делаете, если у вас уже есть PK, то почему вы даже используете сериализатор? потому что он вам не нужен, так как у вас уже есть устройство, и вы можете получить доступ к текущему пользователю из request.user, что вы уже делаете.И я не думаю, что вы должны использовать @staticmethod, вы можете объявить метод post следующим образом: def post(self, request, pk) и удалить статический метод декоратора)

...