从 Angular App 到 Django REST API 的 API 请求 - 被 CORS 阻止

Posted

技术标签:

【中文标题】从 Angular App 到 Django REST API 的 API 请求 - 被 CORS 阻止【英文标题】:API request from Angular App to Django REST API - blocked by CORS 【发布时间】:2020-10-01 17:24:06 【问题描述】:

我有一个工作的 Angular 应用程序,它从 Django REST api 获取数据。当我向某些端点发出请求时,api 请求是成功的,但由于在其他端点上是 blocked by CORS 而失败。

我在 django 应用中的 CORS 配置:

白名单:

CORS_ORIGIN_WHITELIST = (
    'http://localhost:4200', # my angular app
    'http://localhost:8080',
)

中间件:

MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
]

已安装的应用程序:

INSTALLED_APPS = [
    ...
    'corsheaders',
]

当我在我的 Angular 应用程序中发出这个 get 请求时,它成功了,我得到了我期望的结果

角度请求:

public getProviders(searchParams: ProviderSearchParams): Observable<ProviderSearchResult> 
    const p = this.serializeParams(searchParams, new HttpParams());
    return this.http.get<any>(`$this.base_url/providers/`, params: p)
      .pipe(map(this.deserializeAs(ProviderSearchResult)));

Django 端点

# urls
path('', views.ProviderList.as_view(), name="api_provider_list"),

# views
class ProviderList(generics.ListAPIView):
    """
    View all providers.
    """
    queryset = Provider.objects.filter(is_accepted=True)    
    filter_backends = [DjangoFilterBackend,
                       filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['name', 'branches__city', 'branches__area']
    search_fields = ['name', 'branches__name',
                     'branches__city', 'branches__area']
    ordering_fields = ['name', 'created_date']
    pagination_class = PageNumberPagination

    def get_serializer_class(self):
        if self.request.user.is_staff:
            return AdminProviderSerializer
        return PublicProviderSerializer

但是,当我向generics.RetrieveUpdateDestroyAPIView 发出请求时,它似乎因错误blocked by CORS 而失败。这是一个例子:

角度请求:

public getProviderBySlug = (slug: string): Observable<Provider> =>
    this.http.get<any>(`$this.base_url/providers/$slug`)
      .pipe(map(this.deserializeAs(Provider)))

Django 端点

# urls
path('<slug:slug>/', views.ProviderDetail.as_view(), name="api_provider_details"),

# views
class ProviderDetail(generics.RetrieveAPIView):
    """
    Returns a single provider
    """
    queryset = Provider.objects.all()
    serializer_class = PublicProviderSerializer

    def get_object(self):
        return Provider.objects.get(slug=self.kwargs.get('slug', None))

似乎对 generics.RetrieveUpdateDestroyAPIViewgenerics.RetrieveAPIView 的请求导致了这个 CORS 错误

错误

Access to XMLHttpRequest at 'http://localhost:8000/api/providers/icc' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

【问题讨论】:

【参考方案1】:

请加/

这样

this.http.get<any>(`$this.base_url/providers/$slug/`) <---- '/' is there 

【讨论】:

以上是关于从 Angular App 到 Django REST API 的 API 请求 - 被 CORS 阻止的主要内容,如果未能解决你的问题,请参考以下文章

如何从 django rest 框架访问 jwt 令牌到 Angular 前端

同一 AWS 实例上的 Django Rest Framework 和 Angular App

从 AngularJs App 访问 Django 服务器:简单的身份验证解决方案?

将数据从 server/app.js 传递到控制器 Angular-fullstack + multer

Angular 6 - 通过服务将消息传递到从组件到消息组件

Angular2 和 Django:CSRF 令牌头痛