Reputation: 3
I have two classes, class Amount and Transaction
class Account(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
account_number = models.BigIntegerField(unique=True)
currency = models.CharField(max_length=3)
balance = models.DecimalField(max_digits=20, decimal_places=2, default=0)
class Transaction(models.Model):
sender_account_number = models.BigIntegerField()
recipient_account_number = models.BigIntegerField()
amount = models.DecimalField(max_digits=20, decimal_places=2)
date_creation = models.DateTimeField(auto_now_add=True)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
My serializers:
class TransactionSerializer(serializers.ModelSerializer):
class Meta:
model = Transaction
fields = ['sender_account_number', 'recipient_account_number', 'amount', 'date_creation', 'account']
extra_kwargs = {
'date_creation': {'read_only': True},
}``
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ['id', 'account_number', 'currency', 'balance', 'user']
extra_kwargs = {
'balance': {'read_only': True},
'user': {'read_only': True},
}
I want to add a transaction to the database, but so that it automatically sets my account_id based on the account number, because one user can have multiple accounts*. I tried the perform_create method
def perform_create(self, serializer):
serializer.save(account=Account.objects.values('id').filter(
account_number=self.request.data['sender_account_number']))
but I failed. I get error
{
"account": [
"This field is required."
]
}
for example, I want to send these data
{
"sender_account_number": 346,
"recipient_account_number": 546,
"amount": 60
}
and Post method:
def post(self, request):
serializer = TransactionSerializer(data=request.data)
serializer.is_valid(raise_exception=True):
return Response(serializer.data)
How to solve it?
Upvotes: 0
Views: 983
Reputation: 60
you have to tell your transaction serializer that account is a foreign key. And hence, it would expect an object instead of a string. add account = serializers.StringRelatedField() like so
class TransactionSerializer(serializers.ModelSerializer):
account = serializers.StringRelatedField()
class Meta:
model = Transaction
fields = ['sender_account_number', 'recipient_account_number', 'amount', 'date_creation', 'account']
extra_kwargs = {
'date_creation': {'read_only': True},
}``
You do not need the perform create function if you do that. serializer should automatically add it for you. you just have to retrieve from your account models, the instance with your account number. then pass it into the serializer.save() after checking if serializer is valid. like so
def post(self, request):
account_number = request.data.get('sender_account_number')
account = Account.objects.get(account_number=account)
serializer = TransactionSerializer(data=request.data)
serializer.is_valid(raise_exception=True):
serializer.save(account = account_number)
return Response(serializer.data)
Upvotes: 1