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))


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow