Django: télécharger un fichier et lire son contenu pour peupler un modèle?
Je suis nouveau à Django et je voudrais savoir quelle est la façon Django - d'ajouter des éléments dans une base de données non pas en entrant chaque champ à partir d'un formulaire html (comme c'est fait par défaut) mais en téléchargeant un seul fichier (par exemple un fichier json) qui sera utilisé pour peupler la base de données?
ainsi, disons que le modèle n'a que trois champs: Titre,description, Quantité. Et j'ai un fichier texte (myFile.txt) avec "myTitle:myDesc" écrit dedans.
ce que je veux, c'est juste un champ de fils qui va accepter un fichier texte pour que je puisse télécharger myFile.txt ainsi que le titre et la description seront lus à partir de ce fichier. Et en même temps la quantité sera demandée "normalement" dans une entrée de texte comme elle le serait par défaut (seul le titre et la description sont lus à partir du fichier).
bien sûr, la validation sur le fichier va être fait d'accepter ou de refuser le fichier téléchargé. Le problème, je suis confronté est que si j'ajoute un FileField le modèle, le fichier sera stocké dans le local de stockage. Je veux que le contenu de la fichier téléchargé pour être lu, utilisé pour créer une entrée dans le modèle, puis supprimé.
même l'administrateur ne devrait pas être en mesure d'ajouter manuellement un élément entrant le titre et la description sous forme HTML, mais seulement en téléchargeant un fichier. Est-ce que quelqu'un peut m'aider D'une manière Django?
4 réponses
Vous pouvez créer deux formulaires:
- Un formulaire basé sur
django.forms.Form
qui est utilisé pour obtenir le dossier de demande - une forme model qui est utilisée pour valider les champs model et créer un objet model
Ensuite, vous pouvez appeler la deuxième forme de la première, comme ceci:
class MyModelForm(ModelForm):
class Meta:
model = MyModel
class FileUploadForm(forms.Form):
file = forms.FileField()
def clean_file(self):
data = self.cleaned_data["file"]
# read and parse the file, create a Python dictionary `data_dict` from it
form = MyModelForm(data_dict)
if form.is_valid():
# we don't want to put the object to the database on this step
self.instance = form.save(commit=False)
else:
# You can use more specific error message here
raise forms.ValidationError(u"The file contains invalid data.")
return data
def save(self):
# We are not overriding the `save` method here because `form.Form` does not have it.
# We just add it for convenience.
instance = getattr(self, "instance", None)
if instance:
instance.save()
return instance
def my_view(request):
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
form.save()
else:
# display errors
Vous pouvez utiliser assistant de création de formulaire pour accomplir de telles tâches. L'idée de base est de créer deux formes: l'une avec le FileField
et l'autre formulaire avec le titre, les champs quantité de description.
l'utilisateur visualise le formulaire avec FileField
en premier. Une fois que l'utilisateur télécharge le fichier et soumet la demande, vous pouvez afficher l'autre formulaire avec les valeurs initiales lues à partir du fichier (vous pouvez aussi supprimer le fichier à cette étape).
concernant la fonctionnalité d'administration, vous pouvez lire sur la façon d'intégrer l'assistant de forme avec admin ici
j'ai trouvé un autre moyen de remplissage d'un modèle avant de l'enregistrer.
au lieu d'utiliser pre_save, ou en utilisant 2 formulaires différents, si nous utilisons l'administrateur.ModelAdmin, on peut simplement redéfinir la méthode save_model ():
def save_model(self, request, obj, form, change):
obj.user = request.user
# populate the model
obj.save()
# post actions if needed
Pour ce faire, vous devez écrire du code personnalisé. Chaque FileField a un connecté objet Fichier. Vous pouvez lire le contenu de cet objet fichier comme vous le feriez avec des fichiers en Python.
il y a bien sûr différents endroits où vous pouvez le faire. Vous pouvez remplacer la méthode forms/models save qui contient le champ de fichier. Si vous avez le modèle, vous pouvez utiliser pre_save
/post_save
de signaux.