当前位置: 首页 > 知识库问答 >
问题:

django rest框架“此字段是必需的”发布

严锐
2023-03-14

每当我发布到django rest framework(DRF)endpoint时,我都会不断收到“HTTP 400错误请求”{“报价人组织”:[“此字段是必需的”。]}响应。但是,考虑到下面的curl示例,我显然指定了一个值。

无论Content-Type(应用程序/json、应用程序/x-wow-form-urlencoded、多部分/form-data)如何,都会发生这种情况。它唯一有效的时间是当我使用DRF网络界面上的“超文本标记语言表单”(相对于“原始数据”)选项卡提交时。

有一些类似的SO帖子(像这样和这样),但是没有一个解决方案似乎对我有用。

型号:

class OrganizationManager(models.Manager):
    def get_by_natural_key(self, offeror_organization):
        return self.get(offeror_organization=offeror_organization)

class Organization(models.Model):
    idorganization = models.AutoField(primary_key=True)
    offeror_organization = models.CharField(max_length=250, null=False, blank=False, verbose_name='Offeror Organization')
    created_at = models.DateTimeField(auto_now_add=True, null=False)
    updated_at = models.DateTimeField(auto_now=True, null=False)

    objects = OrganizationManager()

    def natural_key(self):
        return "%s" % (self.offeror_organization)

    def __str__(self):
        return self.offeror_organization

序列化程序:

class OrganizationSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Organization
        fields = ['offeror_organization']

    # I've tried both with and without a create function
    def create(self, validated_data): 
        organization_data = validated_data.pop('offeror_organization', None)
        if organization_data:
            organization = Organization.objects.get_or_create(**organization_data)[0]
            validated_data['offeror_organization'] = organization

意见/api.py:

from webapp.models import Organization
from webapp.serializers import OrganizationSerializer

from rest_framework import viewsets

class OrganizationViewSet(viewsets.ModelViewSet):
    queryset = Organization.objects.all().order_by('offeror_organization')
    serializer_class = OrganizationSerializer

urls.py:

from django.urls import include, path
from rest_framework import routers
from . import views

router = routers.DefaultRouter()
router.register(r'organization', views.OrganizationViewSet)

urlpatterns = [
    ...
    path('api/', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

卷曲命令:

curl -X POST -H 'Content-Type: application/json' -d '{"offeror_organization":"Test2"}' 10.101.10.228:29000/webapp/api/organization/

settings.py中间件:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.RemoteUserMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'csp.middleware.CSPMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware'
]

settings.py REST\u框架

# currently have all API authentication disabled while troubleshooting this issue
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [],
    'DEFAULT_PERMISSION_CLASSES': [],
}

共有2个答案

燕飞文
2023-03-14

我有相同的设置(nginx gunicorn django rest framework drf writeable nested),但我可以为包含多部分/表单数据的POST请求找到一种有效的格式:

它必须是这样的:

JSON:

{
   'name': 'test-name',
   'files': [
      {
         'file': 'test-file-1'
      },
      {
         'file': 'test-file-2'
      },
      ...
   ],
   ...
}

必须格式化为:

表单数据:

name: test-name
files[0]file: test-file-1
files[1]file: test-file-2
...

一些库会在嵌套列表的方括号后使用点,这将导致此字段为必填项错误。或者,列表括号之后的另一个括号也会导致相同的错误。这是错误的:文件[0]。文件这也是错误的:文件[0][file]

我的示例假设以下Django类:

# views.py

from rest_framework.viewsets import ModelViewSet
from rest_framework.parsers import MultiPartParser, FormParser
from .serializers import YourCustomModelSerializer

class YourCustomModelViewSet(ModelViewSet):
    queryset = YourCustomModel.objects.all()
    parser_classes = [FormParser, MultiPartParser]
    permission_classes = []
    serializer_class = YourCustomModelSerializer
# serializers.py

from rest_framework.serializers import ModelSerializer
from drf_writable_nested.serializers import WritableNestedModelSerializer
from .models import YourCustomModel, File

class FileSerializer(ModelSerializer):
    class Meta:
        model = File
        fields = ['file']

class YourCustomModelSerializer(WritableNestedModelSerializer):
    # Reverse foreign key
    files = FileSerializer(many=True)

    class Meta:
        model = YourCustomModel
        read_only_fields = ('id', )
        fields = [
            'id',
            'name',
            'files'
        ]
# models.py

from django.db import models

class File(models.Model):
    file = models.FileField()

class YourCustomModel(models.Model):
    name = models.CharField(max_length=200)

我使用下面的javascript/typecript前端代码将我的json数据打包到FormData请求中:

const requestBody = {
  name: 'test-name',
  files: [
    { file: file1 }, // File object
    { file: file2 }, // File object
    { file: file3 }  // File object
  ]
}

// # use your own code to serialize the above javascript dict/json/object
// into form-data object (I used the library https://www.npmjs.com/package/object-to-formdata but I had to write a patch for the exact reason described above: files[0].file is not correctly parsed by Django and files[0][file] also won't work, therefore I slightly changed the library code so that it will format my object to files[0]file for every nested item:

// 2. prepare a serializer-library to convert the dict into a special form which can be parsed by django.
const options = {
  indices: true,
  allowEmptyArrays: true,
  useDotOrBracketsOrNothingForNestedObjects: 2 // Option 0: DOT-Notation, 1: Brackets, 2: Nothing (this option is from my custom patch)
}

// use npx patch: https://stackoverflow.com/a/62567504/3433137
// (I patched this serialize library and the patch is somewhere stored as a file in this project)
const formData = serialize(
  requestBody,
  options
)
    
// 3. upload the data
api.post(url, formData)

韦俊英
2023-03-14

在我的例子中,解决这个问题需要围绕几个不同的实现约束进行“操作”。

nginx uWSGI Socket Django REMOTE_用户身份验证:如本文评论/聊天中所述,我的Django应用程序前面有一个nginx代理和一个uWSGI应用程序服务器。由于我依赖于远程_用户身份验证,因此我的uwsgi/nginx配置必须使用uwsgi套接字(vs.http),以便我可以将远程_用户作为环境变量从nginx传递到Django。使用http(耦合w/nginx proxy\u pass)时,虽然proxy\u pass可以设置头或cookie,但这些头或cookie似乎无法转换为Django(需要环境变量)。

我认为当试图发布到使用uWSGI套接字服务的Django/DRF应用程序时,会有一些问题。根据uWSGI要知道的事情(最佳实践),“TL/DR:如果您计划直接向公众公开uWSGI,请使用超文本传输协议,如果您想在使用后端的超文本传输协议的网络服务器后面代理它,请使用超文本传输协议-套接字”。在我的例子中,同时拥有一个Web应用程序和一个基于DRF的API(我希望其他服务和系统可以与之交谈),我需要两者!作为一个(希望是暂时的)解决方案,我目前正在生成两个uWSGI进程——一个使用-套接字,一个使用-超文本传输协议(用于API POST调用)。如果您在使用---套接字时发布,您可能会从DRF获得空响应错误。

顺便说一句,我最初在uWSGI套接字上使用uwsgi_curl(从uwsgi_tools)到POST时看到了一些“promise”(这导致了“字段是必需的”错误(相对于空响应错误),但那时我开始遇到我的第二个问题...

POST嵌套应用程序/json w/同步文件上传:文章中引用的“组织”模型主要是概念验证,因为它是我的Django应用程序中最不复杂的模型。实际上,我需要发布到一个更复杂的嵌套序列化模型,因为模型包含其他模型的外键。但DRF完全可以做到。除了在我的情况下,我的模型属性之一是FileUpload字段。正如其他SO问题(如本问题)所指出的,在尝试通过单个请求中的文件上传来发布嵌套(即不是“平面”)的应用程序/json时也存在一些问题。虽然我从未能够完全理解这个问题(至少在我的情况下使用了drf_writable_nested.serializers.WritableNestedModelSerializer),但我通过编写自己的自定义Serializer(序列化器)简化了手头的问题。序列化器),这样我就可以避免在我的POST请求中嵌套JSON对象(如{"offeror_organization":{"offeror_organization:"Test"}}。这解决了我的问题。

有了自定义序列化程序来缓解嵌套JSON文件上载问题,我敢打赌uwsgi_curl帖子会起作用。尽管如此,外部客户机系统/服务仅限于使用该Python包。无论如何,我会在尝试后更新我的答案。感谢@Michael的评论,并帮助我走上正确的“道路”。

 类似资料:
  • 从文件中: read_only将其设置为True,以确保在序列化表示时使用该字段,而在反序列化期间更新实例时不使用该字段。 默认为假 required通常情况下,如果反序列化期间未提供字段,则会引发错误。如果反序列化过程中不需要此字段,则设置为false。 默认为True。 因此,我有一个模型,其中有一个字段不可为null,但我希望在pre_save方法中填充它,因此我在serializer中将该

  • 当我要求一个图像http://127.0.0.1:8000/api/images/1/或者传入参数进行裁剪http://127.0.0.1:8000/api/images/1/?height=320 我得到的答复是: 而在http://127.0.0.1:8000/api/images/ 答复是: 为什么缩略图不容易返回主机名,我如何将基本网址追加到响应中? 以下是我的看法。派克

  • 主要内容:PHP - 必需字段,PHP - 显示错误信息本章节我们将介绍如何设置表单必需字段及错误信息。 PHP - 必需字段 在上一章节我们已经介绍了表的验证规则,我们可以看到"名字", "E-mail", 和 "性别" 字段是必需的,各字段不能为空。 字段 验证规则 名字 必需。 + 只能包含字母和空格 E-mail 必需。 + 必需包含一个有效的电子邮件地址(包含"@"和".") 网址 可选。 如果存在,它必需包含一个有效的URL 备注 可选。多

  • 我已将数据注释添加到ASP中的一个模型中。NETMVC应用程序。创建迁移后,运行命令会导致以下错误: 无法将值NULL插入表“MOVICES”的“Director”列中。dbo。电影;;列不允许空值。更新失败。声明已终止。 这是由于某些记录的列中有NULL。如何将这些值自动更改为某个默认值(例如“John Doe”)控制器? 这是我的模型: 以下是我的最新迁移:

  • 我有以下API定义: 我定义了txConfig is required属性(这是类),但当发送空JSON()时,spring boot仍然运行API,而我希望它返回一个错误,即未设置参数tsConfig。 知道我错过了什么吗? 编辑:使用@Valid和@NotNull解决了它,但是返回的错误信息太多,有办法修复吗?

  • 我想我会在这里问这个问题,因为我不太确定我会错在哪里。我正在尝试使用Django Rest框架类通过AJAX执行POST请求。但是,每当事件触发时,我都会收到以下错误: 这是堆栈跟踪中显示的内容: 上下文 我试图做到这一点,当用户单击“添加到列表”按钮时,它会向用户定义的列表发送一个cafeName(以及最终的其他详细信息)。 我想知道是否有人可以看看我的代码,并给我一些指导,我哪里出了问题? 代