2009-09-09 7 views
1

Dire que j'ai des choix définis comme suit:Magasin django forms.MultipleChoiceField dans les modèles directement

choices = (('1','a'), 
      ('2','b'), 
      ('3','c')) 

Et une forme qui rend ces valeurs et entrées dans un MultipleChoiceField,

class Form1(forms.Form): 
    field = forms.MultipleChoiceField(choices=choices) 

Qu'est-ce que le droit façon de stocker field dans un modèle.

Je peux bien sûr boucler le forms.cleaned_data['field'] et obtenir une valeur qui correspond à models.CommaSeperatedIntegerField.

Encore une fois, chaque fois que je récupère ces valeurs, je vais devoir boucler et convertir en options.

Je pense qu'il y a une meilleure façon de le faire, car de cette façon, je suis en train de ré-implémenter la fonction que CommaSeperateIntegerField est censée faire.

Répondre

9

La première chose que je considérerais est une meilleure normalisation de votre schéma de base de données; Si une seule instance de votre modèle peut avoir plusieurs valeurs pour ce champ, le champ devrait peut-être être un modèle lié avec un ForeignKey à la place.

Si vous utilisez Postgres, vous pouvez également utiliser un champ ARRAY; Django a maintenant built-in support.

Si vous ne pouvez pas faire l'une ou l'autre, vous devez essentiellement réimplémenter une (meilleure) version de CommaSeparatedIntegerField. La raison en est que CommaSeparatedIntegerField n'est rien d'autre que a plain CharField whose default formfield representation is a regex-validated text input. En d'autres termes, il ne fait rien qui vous soit utile. Ce que vous devez écrire est un ListField ou MultipleValuesField personnalisé qui attend une liste Python et retourne une liste Python, mais convertit en interne cette liste de/à partir d'une chaîne séparée par des virgules pour l'insertion dans la base de données. Lire le documentation on custom model fields; Je pense que dans votre cas, vous aurez besoin d'une sous-classe de CharField avec deux méthodes remplacées: to_python (convertir une chaîne CSV en liste Python) et get_db_prep_value (convertir une liste Python en chaîne CSV).

+0

Je pense qu'il serait plus approprié de sous-classer 'TextField', car un' CharField' attend l'argument max_length et un PostgreSQL 'INT []' non. –

+0

@danilo Je ne sais pas pourquoi PostgreSQL INT est pertinent ici, car l'idée est de stocker des entiers séparés par des virgules dans un champ non-entier. Dans tous les cas, sous-classer TextField serait bien aussi. –

+0

Désolé, j'ai apparemment mélangé deux différentes questions Stackoverflow. Mon point était - si quelqu'un veut stocker une liste dans un champ Postgres-'[-] [-] en créant un champ personnalisé, il devrait étendre' TextField' :) Mais ressemble à ce commentaire ne rentre pas ici. –

1

Je viens d'avoir ce même problème et la solution (pour moi) parce que Carl Meyer l'a dit. Je ne veux pas qu'une version normalisée de cette "liste de chaînes" soit juste avoir un CharField dans le modèle. De cette façon, votre modèle stockera la liste normalisée des éléments. Dans mon cas, ce sont les pays.

Ainsi, le modèle de déclaration est juste

countries = CharField(max_lenght=XXX) 

où XXX est une valeur précalculée de 2x ma liste de pays. Parce qu'il est plus simple pour nous d'appliquer une vérification pour voir si le pays actuel est dans cette liste plutôt que de le faire en tant que M2M à une table de pays.

+0

Je dois préciser que les documents officiels de django ne montrent pas clairement que le MultipleChoiceField se sérialisera dans une liste correcte de chaînes. –

Questions connexes