Django REST框架 - int()参数必须是字符串,类字节对象或数字,而不是' SimpleLazyObject'

时间:2018-05-16 15:23:50

标签: django django-rest-framework

我使用Django 2.0Django REST Framework撰写REST API

我的 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方法对每个请求进行签名。

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_idSimpleLazyObject,因此在保存

时出错
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 :(得分:1)

假设您的Contact模型与AuthUserModel包含FK关系。因此,您的实例创建语句必须是这样的,

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


更新-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

的工作相同

答案 1 :(得分:1)

您可以self.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)

    df = pd.read_csv(url,skiprows=7)