Reputation: 157
Edit : These different types were just because of the django method:
request.POST.get("attribute")
which from Json data, returns me unicode.
The solution was to parse these values at the beginning
I have got a big problem, and i don't understand where it comes from.
On my Score model to save scores for a game, I need to compare values from the current score and the old one before saving. My error is that the types of my field are different whereas my object types are identical.
Maybe some code could explain :
class Score(models.Model):
map = models.ForeignKey(Map, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
score = models.FloatField()
class Meta:
unique_together = ('map', 'user')
def save(self, *args, **kwargs):
try:
oldScore = Score.objects.get(map=self.map, user=self.user)
except ObjectDoesNotExist:
oldScore = None
if oldScore is not None:
if oldScore.score < self.score:
print >> sys.stderr, type(oldScore), type(self)
print >> sys.stderr, type(oldScore.score), type(self.score)
oldScore.delete()
else:
return False
super(Score, self).save(*args, **kwargs)
return True
def __unicode__(self):
return str(self.map) + ' - ' + self.user.username + " : " + str(self.score)
and how i create the score and save it :
score = Score(map=map, user=user, score=score)
saved = score.save()
The result of debug prints :
<class 'main.models.score.Score'> <class 'main.models.score.Score'>
<type 'float'> <type 'unicode'>
I would like to compare my old with new score, but I can't because of these different types.
I know i could do some type conversions, but I'd like to know why this is happening, maybe I have failed on something stupid :s
ps: I'm under python 2.7 and Django 1.9.2 Thanks for helping me :)
Upvotes: 1
Views: 625
Reputation: 9359
That is some magic done by the model's metaclass. See, the model fields are defined as a Field
class (or its child, eg. FloatField
). But when you want to work with the instance of model, you dont want to have a FloatField
in the .score
property, you want to have the actual value there, right? And that is done by the ModelBase.__metaclass__
when the model's instance is created.
Now when you are saving the value, it's completely ok, that the type of score
is unicode
- let's say you received the data via form, and all the data you receive are unicode
. The value is converted (and validated) when saving. Django looks what kind of data is expected (float), and it tries to convert the value. If that wont work, it will raise an exception. Otherwise the converted value will be stored.
so what you want to do with your save method is this:
def save(self, *args, **kwargs):
if self.pk: # the model has non-empty primary key, so it's in the db already
oldScore = Score.objects.get(self.pk)
if oldScore.score > float(self.score):
# old score was higher, dont do anything
return False
super(Score, self).save(*args, **kwargs)
return True
Upvotes: 2