Petar
Petar

Reputation: 3

Django rest framework - "This field is required."

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

Answers (1)

soby
soby

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

Related Questions