django - 400. 这是一个错误。您的客户发出了格式错误或非法的请求。这就是我们所知道的 - Google App Engine Django App
问题描述
我一直在使用 Django 和 djangorestframework 编写一个 API,以便在 Google App Engine 中进行部署。API 基本上是一个包注册表,因此您可以使用 API 创建、更新、获取和删除包。
除了一个之外,所有端点似乎都可以工作。唯一不起作用的端点是显示在线注册表中所有包的分页列表的端点。
所有端点都在工作,但由于某种原因,当我点击特定端点'/packages/'时,GCP 给了我错误
400. That’s an error.
Your client has issued a malformed or illegal request. That’s all we know
当我在我的计算机上本地运行应用程序时,所有端点都可以正常工作。当我在 Google App Engine 上部署该应用程序时,该应用程序仅针对该特定路由停止工作。API 有效负载应为:
[ { “姓名”: ”*” } ]
我完全迷失了这一点,并希望有任何帮助。
视图.py
import django.db.utils
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.core.paginator import Paginator, EmptyPage
import registry.models
from .serializers import *
from .models import *
# Create your views here.
@api_view(['GET'])
def apiOverview(request):
api_urls = {
'List': '/package-list/',
'Create': '/package-create/',
'Update': '/package-update/',
'Delete': '/package-delete/',
'Rate': '/package-rate/',
'Download': '/package-download/'
}
return Response(api_urls)
@api_view(['GET'])
def packages_middleware(request):
print(request)
print(type(request))
print(request.data)
print(type(request.data))
# determine offset query parameter
offset = request.GET.get('Offset')
if offset is None:
offset = 0
else:
offset = int(offset)
# capturing request body
response = []
queries = request.data
if len(queries) < 1:
return Response({'message: empty request body array'}, status=400)
else:
if len(queries) == 1 and queries[0]['Name'] == '*':
response = list(PackageMetadata.objects.all().values())
else:
for query in queries:
if 'Name' in query.keys() and 'Version' in query.keys():
for x in list(PackageMetadata.objects.filter(Name__icontains=query['Name']).filter(
Version__contains=query['Version']).values()):
response.append(x)
else:
response.append({
'message': 'query {q} is missing at least one attribute - remember to check spelling and capitalization'.format(q=query)
})
paginator = Paginator(response, 10)
try:
return Response(paginator.page(offset + 1).object_list, headers={'Offset': offset + 1})
except EmptyPage:
return Response(paginator.page(1).object_list, headers={'Offset': 2})
@api_view(['GET', 'PUT', 'DELETE'])
def package_middleware(request, pk):
try:
package = Package.objects.get(Metadata__ID__exact=str(pk))
if request.method == 'GET':
# CHECK THAT CONTENT FIELD IS SET
serializer = PackageSerializer(package, many=False)
return Response(serializer.data, status=200)
elif request.method == 'PUT':
payload = request.data
if 'Metadata' in payload and 'Data' in payload:
if payload['Metadata'] != PackageMetadataSerializer(package.Metadata, many=False).data:
return Response({"message": "name, version and ID must match"}, status=400)
else:
# CHECK THAT ONLY ONE DATA FIELD IS SET
serializer_data = PackageDataSerializer(data=payload['Data'], many=False)
if serializer_data.is_valid(raise_exception=True):
try:
serializer_data.update(instance=package.Data, validated_data=serializer_data.validated_data)
except django.db.utils.IntegrityError:
return Response(
{"message": "both Content and URL must be included in query, but exactly one can be set"},
status=400)
return Response(status=200)
else:
return Response(
{"message": "incorrect request body schema - remember to check spelling and capitalization"},
status=400)
else:
package.Metadata.delete()
package.Data.delete()
package.delete()
return Response({"message": "package deleted"}, status=200)
except registry.models.Package.DoesNotExist:
return Response({"message": "package not found"}, status=400)
@api_view(['POST'])
def create_package_middleware(request):
payload = request.data
print(payload)
if 'Metadata' in payload and 'Data' in payload:
serializer_metadata = PackageMetadataSerializer(data=payload['Metadata'], many=False)
serializer_data = PackageDataSerializer(data=payload['Data'], many=False)
if serializer_data.is_valid(raise_exception=True) and serializer_metadata.is_valid(raise_exception=True):
try:
metadata = PackageMetadata.objects.create(ID=serializer_metadata.data.get('ID'),
Name=serializer_metadata.data.get('Name'),
Version=serializer_metadata.data.get('Version'))
except django.db.utils.IntegrityError:
return Response({"message": "duplicate key-value (Name, Version) violates uniqueness constraint"},
status=403)
try:
data = PackageData.objects.create(Content=serializer_data.data.get('Content'),
URL=serializer_data.data.get('URL'))
except django.db.utils.IntegrityError:
metadata.delete()
return Response(
{"message": "both Content and URL must be included in query, but exactly one can be set"},
status=400)
Package.objects.create(Data=data, Metadata=metadata)
serializer_metadata = PackageMetadataSerializer(metadata, many=False)
return Response(serializer_metadata.data, status=200)
else:
return Response({"message": "incorrect request body schema - remember to check spelling and capitalization"},
status=400)
@api_view(['DELETE'])
def byName_middleware(request, name):
if name == '*':
return Response({"message": "query name reserved"}, status=400)
querySet = Package.objects.filter(Metadata__Name__iexact=name)
if len(querySet) == 0:
return Response({"message": "package not found"})
else:
for package in querySet:
package.Metadata.delete()
package.Data.delete()
package.delete()
return Response(status=200)
URLS.py
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.apiOverview),
path('packages/', views.packages_middleware, name='packages_middleware'),
path('package/<str:pk>', views.package_middleware, name='package'),
path('package/', views.create_package_middleware, name='create'),
path('package/byName/<str:name>', views.byName_middleware, name='byName')
]
模型.py
from django.db import models
# Create your models here.
class PackageData(models.Model):
Content = models.TextField(blank=True, null=True) # actual zip file
URL = models.CharField(max_length=500, blank=True, null=True) # url of package
# class Meta:
# constraints = [
# models.CheckConstraint(
# name="%(app_label)s_%(class)s_content_or_url",
# check=models.Q(Content__isnull=True, URL__isnull=False) | models.Q(Content__isnull=False, URL__isnull=True)
# )
# ]
class PackageMetadata(models.Model):
class Meta:
constraints = [
models.UniqueConstraint(fields=['Name', 'Version'], name='unique_package')
]
ID = models.CharField(primary_key=True, max_length=50)
Name = models.CharField(max_length=50)
Version = models.CharField(max_length=50)
class Package(models.Model):
Data = models.ForeignKey(PackageData, on_delete=models.CASCADE)
Metadata = models.ForeignKey(PackageMetadata, on_delete=models.CASCADE)
class PackageRating(models.Model):
BusFactor = models.DecimalField(max_digits=10, decimal_places=9)
Correctness = models.DecimalField(max_digits=10, decimal_places=9)
GoodPinningPractice = models.DecimalField(max_digits=10, decimal_places=9)
LicenseScore = models.DecimalField(max_digits=10, decimal_places=9)
RampUp = models.DecimalField(max_digits=10, decimal_places=9)
ResponsiveMaintainer = models.DecimalField(max_digits=10, decimal_places=9)
class PackageQuery(models.Model):
Name = models.CharField(max_length=50)
Version = models.CharField(max_length=50)
解决方案
您正在GET
调用/packages/
由路由定义处理的调用packages_middleware(request)
。
在您拥有的那个功能中,您queries = request.data
的其余逻辑依赖于queries
. 该文件说request.data
适用于 POST、PATCH、PUT。如果这是正确的,那么这似乎就是你的错误所在。
您可以在该行之前和之后放置一个打印语句,然后查看您的应用程序是否在之后打印该语句。这将帮助您确认这是否是问题所在。
您还应该打印queries
. 由于您实际上并未使用 GET 请求发送正文,因此您的其余逻辑可能会失败,因为 的值queries
不是您所期望的。
推荐阅读
- javascript - 使用闭包时遇到问题
- python - 根据条件安装依赖项
- javascript - 如何使用 Prisma 2 实现社交媒体“关注提要”查询?
- python - 熊猫:找到最近的高点(OHLC)
- c++ - Gmock如何模拟不带参数的单行函数?
- javascript - 我的代码应该检测一个字符串是否有货币符号,但它不会检测到 £
- sql - GCP:与硬编码值相比,从数组中选择查询具有非常大的流程数据要运行
- database - 错误:无法打开数据库 - SQLite - React-Native - Android
- ios - SKPhysicsBody(texture:,size:) 的问题
- python-3.x - 有人可以在 python 中解释这种行为吗