"detail": "Учетные данные для аутентификации не были предоставлены." при попытке получить доступ к представлению списка от имени администратора. REST-фреймворк Django

У меня есть простое представление, которое я построил с помощью фреймворка Django REST:

class ProductListCreateAPIView(
        StaffEditorPermissionMixin,
        generics.ListCreateAPIView):

    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    def perform_create(self, serializer):
        print(serializer.validated_data)
        name = serializer.validated_data.get('name')
        description = serializer.validated_data.get('description') or None
        if description is None:
            description = name
        serializer.save(description=description)

здесь StaffEditorPermissionMixin:

class StaffEditorPermissionMixin():
    permission_classes = [permissions.IsAdminUser, IsStaffEditorPermission]

и вот ProductSerializer:

class ProductSerializer(serializers.ModelSerializer):
    edit_url = serializers.SerializerMethodField(read_only=True)
    url = serializers.HyperlinkedIdentityField(
        view_name='product-details',
        lookup_field='pk',
    )
    class Meta:
        model = Product
        fields = [
            'url',
            'edit_url',
            'name',
            'description',
            'price',
            'sale_price',
        ]

    def get_edit_url(self, obj):
        # return f"/api/v2/products/{obj.pk}/"
        request = self.context.get('request')

        if request is None:
            return None
        return reverse("product-edit", kwargs={"pk": obj.pk}, request=request)

и на всякий случай вот products.url:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.ProductListCreateAPIView.as_view(), name='product-list'),
    path('<int:pk>/update/', views.ProductUpdateAPIView.as_view(), name='product-edit'),
    path('<int:pk>/delete/', views.ProductDestroyAPIView.as_view()),
    path('<int:pk>/',  views.ProductDetailAPIView.as_view(), name='product-details'),
]

и на всякий случай вот исходник urls.py:

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls')),
    path('api/products/', include('product.urls')),
    path('api/v2/', include('rest_practice.routers')),
]

поэтому, когда я вхожу как администратор на http://127.0.0.1:8000/admin/ и перехожу на http://127.0.0.1:8000/api/products/, я не могу получить доступ к списку товаров и получению

HTTP 401 Unauthorized
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
WWW-Authenticate: Bearer

{
    "detail": "Authentication credentials were not provided."
}

Так что я не знаю, почему аутентификация не работает, поэтому любая помощь будет оценена по достоинству

По-моему, в вопросе немного неясно, имеется ли в виду собственная админ-панель Django или ваша собственная, которая вызывает эту конечную точку. Это происходит потому, что при переходе на эту страницу из админки в запрос не включается токен пользователя.

При этом я думаю, что лучше отделить ListCreateAPIView от страниц администрирования (если вы говорите о собственных страницах администрирования Django), чтобы представление было логикой, обслуживающей вызовы API. Для этого достаточно изменить файл admin.py в папке app следующим образом:

from django.contrib import admin
from .models import Product

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_filter = ['some_column',...]
    list_display = [...]

Надеюсь, это поможет.

Я забыл изменить DEFAULT_AUTHENTICATION CLASSES, где у меня было установлено вот так

auth_classes = [
    "rest_framework.authentication.SessionAuthentication",
    "api.authentication.TokenAuthentication",
]

if DEBUG:
    auth_classes = ["api.authentication.TokenAuthentication"]

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": auth_classes,
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticatedOrReadOnly",
        "rest_framework.permissions.IsAdminUser",  # ONLY GET METHODS
    ],
}

там, где должно быть примерно так:

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.SessionAuthentication",
        "api.authentication.TokenAuthentication",
    ],
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticatedOrReadOnly",
        "rest_framework.permissions.IsAdminUser",  # ONLY GET METHODS
    ],
}
Вернуться на верх