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)