Basically I have two models with one-to-one relationship. And I want retrieve information from one, when I call the other.
My models:
class Customer(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) class CurrentAccount(models.Model): customer_account = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='customer_account', blank=True, null=True) balance = models.FloatField()
So I can just call an POST and create an Customer, that customer will have id, first_name and last_name. For now everything is working.
But when I try to call my endpoint to create an CurrentAccount informing my Customer to relate, nothing happens.
My input:
{ "customer_account": 1 #this is some id from an Customer that is already created, "balance": 0.0 }
The output that I expected:
{ "id": 42, "customer_account": { "id": 2, "first_name": "Michele", "last_name": "Obama" } "balance": 0.0 }
The output that I received:
{ "id": 4, "balance": 0.0 }
As you can see, Django are ignoring the relationship (In the database the field ‘customer_account_id’ is null too, so isn’t just an problem with my return).
Here is my serializers:
class CustomerSerializer(serializers.ModelSerializer): class Meta: model = Customer fields = ('id', 'first_name', 'last_name') class CurrentAccountSerializer(serializers.ModelSerializer): customer_account = CustomerSerializer(read_only=True) class Meta: model = CurrentAccount fields = ('id', 'customer_account', 'balance')
And my views to create the CurrentAccount:
@api_view(['GET', 'POST']) def currentaccount_list_view(request): if request.method == 'GET': try: data = CurrentAccount.objects.all() ser = CurrentAccountSerializer(data, many=True) return response_success(data=ser.data) except Exception as e: return response_failed(e.args) elif request.method == 'POST': try: ser = CurrentAccountSerializer(data=request.data, context={'request': request}) if ser.is_valid(): ser.save() return response_success(data=ser.data) else: return response_failed('Something wrong with the input data') except Exception as e: return response_failed(e.args)
So I basically want to understand how the relationships works on Django and how to handle with DRF context, using serializers. I already looked the docs, but I still not understanding.
Advertisement
Answer
The problem is with the CurrentAccountSerializer
serializer, you set the customer_account
field as read only. You should also use two serializers with CurrentAccount
, the first to list existing instances and the second to create new ones.
serializers
class CustomerSerializer(serializers.ModelSerializer): class Meta: model = Customer fields = ('id', 'first_name', 'last_name') class CurrentAccountInfoSerializer(serializers.ModelSerializer): customer_account = CustomerSerializer(read_only=True) class Meta: model = CurrentAccount fields = ('id', 'customer_account', 'balance') class CurrentAccountCreationSerializer(serializers.ModelSerializer): customer_account = serializers.PrimaryKeyRelatedField(queryset=Customer.objests.all()) class Meta: model = CurrentAccount fields = ('id', 'customer_account', 'balance') def create(self, validated_data): return CurrentAccount.objects.create(**validated_data)
views
@api_view(['GET', 'POST']) def currentaccount_list_view(request): if request.method == 'GET': try: data = CurrentAccount.objects.all() ser = CurrentAccountInfoSerializer(data, many=True) return response_success(data=ser.data) except Exception as e: return response_failed(e.args) elif request.method == 'POST': try: ser = CurrentAccountCreationSerializer(data=request.data, context={'request': request}) if ser.is_valid(): instance = ser.save() return response_success(data=CurrentAccountInfoSerializer(instance=instance).data) else: return response_failed('Something wrong with the input data') except Exception as e: return response_failed(e.args)