【问题标题】:DRF use field-value instead of default (pk) in POST requestDRF 在 POST 请求中使用字段值而不是默认值 (pk)
【发布时间】:2019-12-19 10:20:20
【问题描述】:

尝试发送有效的 POST 请求。

当我这样发送时它会起作用:

{
  "name":"but",
  "sklad":1
}

响应是这样的,一切都是有效的:

{
  "name": "but",
  "getsklad": "fence"
}

但是当我尝试发送这个时,使用“栅栏”:

{
  "name":"but",
  "sklad":"fence"
}

出现错误:

Invalid type. The primary key value was expected, str was received.

在models.py中有这段代码:

class Sklad(models.Model):
    storages = (
        ('fence', 'Забор'),
        ('sett', 'Тротуарка'),
    )
    storage = models.CharField(
        max_length=10,
        choices=storages, 
        help_text='Name of storage',
        default='sett'
    )

class Zabor(models.Model):
    sklad = models.ForeignKey(Sklad, on_delete=models.CASCADE)
    name = models.CharField(max_length=10)
    ...

这在 serializers.py 中:

class ZaborPostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Zabor
        fields = ( 
              ...
            'name',
            'sklad',
        )

和 Views.py 部分:

class ZaborView(APIView):
    def post(self, request):
        serializer = ZaborPostSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'status': 'Success'})
        else:
            return Response({'status': 'Failed'})

我知道当我在请求中写“1”时,这意味着“pk”。但是我如何发送名称而不是 id/pk?

我是初学者。所以不要因为愚蠢的问题而狠狠地踢我)

【问题讨论】:

    标签: python-3.x api post serialization django-rest-framework


    【解决方案1】:

    由于您提供的是唯一的Sklad FOREIGN_KEY,因此您只能使用一种类型按该值进行过滤:整数、字符串等。

    可以将Skladstorage字段设置为主键:

    class Sklad(models.Model):
        storages = (
            ('fence', 'Забор'),
            ('sett', 'Тротуарка'),
        )
        storage = models.CharField(
            max_length=10,
            choices=storages, 
            help_text='Name of storage',
            default='sett',
            primary_key=True
        )
    

    现在您可以直接使用您的字符串值进行过滤。

    另一种选择是在视图中过滤:

    from django.shortcuts import get_object_or_404
    from django.http import Http404
    
    class ZaborView(APIView):
        def post(self, request):
            dataDict = dict(request.data)
            try:
                sklad = get_object_or_404(Sklad.objects, storage=dataDict['sklad'][0])
                serializer = ZaborPostSerializer(data=request.data)
                if serializer.is_valid():
                    serializer.save()
                    return Response({'status': 'Success'})
                else:
                    return Response({'status': 'Failed'})
            except Http404:
                return Response({'status': 'Failed'})
    

    请注意,仅当您只有一个带有给定 storage 字段的 Sklad 时,它才会起作用。 如果您有多个,则可以选择第一个,因为您没有提供主键并且没有其他字段要过滤:

    from django.shortcuts import get_list_or_404
    
    .....
    sklad = list(get_list_or_404(Sklad.objects, storage=dataDict['sklad'][0]))[0]
    .....
    

    希望对你有帮助!

    【讨论】:

    • 非常有用,谢谢兄弟。发布这个问题后的一段时间,我去文档并在那里找到一件事。 ForeignKey 关系字段的“to_field”选项,按选定字段过滤相关模型。在所选字段中需要“唯一=真”选项。按预期工作。您对此有何看法?
    • unique=True 是有道理的,因为必须有某种方法来唯一地定义 ForeignKey。想象一下,您有多个带有存储“围栏”的 Sklad。 Zabor 序列化程序应该选择哪一个?您的解决方案更好,因为它不会使存储字段成为 PrimaryKey。感谢您的信息!
    猜你喜欢
    • 1970-01-01
    • 2016-09-09
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 2018-05-21
    相关资源
    最近更新 更多