Création de champs de modèles dynamiques dans django
C'est un problème concernant django.
J'ai un modèle de dire "Automobiles". Cela aura des champs de base comme "Couleur","Véhicule Propriétaire Nom", "le Coût du Véhicule".
Je veux fournir un formulaire où l'utilisateur peut ajouter des champs supplémentaires en fonction de l'automobile qu'il est ajout. Par exemple, si l'utilisateur est l'ajout d'une "Voiture", il va de champs supplémentaires dans le formulaire, de manière dynamique au moment de l'exécution, comme la Voiture "Kilométrage", "Cal Fabricant".
Supposons que si l'utilisateur veut ajouter un "Camion", il va ajouter de la Charge qui peut être porté", "Permis", etc.
Comment puis-je réaliser cela dans django?
Il y a deux questions ici:
- Comment fournir un formulaire où l'utilisateur peut ajouter de nouveaux champs au moment de l'exécution?
- Comment faire pour ajouter les champs de la base de données de sorte qu'il peut être récupéré/interrogé plus tard?
source d'informationauteur thestudent
Vous devez vous connecter pour publier un commentaire.
Il existe quelques approches:
Il semble que vous voulez le dernier, mais je ne suis pas sûr que c'est le meilleur pour vous. Django est très facile de modifier/mettre à jour, si les admins veulent champs supplémentaires, il suffit d'ajouter eux et de les utiliser au sud de migrer. Je n'aime pas les génériques de clé/valeur schémas de base de données, le point de l'ensemble d'un cadre puissant comme Django, c'est que vous pouvez facilement écrire et de réécrire des schémas personnalisés sans avoir recours à des principes généraux.
Si vous devez autoriser les utilisateurs du site/administrateurs de définir directement leurs données, je suis sûr que d'autres vont vous montrer comment faire les deux premières approches ci-dessus. La troisième approche est ce que vous demandez, et un peu plus fou, je vais vous montrer comment le faire. Je ne recommande pas de l'utiliser dans presque tous les cas, mais il est parfois approprié.
Les modèles de dynamique de
Une fois que vous savez quoi faire, c'est relativement simple. Vous aurez besoin de:
1. Le stockage de la définition du modèle
C'est à vous de voir. J'imagine que vous aurez un modèle
CustomCarModel
etCustomField
pour permettre à l'utilisateur/administrateur de définir et de stocker les noms et les types de champs que vous le souhaitez. Vous n'avez pas de miroir Django champs directement, vous pouvez faire vos propres types que l'utilisateur peut mieux comprendre.Utiliser un
forms.ModelForm
en ligne jeux de formulaires pour permettre à l'utilisateur de construire leur classe personnalisée.2. Modèle abstrait
Encore une fois, c'est très simple, il suffit de créer un modèle de base avec la commune de champs/méthodes pour tous vos modèles de dynamique. Ce modèle abstrait.
3. Construire un modèle dynamique
Définir une fonction qui prend les informations nécessaires (peut-être une instance de votre classe à partir d' #1) et produit un modèle de classe. C'est un exemple de base:
4. Code pour mettre à jour les tables de base de données
Le code ci-dessus va générer un modèle dynamique pour vous, mais ne va pas créer les tables de la base. Je recommande d'utiliser le Sud pour la manipulation de la table. Ici sont un couple de fonctions qui vous pouvez vous connecter à pré/post-enregistrement des signaux:
Et là vous l'avez! Vous pouvez appeler
get_custom_car_model()
de livrer un django modèle, que vous pouvez utiliser pour faire des django requêtes:Problèmes
get_custom_car_model
pour chaque instance de votre définitions dans leclass_prepared
signal pour votre modèle de définition.ForeignKeys
/ManyToManyFields
peut ne pas fonctionner (je n'ai pas essayé)Aperçu
Si vous êtes bien avec la complication supplémentaire et des problèmes, profitez-en! C'est en cours d'exécution, il fonctionne exactement comme prévu grâce à Django et Python flexibilité. Vous pouvez nourrir votre modèle dans Django
ModelForm
pour permettre à l'utilisateur de modifier leurs instances, et d'effectuer des requêtes à l'aide de la base de données de champs directement. Si il ya quelque chose que vous ne comprenez pas dans le ci-dessus, vous êtes probablement mieux de ne pas prendre cette approche (j'ai volontairement pas expliqué ce que certains concepts sont pour les débutants). Keep it Simple!Je ne pense vraiment pas que beaucoup de gens ont besoin de cela, mais je l'ai utilisé moi-même, où nous avons eu beaucoup de données dans les tables et vraiment, vraiment besoin pour permettre aux utilisateurs de personnaliser les colonnes, ce qui a changé rarement.
Base de données
Tenir compte de votre conception de base de données une fois de plus.
Vous devriez penser en termes de la façon dont ces objets que vous souhaitez représenter rapportent les uns aux autres dans le monde réel, et puis essayer de généraliser les relations autant que vous le pouvez, (donc au lieu de dire chaque camion a un permis, vous dire que chaque véhicule a un attribut qui peut être soit un permis, d'une charge ou d'autre chose).
Donc permet de l'essayer:
Si vous dites que vous avez un véhicule et chaque véhicule peut avoir plusieurs attributs spécifiés considérer les modèles suivants:
Comme indiqué avant, c'est une idée générale qui vous permet d'ajouter autant d'attributs pour chaque véhicule comme vous le souhaitez.
Si vous voulez spécifique ensemble d'attributs à la disposition de l'utilisateur vous pouvez utiliser
choix
dans leAttribute.type
champ.Maintenant, peut-être que vous voulez chaque véhicule de sorte à avoir son propre ensemble d'attributs disponibles. Cela peut être fait en ajoutant encore un autre modèle et définir des relations de clé étrangère des deux
Vehicle
etAttribute
modèles.Cette façon, vous avez une image claire de la façon dont chaque attribut se rapporte à un véhicule.
Formes
En fait, avec cette conception de base de données, vous aurez besoin de deux formulaires pour ajouter des objets dans la base de données. Plus spécifiquement, un modèle de formulaire pour un véhicule et un modèle formset pour les attributs. Vous pouvez utiliser jQuery pour ajouter dynamiquement plus d'articles sur le
Attribute
formset.Note
Vous pouvez également séparer
Attribute
classe deAttributeType
etAttributeValue
de sorte que vous n'avez pas redondant types d'attributs stockés dans votre base de données ou si vous souhaitez limiter l'attribut de choix pour l'utilisateur, mais de garder la possibilité d'ajouter plus de types avec Django admin du site.Pour être tout à fait cool, vous pouvez utiliser la saisie semi-automatique sur votre formulaire pour suggérer existant types d'attributs de l'utilisateur.
Soupçon: en savoir plus sur normalisation de base de données.
D'autres solutions
Comme suggéré dans la réponse précédente par Stuart Marais
D'autre part, vous pourriez dur code vos modèles pour chaque type de véhicule, de sorte que chaque type de véhicule est représenté par la sous-classe du véhicule de base et chaque sous-classe peut avoir ses propres attributs, mais que des solutions n'est pas très souple (si vous avez besoin de souplesse).
Vous pouvez également garder la représentation JSON d'supplémentaire des attributs d'un objet dans un champ de base de données, mais je ne suis pas sûr que ce serait utile lors de l'interrogation des attributs.
Voici mon test simple dans django shell - j'ai juste tapé et il semble bien fonctionner-
Il semble très simple - je ne sais pas pourquoi il ne devrait pas être considérée comme une option de la Réflexion est très commun est d'autres langages comme C# ou Java - de toute façon, je suis très nouveau à django choses-
Vous parlez à une extrémité avant de l'interface, ou dans l'admin de Django?
Vous ne pouvez pas créer de véritables champs à la volée comme ça, sans beaucoup de travail sous le capot. Chaque modèle et chaque champ dans Django est associé à une table et de colonne dans la base de données. Pour ajouter de nouveaux champs nécessite généralement cru sql, ou des migrations à l'aide du Sud.
À partir d'une extrémité avant de l'interface, vous pouvez créer des champs pseudo, et de les stocker dans un format json dans un seul champ de modèle.
Par exemple, créer un other_data champ de texte dans le modèle. Ensuite, permettre aux utilisateurs de créer des champs, et de les stocker comme {'userfield':'userdata','kilométrage':54}
Mais je pense que si vous êtes en utilisant un nombre fini de classe comme les véhicules, vous devez créer un modèle de base avec la base des caractéristiques du véhicule, puis de créer des modèles qui hérite de la base modèle pour chacun des types de véhicule.
etc