Django REST Framework - аргумент int () должен быть строкой, байтовым объектом или числом, а не 'SimpleLazyObject' - PullRequest
0 голосов
/ 16 мая 2018

Я использую Django 2.0 и Django REST Framework для записи REST API.

my settings.py содержит настройки для DRF

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated'
    ]
}

икаждый запрос должен быть подписан любым методом DEFAULT_AUTHENTICATION_CLASSES.

In contacts / serializers.py

class ContactSerializer(serializers.HyperlinkedModelSerializer):
    phone_numbers = ContactPhoneNumberSerializer(source='contactphonenumber_set', many=True)

    class Meta:
        model = Contact
        fields = ('url', 'first_name', 'last_name', 'full_name', 'date_of_birth', 'phone_numbers')

    def create(self, validated_data):
        phone_numbers = validated_data.pop('contactphonenumber_set')
        emails = validated_data.pop('contactemail_set')
        instance = Contact.objects.create(**validated_data)
        for phone_data in phone_numbers:
            ContactPhoneNumber.objects.create(contact=instance, **phone_data)
        return instance

print(validated_data) дает следующие данные

{'first_name': 'Anshuman', 'last_name': 'Upadhyay', 'date_of_birth': datetime.date(2018, 5, 15), 'contactphonenumber_set': [], 'user_id': <SimpleLazyObject: <User: anuj>>}

user_id равно SimpleLazyObject, что дает ошибку при сохранении

TypeError: int() argument must be a string, a bytes-like object or a number, not 'SimpleLazyObject'

Ошибка находится на линии instance = Contact.objects.create(**validated_data)

Как мне пройтиаутентифицированный пользователь в user поле?

Редактировать 2: contacts / models.py

class Contact(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100, blank=True, null=True)
    date_of_birth = models.DateField(blank=True, null=True)

контакты/views.py

class ContactViewSet(viewsets.ModelViewSet):
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)

    def get_queryset(self):
        return Contact.objects.filter(user=self.request.user)

    def perform_create(self, serializer):
        serializer.save(user_id=self.request.user)

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Вы можете использовать self.context для этого http://www.django -rest-framework.org / api-guide / serializers / # incl-extra-context

Если вы используете GenericAPIView контекст передается автоматически

Прежде всего вам не нужно передавать user_id в ваш сериализатор, а затем вам нужно обновить ContactSerializer, чтобы он выглядел следующим образом.

class ContactSerializer(serializers.HyperlinkedModelSerializer):
    phone_numbers = ContactPhoneNumberSerializer(source='contactphonenumber_set', many=True)

    class Meta:
        model = Contact
        fields = ('url', 'first_name', 'last_name', 'full_name', 'date_of_birth', 'phone_numbers')

    def create(self, validated_data):
        phone_numbers = validated_data.pop('contactphonenumber_set')
        emails = validated_data.pop('contactemail_set')
        instance = Contact.objects.create(user=self.context['request'].user, **validated_data)
        for phone_data in phone_numbers:
            ContactPhoneNumber.objects.create(contact=instance, **phone_data)
        return instance

Вы не должны перезаписывать perform_create

class ContactViewSet(viewsets.ModelViewSet):
    serializer_class = ContactSerializer
    permission_classes = (IsAuthenticated, AdminAuthenticationPermission,)

    def get_queryset(self):
        return Contact.objects.filter(user=self.request.user)
0 голосов
/ 16 мая 2018

Предполагается, что ваша модель Contact содержит отношение FK с AuthUserModel. Итак, ваш оператор создания экземпляра должен выглядеть так:

user = get some user instance from `validated` data
instance = Contact.objects.create(user=user,**validated_data)


Это общее решение для вашего вопроса. Если вы добавите модель Contact, мы можем помочь вам

UPDATE-1
Измените create(), как показано ниже,

def create(self, validated_data):
    phone_numbers = validated_data.pop('contactphonenumber_set')
    emails = validated_data.pop('contactemail_set')
    user = validated_data.pop('user') # change 1
    instance = Contact.objects.create(user=user, **validated_data) # # change 2
    for phone_data in phone_numbers:
        ContactPhoneNumber.objects.create(contact=instance, **phone_data)
    return instance


Update-2
Вы можете использовать user = serializers.CurrentUserDefault() в сериализаторе, как показано ниже,

class ContactSerializer(serializers.HyperlinkedModelSerializer):
    phone_numbers = ContactPhoneNumberSerializer(source='contactphonenumber_set', many=True)
    user = serializers.CurrentUserDefault()

    class Meta:
        model = Contact
        fields = ('url', 'first_name', 'last_name', 'full_name', 'date_of_birth', 'phone_numbers')

    def create(self, validated_data):
        phone_numbers = validated_data.pop('contactphonenumber_set')
        emails = validated_data.pop('contactemail_set')
        user = validated_data.pop('user_id') 
        instance = Contact.objects.create(user=user, **validated_data) 
        for phone_data in phone_numbers:
            ContactPhoneNumber.objects.create(contact=instance, **phone_data)
        return instance


CurrentUserDefault() выполняет ту же работу, что и self.context.get('request').user

...