Django deserialization of a natural key that contains another natural key

883 Views Asked by At

I am creating a model that records player stats.
By manually entering data points first, I am able to have Django serialize data with natural keys into a json file just fine using dumpdata --natural. My plan is to copy this serialized format to mass insert other data points; the problem is that Django won't deserialize the json back into the database using loaddata. The error thrown is

DeserializationError: int() argument must be a string or a number, not 'list'

I've simplified the complaining json data a little but it looks like this:
{"pk": 1, "model": "nba.metric", "fields": {"player": ["Kobe Bryant", ["Lakers", 2012]]}}

My models are like so:

class TeamManager(models.Manager):
    def get_by_natural_key(self, name, season):
        return self.get(name=name, season=season)
class Team(models.Model):
    name = models.CharField(max_length=20)
    season = models.IntegerField()
    class Meta:
        unique_together = ('name', 'season')
    objects = TeamManager()
    def natural_key(self):
        return (self.name, self.season)

class PlayerManager(models.Manager):
    def get_by_natural_key(self, name, team):
        return self.get(name=name, team=team)
class Player(models.Model):
    name = models.CharField(max_length=100)
    team = models.ForeignKey(Team)
    class Meta:
        unique_together = ('name', 'team')
    objects = PlayerManager()
    def natural_key(self):
        return (self.name, self.team.natural_key())

class Metric(models.Model):
    player = models.ForeignKey(Player)
    # ...

Any input is greatly appreciated, thanks!

1

There are 1 best solutions below

0
On

I had the exact same (tricky) problem and managed to solve it this way. You need to change the get_by_natural_key method so that it accepts the 2 arguments implicitely given by the team.natural_key() you used inside Player.natural_key(). Try this:

class PlayerManager(models.Manager):
    def get_by_natural_key(self, name, team_name, team_season):
        return self.get(name=name, team__name=team_name, team__season=team_season)

If you have found another solution where Django handles this automatically, I would be glad to hear it.