簡體   English   中英

Django 在無服務器上運行的應用程序 + Lambda + API 網關 HTTP API 正在重寫鏈接以使用默認前綴

[英]Django application running on top of Serverless + Lambda + API Gateway HTTP API is rewriting links to be prefixed with default

我的 Django 應用程序(主要基於 REST 框架)當前在管理頁面上生成無法解析的 URL。 預期結果是 Django 管理員的登錄提示將帶有 POST 的表單提交到/admin/login 作為表單提交 URL 通過 Django 傳遞的結果 URL 是/$default/admin/login並返回 404 和更遲鈍的/$default/$default/admin/login/

我假設我的 Django 配置或serverless.yml中存在某種配置錯誤。

根據以下serverless.yml ,我正在使用 API Gateway V2、Django 通過 WSGI 和 Lambda 函數。

service: api
app: api
org: myapp
frameworkVersion: '3'
provider:
  name: aws
  runtime: python3.8
functions:
  serve:
    handler: wsgi_handler.handler
    timeout: 20
    environment:
      DB_NAME: ${param:db_name}
      DB_PASSWORD: ${param:db_password}
      DB_USER: ${param:db_user}
      DB_PORT: ${param:db_port}
      DB_HOST: ${param:db_host}
    events:
      - httpApi: "*"
  migration:
    handler: migrate.handler
    timeout: 60
    environment: 
      DB_NAME: ${param:db_name}
      DB_PASSWORD: ${param:db_password}
      DB_USER: ${param:db_user}
      DB_PORT: ${param:db_port}
      DB_HOST: ${param:db_host}
custom:
  wsgi:
    app: myapp.wsgi.application
plugins:
  - serverless-python-requirements
  - serverless-wsgi

我的網址非常標准:

from django.contrib import admin
from django.urls import path, include

from rest_framework.schemas import get_schema_view

schema_view = get_schema_view(
    title="MyApp",
    description="MyApp Universal API",
    version="1.0.0",
)

urlpatterns = [
    path("admin/", admin.site.urls),
    path("user/", include("myapp.core.urls"), name="user"),
    path("openapi", schema_view, name="openapi-schema"),
]

我的配置更標准:

import os
from pathlib import Path
from dotenv import load_dotenv

load_dotenv()

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "not for you :)"

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']

if 'CODESPACE_NAME' in os.environ:
    codespace_name = os.getenv("CODESPACE_NAME")
    codespace_domain = os.getenv("GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN")
    CSRF_TRUSTED_ORIGINS = [f'https://{codespace_name}-8000.{codespace_domain}']

ROOT_URLCONF = "myapp.urls"

# Application definition

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    'rest_framework',
    "myapp.core",
]

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.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

X_FRAME_OPTIONS = "ALLOW-FROM preview.app.github.dev"

ROOT_URLCONF = "myapp.urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "myapp" / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

WSGI_APPLICATION = "myapp.wsgi.application"


STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DB_NAME', 'neondb'),
        'USER': os.environ.get('DB_USER', 'postgres'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOST', 'localhost'),
        'PORT': os.environ.get('DB_PORT', 5432),
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATICFILES_DIRS = [
    BASE_DIR / "myapp" / "static",
]

STATIC_URL = "static/"

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'

AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = "myapp-django-static"

AUTH_USER_MODEL = 'core.User'

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    )
}

至於由此產生的錯誤信息:

在此處輸入圖像描述

任何幫助(或想法)將不勝感激!

我已經嘗試修改serverless.yml的路徑結構,並且一直在瀏覽 Django 源代碼以尋找任何無濟於事的提示。 當然,我只想讓 Django 管理員工作。 至於應用程序的 rest,它工作正常,因為 API 本身不是自引用的。 Django 只是沒有返回正確的路徑。

簡而言之,Django 認為我所有的路由都以/$default/為前綴,但事實並非如此。 我正在尋找一種解決方案來強制將 Django 發送的路徑設為/或修復我的無服務器配置以緩解此問題。

我設法用一個相當小眾的 Django 設置選項解決了這個問題。 https://docs.djangoproject.com/en/4.1/ref/settings/#force-script-name

雖然這並不能解釋為什么要解析到/$default/的路徑,但它確實緩解了這個問題。

如果您將此用於與我不同的用例並且您的路徑位於子目錄中(例如與我相反的問題),那么您將在FORCE_SCRIPT_NAME中添加您的路徑。

請參閱我提供的鏈接以獲取更多信息。

將以下內容添加到您應用的settings.py或您用作DJANGO_SETTINGS_MODULE的任何文件中。

# Force Django to resolve the URL to the root of the site
# This is required for API Gateway <- WSGI -> Django path resolution to work properly.
FORCE_SCRIPT_NAME = ""

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM