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

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

宗晟
2023-03-14

我一直在使用Django和Djangorest框架编程API,以便在Google App Engine中部署。API基本上是一个包注册表,因此您可以使用API创建、更新、获取和删除包。

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

所有endpoint都在工作,但由于某种原因,当我点击特定的endpoint“/packages/”时,GCP给出了错误消息

400. That’s an error.

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

当我在计算机上本地运行应用程序时,所有endpoint都能正常工作。当我在Google App Engine上部署该应用程序时,该应用程序仅停止对该特定路由的工作。API有效载荷应为:

[{“名称”:“*”}]

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

意见。派克

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)

网址。派克

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)

共有1个答案

柴默
2023-03-14

您正在对路由定义packages_middleware(请求)进行GET调用。

在该函数中,您有querys=request。数据和其他逻辑依赖于查询。本文档说明了请求。数据用于POST、补丁和PUT。如果这是正确的,那么这似乎就是你的错误所在。

您可以在该行前后放置一条打印语句,然后查看应用程序是否在该行之后打印该语句。这将帮助您确认这是否是问题所在。

您还应该打印查询的内容。由于GET请求实际上没有发送正文,因此可能会导致其余逻辑失败,因为querys的值不是您期望的值。

 类似资料: