400.这是个错误.您的客户端发出了格式错误或非法的请求.这就是我们所知道的全部-谷歌应用引擎Django应用程序



我一直在使用Django和djangorestframework编写API,以便在Google应用引擎中部署。API基本上是一个包注册表,因此您可以使用API创建、更新、获取和删除包。

除了一个端点外,所有端点似乎都能工作。唯一不起作用的端点是显示在线注册表中所有包的分页列表的端点。

所有的端点都在工作,但由于某种原因,当我到达特定的端点"/packages/"时,GCP会给我错误

400. That’s an error.
Your client has issued a malformed or illegal request. That’s all we know

当我在计算机上本地运行应用程序时,所有端点都能完美工作。当我在谷歌应用引擎上部署应用程序时,该应用程序只会停止为特定路由工作。API负载应该是:

[{"名称":"}]

我完全迷失在这一点上,如果有任何帮助,我将不胜感激。

VIEWS.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)

您正在对/packages/进行GET调用,该调用由路由定义packages_middleware(request)处理。

在该函数中,您有queries = request.data,其余的逻辑依赖于queries。该文档中说request.data用于POST、PATCH、PUT。如果这是正确的,那么这似乎就是你的错误所在。

您可以在该行前后放置一个打印对账单,并查看您的应用程序是否在该行之后打印对账单。这将帮助您确认是否存在问题。

您还应该打印queries的内容。由于您实际上并没有在GET请求中发送正文,因此您的逻辑的其余部分可能会失败,因为queries的值不是您所期望的值。

相关内容

最新更新