Sök…


ModelForm-exempel

Skapa en ModelForm från en befintlig ModelForm genom att underklassera ModelForm :

from django import forms

class OrderForm(forms.ModelForm):
    class Meta:
        model = Order
        fields = ['item', 'order_date', 'customer', 'status']

Definiera en Django-form från grunden (med widgets)

Formulär kan definieras på liknande sätt som modeller genom att underklassera django.forms.Form .
Olika fältinmatningsalternativ är tillgängliga som CharField , URLField , IntegerField , etc.

Definiera ett enkelt kontaktformulär kan ses nedan:

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 är Djangos representation av HTML-användarinmatningstaggar och kan användas för att återge anpassad html för formulärfält (t.ex.: som en textruta visas för innehållsinmatningen här)

attrs är attribut som kommer att kopieras på samma sätt som till den återgivna html för formuläret.

content.render("name", "Your Name") : content.render("name", "Your Name") ger

<input title="Your name" type="text" name="name" value="Your Name" class="form-control" />

Ta bort en modellFords fält baserat på villkor från views.py

Om vi har en modell enligt följande,

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

Och en modellform som använder den här modellen enligt följande,

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']

Lägg märke till att under metaklassen i formulär har jag lagt till en init- funktion som vi kan använda medan jag initialiserar formuläret från views.py för att radera ett formulärfält (eller några andra åtgärder). Jag kommer att förklara det senare.

Så det här formuläret kan användas för användarregistreringsändamål och vi vill att alla fält definieras i metaklassen på formuläret. Men tänk om vi vill använda samma formulär när vi redigerar användaren men när vi inte vill visa administrationsfältet för formuläret?

Vi kan helt enkelt skicka ett ytterligare argument när vi initierar formuläret baserat på någon logik och tar bort adminfältet från 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)

Som ni ser har jag visat här ett enkelt redigeringsexempel med hjälp av det formulär vi skapade tidigare. Lägg märke till när jag initialiserade formuläret passerade jag en ytterligare admin_check variabel som innehåller antingen True eller False .

profile_form = UserProfileForm(instance = profile,admin_check=admin_check)

Nu om du märker det formulär vi skrev tidigare kan du se att i init försöker vi fånga admin_check parametern som vi passerar härifrån. Om värdet är falskt tar vi helt enkelt bort admin från formuläret och använder det. Och eftersom detta är ett modellformulär kan adminfältet inte vara noll i modellen, vi kontrollerar helt enkelt om formulärinlägget hade adminfält i formulärposten, om inte sätter vi det till False i visningskoden i följande kod i vyn.

form_bool = request.POST.get("admin", "xxx")
if form_bool == "xxx":
    form_bool_value = False
else:
    form_bool_value = True

Filuppladdningar med Django-formulär

Först måste vi lägga till MEDIA_ROOT och MEDIA_URL i vår settings.py fil

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

Även här kommer du att arbeta med ImageField , så kom ihåg att i sådana fall installera Pillow-bibliotek ( pip install pillow ). Annars kommer du att ha ett sådant fel:

ImportError: No module named PIL

Kudde är en gaffel från PIL, Python Imaging Library, som inte längre underhålls. Kudden är bakåtkompatibel med PIL.

Django kommer med två formfält för att ladda upp filer till servern, FileField och ImageField , följande är ett exempel på att använda dessa två fält i vår form

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>

Validering av fält och Commit to model (Ändra användar-e-post)

Det finns redan implementerade formulär inom Django för att ändra användarlösenordet, ett exempel är SetPasswordForm .

Det finns dock inga formulär för att ändra användarens e-postmeddelande och jag tror att följande exempel är viktigt för att förstå hur man använder ett formulär korrekt.

Följande exempel utför följande kontroller:

  • E-postmeddelanden har faktiskt förändrats - mycket användbart om du behöver validera e-posten eller uppdatera e-postchimpeln;
  • Både e-postmeddelanden och e-postbekräftelsen är desamma - formuläret har två fält för e-post, så uppdateringen är mindre benägna.

Och till slut sparar det det nya e-postmeddelandet i användarobjektet (uppdaterar användarens e-postmeddelande). Observera att __init__() kräver ett användarobjekt.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow