Django Rest Frame Work: передача пользователя в djago rest frame work

У меня есть проект Django со следующим кодом в модели

class Report(models.Model):
created_by_user=models.ForeignKey(User,on_delete=models.CASCADE)

следующий код в сериализаторе

class ReportSerializer(serializers.ModelSerializer):
class Meta:
    model=Report
    fields='__all__'

и следующий код в представлении

class ReportCreateView(APIView):


def post(self,request, *args, **kwargs):
    received_data=ReportSerializer(data=request.data)
    if received_data.is_valid():
        received_data.save()
        return Response(received_data.data, status=status.HTTP_201_CREATED)
    return Response(received_data.errors,status.HTTP_400_BAD_REQUEST)

когда я отправляю запрос на почту с помощью postman и отправляю имя пользователя и пароль во вкладке авторизация возникает ошибка:

{
"created_by_user": [
    "This field is required."
]

}

но если я введу имя пользователя или пароль неправильно, то будет

{
"detail": "Invalid username/password."

}

все могут мне помочь?

Ваш сериализатор не имеет представления о текущем вошедшем пользователе. Вы должны передать его как контекст из request. user или request.

Я лично предпочитаю CurrentUserDefault использовать в сериализаторе. Чтобы это работало, нам нужно передать запрос как контекст, потому что CurrentUserDefault выбирает пользователя из контекста запроса. Нам нужно обновить наши представления и код сериализатора следующим образом

Просматривает файл: Добавить запрос в качестве контекстного контекста

class ReportCreateView(APIView):


def post(self,request, *args, **kwargs):
    received_data=ReportSerializer(data=request.data, context = {"request": request})
    if received_data.is_valid():
        received_data.save()
        return Response(received_data.data, status=status.HTTP_201_CREATED)
    return Response(received_data.errors,status.HTTP_400_BAD_REQUEST)

serializer.py: Обновите свой сериализатор для автоматического заполнения created_by_user

class ReportSerializer(serializers.ModelSerializer):
    created_by_user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    
    class Meta:
        model=Report
        fields='__all__'

Это решит проблему с обязательным полем пользователя.

"created_by_user": ["This field is required."]

Переходим к следующей части проблемы, связанной с неправильными паролями.

По умолчанию APIView выбирает класс аутентификации по умолчанию из настроек. Внутри проектов settings.py мы в основном пишем эти строки при использовании DRF, и они служат аутентификацией по умолчанию для APIView:

Из settings.py

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    "DEFAULT_PERMISSION_CLASSES": [
        "rest_framework.permissions.IsAuthenticated",
    ],
    # Authentication settings
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework.authentication.SessionAuthentication",
    ],
   ...
}

В APIView вы можете посмотреть на стандартные permission_classes, и authentication_classes

Изнутри APIView:

    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES

это когда вы вводите неправильный пароль:

"detail": "Invalid username/password."

Предоставьте правильное имя пользователя и пароль вашему APIView из postman, чтобы он получил запрашиваемого зарегистрированного пользователя для автозаполнения на уровне БД.

Выпьем!

Есть полезные решения https://www.py4u.net/discuss/1252794 мы можем решить эту проблему многими способами.

Вы не выполняете никаких процессов над данными пользователя и просто должны сохранить запрос пользователя, поэтому я думаю, что вам не нужно поле сериализатора для этого и лучше получить текущего пользователя в представлении. также если вам нужно больше полей для сериализации, вы можете сделать created_by_user read_only true и установить его значение в представлении.

например, если в вашей модели есть поле report name и report desc:

class Report(models.Model):
    created_by_user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=256)
    desc = models.TextField()

выполните ваш сериализатор следующим образом :

class ReportSerializer(serializers.ModelSerializer):
    class Meta:
        model = Report
        fields = '__all__'
        extra_kwargs = {
            'created_by_user': {'read_only': True},
        }

затем установите значение created_by_user в вашем представлении:

class ReportCreateView(APIView):
    def post(self, request, *args, **kwargs):
        request.data['created_by_user'] = request.user # just need add this line 
        received_data = ReportSerializer(data=request.data)
        if received_data.is_valid():
            received_data.save()
            return Response(received_data.data, status=status.HTTP_201_CREATED)
        return Response(received_data.errors, status.HTTP_400_BAD_REQUEST)
Вернуться на верх