Django
Formularze
Szukaj…
Przykład ModelForm
Utwórz ModelForm z istniejącej klasy Model, ModelForm
:
from django import forms
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['item', 'order_date', 'customer', 'status']
Definiowanie formularza Django od podstaw (z widżetami)
Formularze można zdefiniować w podobny sposób jak modele, django.forms.Form
.
Dostępne są różne opcje wprowadzania pól, takie jak CharField
, URLField
, IntegerField
itp.
Zdefiniowanie prostego formularza kontaktowego można zobaczyć poniżej:
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'}))
Widżet jest reprezentacją Django znaczników HTML wprowadzanych przez użytkownika i może być używany do renderowania niestandardowego kodu HTML dla pól formularzy (np .: gdy pole tekstowe jest renderowane dla danych wprowadzanych tutaj)
attrs
to atrybuty, które zostaną skopiowane tak jak renderowany HTML dla formularza.
Np .: content.render("name", "Your Name")
daje
<input title="Your name" type="text" name="name" value="Your Name" class="form-control" />
Usuwanie pola modelForm na podstawie warunku z views.py
Jeśli mamy następujący model,
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
I formularz modelowy, który wykorzystuje ten model w następujący sposób,
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']
Zauważ, że poniżej klasy Meta w formularzu dodałem funkcję init, której możemy użyć podczas inicjalizacji formularza z views.py, aby usunąć pole formularza (lub kilka innych akcji). Wyjaśnię to później.
Tak więc ten formularz może być używany do celów rejestracji użytkowników i chcemy, aby wszystkie pola zdefiniowane były w klasie Meta formularza. Ale co, jeśli chcemy używać tego samego formularza podczas edycji użytkownika, ale kiedy tak nie chcemy, aby wyświetlać pole administracyjne formularza?
Możemy po prostu wysłać dodatkowy argument, gdy inicjalizujemy formularz w oparciu o logikę i usuwamy pole administratora z backendu.
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)
Jak widać, pokazałem tutaj prosty przykład edycji z wykorzystaniem formularza, który wcześniej utworzyliśmy. Zauważ, że kiedy zainicjowałem formularz, przekazałem dodatkową zmienną admin_check
, która zawiera True
lub False
.
profile_form = UserProfileForm(instance = profile,admin_check=admin_check)
Teraz, jeśli zauważysz formularz, który napisaliśmy wcześniej, zobaczysz, że w init staramy się uchwycić parametr admin_check
, który tutaj przekazujemy. Jeśli wartość to Fałsz, po prostu usuwamy pole admin
z formularza i używamy go. Ponieważ jest to modelowe pole administratora formularza, które nie może być puste w modelu, po prostu sprawdzamy, czy pole formularza ma pole administracyjne w formularzu formularza, jeśli nie, ustawiamy je na False
w kodzie widoku w poniższym kodzie widoku.
form_bool = request.POST.get("admin", "xxx")
if form_bool == "xxx":
form_bool_value = False
else:
form_bool_value = True
Przesyłanie plików za pomocą formularzy Django
Przede wszystkim musimy dodać MEDIA_ROOT
i MEDIA_URL
do naszego pliku settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Również tutaj będziesz pracować z ImageField
, więc pamiętaj, w takich przypadkach zainstaluj bibliotekę Pillow ( pip install pillow
). W przeciwnym razie wystąpi taki błąd:
ImportError: No module named PIL
Poduszka to rozwidlenie biblioteki PIL, Python Imaging Library, która nie jest już utrzymywana. Poduszka jest wstecznie kompatybilna z PIL.
Django zawiera dwa pola formularza do przesyłania plików na serwer, FileField
i ImageField
, poniżej znajduje się przykład użycia tych dwóch pól w naszym formularzu
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>
Sprawdzanie poprawności pól i zatwierdzanie do modelu (Zmień adres e-mail użytkownika)
Istnieją już zaimplementowane formularze w Django do zmiany hasła użytkownika, jednym z przykładów jest SetPasswordForm .
Nie ma jednak formularzy do modyfikowania wiadomości e-mail użytkownika i uważam, że poniższy przykład jest ważny, aby zrozumieć, jak poprawnie używać formularza.
Poniższy przykład wykonuje następujące kontrole:
- Adres e-mail w rzeczywistości się zmienił - bardzo przydatne, jeśli trzeba zweryfikować wiadomość e-mail lub zaktualizować szympansa pocztowego;
- Zarówno e-mail, jak i e-mail potwierdzający są takie same - formularz zawiera dwa pola na e-mail, więc aktualizacja jest mniej podatna na błędy.
Na koniec zapisuje nową wiadomość e-mail w obiekcie użytkownika (aktualizuje wiadomość e-mail użytkownika). Zauważ, że __init__()
wymaga obiektu użytkownika.
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))