简体   繁体   中英

django rest framework : nested model get not working. 'str' object has no attribute 'values'

I have a customer model in Bcustomer app that extends the django User model, So I will save the basic details such as name in User table and the remaining data (city, etc) in customer table.

Saving is working perfectly. But now it is showing the following error when I call the GET method.

AttributeError at /api/v1/customer 'str' object has no attribute 'values'

Request Method: GET

bcustomer/models.py

class BCustomer(models.Model):

    customer = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True, blank=True )
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=256)
    state = models.CharField(max_length=50)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, db_index=True, on_delete=models.CASCADE, related_name='customer_creator')
    # more fields to go

    def __str__(self):
        # return str(self.name) (This should print first and last name in User model)

    class Meta:
        app_label = 'bcustomer'

bcusomer/serializers.py

class CustomerDetailsSerializer(serializers.ModelSerializer):
    class Meta:
        model = BCustomer
        fields = ('city', 'phone')


class CustomerSerializer(serializers.ModelSerializer):
    customer_details = CustomerDetailsSerializer()

    class Meta:
        model = get_user_model()
        fields = ('id','first_name', 'email', 'customer_details')

    def create(self, validated_data):
        request = self.context.get('request')
        customer_details_data = validated_data.pop('customer_details')
        customer_user = get_user_model().objects.create(**validated_data)
        BCustomer.objects.create(customer=customer_user, user=request.user, **customer_details_data)
        customer_user.customer_details = customer_details_data
        return customer_user

class CustomerListSerializer(serializers.ModelSerializer):
    model = get_user_model()
    fields = '__all__'

    class Meta:
        model = get_user_model()
        fields = '__all__'

bcustomer/views.py

class CustomerViewSet(viewsets.ModelViewSet):
    customer_photo_thumb = BCustomer.get_thumbnail_url
    permission_classes = [permissions.IsAuthenticated, TokenHasReadWriteScope]
    queryset = BCustomer.objects.all()
    serializer_class = CustomerSerializer

    def get_queryset(self):
        queryset = BCustomer.objects.all()
        return queryset

    def get_serializer_class(self):
        if self.action == 'list' or self.action == 'retrieve':
            return CustomerListSerializer
        return CustomerSerializer

bcustomer/urls.py

router.register(r'customer', views.CustomerViewSet, 'customers')

Data post parameter format

{
    "first_name":"Myname",
    "email":"testemail@gmail.com",
    "customer_details": {
        "city":"citys",
        "phone":"04722874567",
    }
}

You should remove model and fields from CustomListSerializer

class CustomerListSerializer(serializers.ModelSerializer):
    class Meta:
        model = get_user_model()
        fields = '__all__'
customer_details = CustomerDetailsSerializer()

You need to set the source argument to point to the user model's customer. Most probably:

customer_details = CustomerDetailsSerializer(source='customer')

(or maybe source='bcustomer' , not sure if it reversed the field name or class name).

On a side not, you should not need the ListSerializer at all. The list method will call the serializer with the many=True argument on CustomerSerializer which will create the ListSerializer appropriately.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM