Django
Formes
Recherche…
Exemple ModelForm
Créez un ModelForm à partir d'une classe Model existante, en sous- ModelForm
:
from django import forms
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['item', 'order_date', 'customer', 'status']
Définir un formulaire Django à partir de zéro (avec des widgets)
Les formulaires peuvent être définis, de la même manière que les modèles, en sous- django.forms.Form
.
Différentes options de saisie sur le terrain sont disponibles, telles que CharField
, URLField
, IntegerField
, etc.
Vous trouverez ci-dessous la définition d'un formulaire de contact simple:
from django import forms
class ContactForm(forms.Form):
contact_name = forms.CharField(
label="Your name", required=True,
widget=forms.TextInput(attrs={'class': 'form-control'}))
contact_email = forms.EmailField(
label="Your Email Address", required=True,
widget=forms.TextInput(attrs={'class': 'form-control'}))
content = forms.CharField(
label="Your Message", required=True,
widget=forms.Textarea(attrs={'class': 'form-control'}))
Widget est la représentation par Django des balises HTML saisies par l'utilisateur et peut être utilisée pour rendre le HTML personnalisé pour les champs de formulaire (par exemple: une zone de texte est rendue pour le contenu saisi ici)
attrs
attributs sont des attributs qui seront copiés tels attrs
HTML rendu pour le formulaire.
Par exemple: content.render("name", "Your Name")
donne
<input title="Your name" type="text" name="name" value="Your Name" class="form-control" />
Suppression du champ modelForm en fonction de la condition de views.py
Si nous avons un modèle comme suit,
from django.db import models
from django.contrib.auth.models import User
class UserModuleProfile(models.Model):
user = models.OneToOneField(User)
expired = models.DateTimeField()
admin = models.BooleanField(default=False)
employee_id = models.CharField(max_length=50)
organisation_name = models.ForeignKey('Organizations', on_delete=models.PROTECT)
country = models.CharField(max_length=100)
position = models.CharField(max_length=100)
def __str__(self):
return self.user
Et une forme de modèle qui utilise ce modèle comme suit,
from .models import UserModuleProfile, from django.contrib.auth.models import User
from django import forms
class UserProfileForm(forms.ModelForm):
admin = forms.BooleanField(label="Make this User Admin",widget=forms.CheckboxInput(),required=False)
employee_id = forms.CharField(label="Employee Id ")
organisation_name = forms.ModelChoiceField(label='Organisation Name',required=True,queryset=Organizations.objects.all(),empty_label="Select an Organization")
country = forms.CharField(label="Country")
position = forms.CharField(label="Position")
class Meta:
model = UserModuleProfile
fields = ('admin','employee_id','organisation_name','country','position',)
def __init__(self, *args, **kwargs):
admin_check = kwargs.pop('admin_check', False)
super(UserProfileForm, self).__init__(*args, **kwargs)
if not admin_check:
del self.fields['admin']
Notez que sous la classe Meta dans le formulaire, j'ai ajouté une fonction d' initialisation que nous pouvons utiliser lors de l'initialisation du formulaire depuis views.py pour supprimer un champ de formulaire (ou d'autres actions). Je vais expliquer cela plus tard.
Donc, ce formulaire peut être utilisé à des fins d'inscription des utilisateurs et nous voulons tous les champs définis dans la classe Meta du formulaire. Mais que se passe-t-il si nous voulons utiliser le même formulaire lorsque nous modifions l'utilisateur, mais lorsque nous le faisons, nous ne voulons pas afficher le champ admin du formulaire?
Nous pouvons simplement envoyer un argument supplémentaire lorsque nous initialisons le formulaire en fonction d’une logique et supprimons le champ admin du backend.
def edit_profile(request,user_id):
context = RequestContext(request)
user = get_object_or_404(User, id=user_id)
profile = get_object_or_404(UserModuleProfile, user_id=user_id)
admin_check = False
if request.user.is_superuser:
admin_check = True
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
# Attempt to grab information from the raw form information.
profile_form = UserProfileForm(data=request.POST,instance=profile,admin_check=admin_check)
# If the form is valid...
if profile_form.is_valid():
form_bool = request.POST.get("admin", "xxx")
if form_bool == "xxx":
form_bool_value = False
else:
form_bool_value = True
profile = profile_form.save(commit=False)
profile.user = user
profile.admin = form_bool_value
profile.save()
edited = True
else:
print profile_form.errors
# Not a HTTP POST, so we render our form using ModelForm instance.
# These forms will be blank, ready for user input.
else:
profile_form = UserProfileForm(instance = profile,admin_check=admin_check)
return render_to_response(
'usermodule/edit_user.html',
{'id':user_id, 'profile_form': profile_form, 'edited': edited, 'user':user},
context)
Comme vous pouvez le voir, j'ai montré ici un exemple d'édition simple utilisant le formulaire que nous avons créé précédemment. Notez que lorsque j'ai initialisé le formulaire, j'ai transmis une variable admin_check
supplémentaire contenant True
ou False
.
profile_form = UserProfileForm(instance = profile,admin_check=admin_check)
Maintenant, si vous remarquez le formulaire que nous avons écrit plus tôt, vous pouvez voir que dans l' init, nous essayons d'attraper le admin_check
que nous passons ici. Si la valeur est False, il suffit de supprimer le champ admin
du formulaire et de l'utiliser. Et comme il s'agit d'un modèle, le champ admin ne peut pas être nul dans le modèle. Nous vérifions simplement si le post d'administration contenait un champ admin dans le post du formulaire, sinon nous avons défini False
dans le code de la vue.
form_bool = request.POST.get("admin", "xxx")
if form_bool == "xxx":
form_bool_value = False
else:
form_bool_value = True
Téléchargement de fichiers avec les formulaires Django
Tout d'abord, nous devons ajouter MEDIA_ROOT
et MEDIA_URL
à notre fichier settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Ici aussi, vous travaillerez avec ImageField
, donc souvenez-vous, dans ce cas, installez la bibliothèque Pillow ( pip install pillow
). Sinon, vous aurez une telle erreur:
ImportError: No module named PIL
Pillow est un fork de PIL, la bibliothèque de création d'images Python, qui n'est plus maintenue. L'oreiller est rétrocompatible avec PIL.
Django est livré avec deux champs de formulaire pour télécharger des fichiers sur le serveur, FileField
et ImageField
. Voici un exemple d'utilisation de ces deux champs dans notre formulaire.
forms.py:
from django import forms
class UploadDocumentForm(forms.Form):
file = forms.FileField()
image = forms.ImageField()
views.py:
from django.shortcuts import render
from .forms import UploadDocumentForm
def upload_doc(request):
form = UploadDocumentForm()
if request.method == 'POST':
form = UploadDocumentForm(request.POST, request.FILES) # Do not forget to add: request.FILES
if form.is_valid():
# Do something with our files or simply save them
# if saved, our files would be located in media/ folder under the project's base folder
form.save()
return render(request, 'upload_doc.html', locals())
upload_doc.html:
<html>
<head>File Uploads</head>
<body>
<form enctype="multipart/form-data" action="" method="post"> <!-- Do not forget to add: enctype="multipart/form-data" -->
{% csrf_token %}
{{ form }}
<input type="submit" value="Save">
</form>
</body>
</html>
Validation des champs et Validation du modèle (Modification de l'e-mail de l'utilisateur)
Il existe déjà des formulaires implémentés dans Django pour modifier le mot de passe de l'utilisateur, par exemple SetPasswordForm .
Il n'y a cependant pas de formulaire pour modifier le courrier électronique de l'utilisateur et je pense que l'exemple suivant est important pour comprendre comment utiliser un formulaire correctement.
L'exemple suivant effectue les vérifications suivantes:
- Les e-mails ont en effet changé - très utile si vous devez valider l'e-mail ou mettre à jour le courrier chimp;
- Les e-mails et les e-mails de confirmation sont les mêmes: le formulaire contient deux champs pour le courrier électronique. La mise à jour est donc moins sujette aux erreurs.
Et à la fin, il enregistre le nouvel e-mail dans l'objet utilisateur (met à jour l'e-mail de l'utilisateur). Notez que la __init__()
nécessite un objet utilisateur.
class EmailChangeForm(forms.Form):
"""
A form that lets a user change set their email while checking for a change in the
e-mail.
"""
error_messages = {
'email_mismatch': _("The two email addresses fields didn't match."),
'not_changed': _("The email address is the same as the one already defined."),
}
new_email1 = forms.EmailField(
label=_("New email address"),
widget=forms.EmailInput,
)
new_email2 = forms.EmailField(
label=_("New email address confirmation"),
widget=forms.EmailInput,
)
def __init__(self, user, *args, **kwargs):
self.user = user
super(EmailChangeForm, self).__init__(*args, **kwargs)
def clean_new_email1(self):
old_email = self.user.email
new_email1 = self.cleaned_data.get('new_email1')
if new_email1 and old_email:
if new_email1 == old_email:
raise forms.ValidationError(
self.error_messages['not_changed'],
code='not_changed',
)
return new_email1
def clean_new_email2(self):
new_email1 = self.cleaned_data.get('new_email1')
new_email2 = self.cleaned_data.get('new_email2')
if new_email1 and new_email2:
if new_email1 != new_email2:
raise forms.ValidationError(
self.error_messages['email_mismatch'],
code='email_mismatch',
)
return new_email2
def save(self, commit=True):
email = self.cleaned_data["new_email1"]
self.user.email = email
if commit:
self.user.save()
return self.user
def email_change(request):
form = EmailChangeForm()
if request.method=='POST':
form = Email_Change_Form(user,request.POST)
if form.is_valid():
if request.user.is_authenticated:
if form.cleaned_data['email1'] == form.cleaned_data['email2']:
user = request.user
u = User.objects.get(username=user)
# get the proper user
u.email = form.cleaned_data['email1']
u.save()
return HttpResponseRedirect("/accounts/profile/")
else:
return render_to_response("email_change.html", {'form':form},
context_instance=RequestContext(request))