web-dev-qa-db-fra.com

Comment stocker une valeur vide en tant que Integerfield

J'ai vu tous les threads similaires, lu la documentation et essayé plusieurs combinaisons pour stocker une valeur vide sous la forme IntegerField dans la base de données et échouant à chaque fois. 

J'utilise MySQL. 

Mon models.py définit un champ age=models.IntegerField(). Je renseigne la base de données à partir d'un fichier csv, et certaines cellules n'ont aucune valeur. Django docs dit:

Field.null

If True, Django will store empty values as NULL in the database. Default is False.
Note that empty string values will always get stored as empty strings, not as NULL. 

Étant donné que je travaille avec IntegerField, je souhaite qu'une chaîne vide (une cellule vide du csv) soit stockée sous la forme NULL dans db. Par conséquent, je (pense) devoir ajouter null=True au champ age. En fait, j'ai essayé plus que ça:

age=models.IntegerField()
age=models.IntegerField(null=True)
age=models.IntegerField(null=True, blank=True)
age=models.IntegerField(null=True, blank=True, default=None)

et chaque fois que j'insère une chaîne vide dans une base de données, je suis 

ValueError: invalid literal for int() with base 10: ''

Vous savez quoi d'autre puis-je faire?

18
nutship

Une chaîne n'est pas un entier. et une chaîne vide n'est pas None ou NULL. Ce que vous devez faire, c'est intercepter les cas où le champ est vide, puis le convertir en None.

foo = "something" # "something" is coming from your CSV file

try:
   val = int(foo)
except ValueError:
   # foo is something that cannot be converted to
   # a number. It could be an empty string, or a
   # string like 'hello'
   # provide a default value
   val = None

# Now use val to insert into the database
f = MyModel()
f.age = val
f.save()

blank est strictement destiné à la validation initiale; cela n'a aucun impact sur la base de données:

Notez que ceci est différent de null. null est purement lié à la base de données, alors que blank est lié à la validation. Si un champ a blank=True, la validation du formulaire autorisera la saisie d'une valeur vide. Si un champ a blank=False, il sera requis.

null concerne la base de données:

Si True, Django stockera les valeurs vides comme NULL dans la base de données. La valeur par défaut est False.

IntegerField requiert une valeur pouvant être convertie en un entier. Ainsi, lorsque vous transmettez une chaîne vide , il ne peut pas la convertir et déclenche une exception. Au lieu de cela, si vous passez None et que vous avez age = models.IntegerField(null=True), il sait le stocker correctement.

Résumer:

  • age = models.IntegerField()

    Ce champ est obligatoire et nécessite une valeur entière valide. Il n'acceptera pas None et n'aura aucune valeur NULL dans la base de données. Les valeurs valides sont -2147483648 à 2147483647

  • age = models.IntegerField(null=True)

    Ce champ est obligatoire (validation du formulaire). Si le champ a pour valeur None, il sera traduit en NULL dans la base de données.

  • age = models.IntegerField(blank=True, null=True)

    Ce champ n'est pas obligatoire (validation du formulaire). Si le champ est passé dans None, il sera traduit en NULL

  • age = models.IntegerField(blank=True)

    Le champ n'est pas obligatoire (validation du formulaire), mais une valeur entière valide doit être transmise car la base de données n'accepte pas la valeur null. Généralement, vous lui attribuez une valeur par défaut avec default=0 ou effectuez une validation avant de soumettre la valeur à orm.

39
Burhan Khalid

Essayez de passer None à ce champ pas une chaîne vide ''

3
ndpu

Vous pouvez remplacer la méthode 'clean' dans votre classe de formulaire, puis nettoyer les données de nombre entier pour éviter l'envoi d'une chaîne vide, voir l'exemple ci-dessous:

def clean(self):
    self.cleaned_data = super(YourForm, self).clean()
    if self.cleaned_data['age'] == '': self.cleaned_data['age'] = None
    return self.cleaned_data
0
Simon Chen