Найти - Пользователи
Полная версия: Django REST Framework - подставить в значение поля id текущего пользователя
Начало » Django » Django REST Framework - подставить в значение поля id текущего пользователя
1
dun
Здравствуйте!

Не могу написать сериализатор для модели, который будет подставлять в значение поля id текущего пользователя в момент создания записи, в остальное же время возвращающий только id и ФИО пользователя.
Модель:
from django.models import models
from django.conf import settings
class NewsItem(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL)

Сериализаторы:
class NewsReadSerializer(serializers.ModelSerializer):
    author = UserSerializer()
    class Meta:
        model = NewsItem
class NewsWriteSerializer(serializers.ModelSerializer):
    class Meta:
        model = NewsItem

В api.py нужный сериализатор выбирается путём анализа параметров объекта request:

class NewsList(ListCreateAPIView):
    queryset = NewsItem.objects.sorted('-pub_date')
    def get_serializer_class(self, *args, **kwargs):
        if self.request.method == 'GET':
            return NewsReadSerializer
        return NewsWriteSerializer
    class Meta:
        model = NewsModel

При сохранении новой модели класса NewsItem получаю ошибку 400 Bad Request с сообщением о том, что поле author обязательно для заполнения. Пробовал определять метод validate_author для сериализатора NewsWriteSerializer, но это не дало результата.
Что делать?
GreyZmeem
class NewsWriteSerializer(models.Model)
У вас тут опечатка. Должен быть class NewsWriteSerializer(serializers.ModelSerializer)
А так, да - нужно определить метод validate_author.
dun
GreyZmeem
Поправил опечатку. Как правильно описать validate_author?
У меня сейчас вот так и не работает:
class NewsWriteSerializer(serializers.ModelSerializer):
    
    def validate_author(self):
        return self.request.user.id
    
    class Meta:
        model = NewsModel 
GreyZmeem
Для DRF < 3
def validate_user(self, attrs, source):
        attrs.update({'user': self.context['request'].user})
        return attrs
Для DRF >= 3 (не проверял)
def validate_user(self, value):
        return self.context['request'].user

Также для обоих версий надо в serializer переопределить поле user и поставить required=False, иначе DRF вообще не вызовет validate для этого поля.
user = serializers.PrimaryKeyRelatedField(source='user', required=False)

Также добавьте в свой View permission class который проверяет авторизацию (чтобы не было 500 ошибки при сохранении)
from rest_framework import permissions
 
class NewsList(class NewsList(ListCreateAPIView):
        permission_classes = [permissions.IsAuthenticated]
dun
Поправил сериализатор, который использую для записи:
class NewsWriteSerializer(serializers.ModelSerializer):
    
    author = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), required=False)
    # В DRF 3 требуется указывать queryset для PrimaryKeyRelatedField, source уже не катит
    
    def validate_author(self, value):
        return self.context['request'].user
       
    class Meta:
        model = NewsModel      
        fields = ('title', 'announce', 'full_text', 'author') 

Теперь хотя бы другая ошибка - news.author_id may not be NULL
Кстати, вставил возбуждение исключения в методе validate_author() и не увидел его. Есть подозрение, что этот метод вовсе не вызывается сейчас.
GreyZmeem
Что-то они сильно заморочились с проверками в 3
Поколупался в исходниках. Вобщем должно быть утсановлены allow_null & default.
Иначе в Field.validate_empty_values() будет вызван метод get_default() который сделает raise SkipField и никакие валидаторы для этого поля не запустяться.
class TestModelSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(
        queryset=User.objects.all(),
        allow_null=True,
        default=None
    )
 
    def validate_user(self, value):
        return self.context['request'].user
 
    class Meta:
        model = models.TestModel
dun
Спасибо большое за помощь! Именно так, как Вы написали, всё работает, как положено.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB