0

I have form data that I want to serialize to create two objects, Account and AccountClub. AccountClub is the in between table between Account and Club with additional fields, rakeback and chip_value.

I can serialize the formdata but when i call the is.valid() function before saving, I get returned an error with the manytomany fields empty

Here is my models:

class Account(models.Model):
nickname = models.CharField(max_length=64)
club_account_id = models.IntegerField()
agent_players = models.ManyToManyField(
    AgentPlayer, related_name="accounts")
clubs = models.ManyToManyField(
    Club, through='AccountClub', related_name='accounts')

def __str__(self):
    return f"{self.nickname} ({self.club_account_id})"

class AccountClub(models.Model):
    account = models.ForeignKey(
        Account, on_delete=models.CASCADE, related_name='club_deal')
    club = models.ForeignKey(
        Club, on_delete=models.CASCADE, related_name='account_deal')
    rakeback_percentage = models.DecimalField(
        max_digits=3, decimal_places=3, validators=[MinValueValidator(Decimal('0.01'))])
    chip_value = models.DecimalField(max_digits=3, decimal_places=2, validators=[
                                     MinValueValidator(Decimal('0.01'))])

    def __str__(self):
        return f"{self.account.nickname} belongs to {self.club.name} with rakeback of {self.rakeback_percentage} and chip value of {self.chip_value}"

Serializers:

class AgentPlayerSerializer(serializers.ModelSerializer):

class Meta:
    model = AgentPlayer
    fields = "__all__"


class ClubSerializer(serializers.ModelSerializer):
    agent_players = AgentPlayerSerializer(many=True)

    class Meta:
        model = Club
        fields = '__all__'


class AccountSerializer(serializers.ModelSerializer):
    agent_players = AgentPlayerSerializer(many=True)
    clubs = ClubSerializer(many=True)

class Meta:
    model = Account
    fields = [
        'nickname',
        'club_account_id',
        'agent_players',
        'clubs',
    ]

def create(self, validated_data):
    rakeback_percentage = validated_data.pop('rakeback_percentage')
    chip_value = validated_data.pop('chip_value')
    club = validated_data.club
    account = Account.objects.create(**validated_data)
    account.account_club.rakeback_percentage = rakeback_percentage
    account.account_club.chip_value = chip_value
    AccountClub.create(account=account, club=club,
                       rakeback_percentage=rakeback_percentage, chip_value=chip_value)
    return account

views.py:

def create_account(request):
data = FormParser().parse(request)
serializer = AccountSerializer(data=data)
if serializer.is_valid():
    serializer.save()
    next = request.POST.get('next', '/')
    return HttpResponseRedirect(next, status=201)
return JsonResponse(serializer.errors, status=400)

1 Answers1

0

your clubs field on the Account model is not blank=True so you can not create an account without at least a club. so you can not do

account = Account.objects.create(**validated_data)

and then do

AccountClub.create(account=account, club=club, rakeback_percentage=rakeback_percentage, chip_value=chip_value)

you may change your Account model code to:

clubs = models.ManyToManyField(Club, through='AccountClub', blank=True, related_name='accounts')

also checkout these links:

aasmpro
  • 554
  • 9
  • 21
  • I can get is_valid = True with the method above, print(repr(serializer)) gets me: a query dict with all the data from response.data but when save() is called. The validated data only shows 'nickname' and 'club_account_id' – Junzhong Loo May 14 '20 at 12:29
  • @JunzhongLoo i don't really know what's going on there, but `nickname` error may be about the length or no data. in case of `club_account_id` as said, you can not create account object without an account_club, so when you call create on `Account.object.create(**validated_data)` there is no account_club object in that data and you get error. may you provide some data about how you send and get data in that serializer? it may help. – aasmpro May 15 '20 at 09:50
  • There is no error with `nickname` and `club_account_id`. I have a nested serialization in `AccountSerializer` for `agent_player` and `clubs`: `class AccountSerializer(serializers.ModelSerializer): agent_players = AgentPlayerSerializer(many=True) clubs = ClubSerializer(many=True, required=False)` In my data, `agent_players` and `clubs` value is the primary key. When pass through the serializer, it is not read or call the `agent_player` and `club` in the database – Junzhong Loo May 15 '20 at 12:00