Django
Formen
Suche…
ModelForm-Beispiel
Erstellen Sie eine ModelForm aus einer vorhandenen Model-Klasse, indem Sie ModelForm
subclassing:
from django import forms
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['item', 'order_date', 'customer', 'status']
Django-Formular von Grund auf neu definieren (mit Widgets)
Formulare können auf ähnliche Weise wie Modelle definiert werden, indem django.forms.Form
subclassiert django.forms.Form
.
Es stehen CharField
URLField
wie CharField
, URLField
, IntegerField
usw. zur Verfügung.
Das Definieren eines einfachen Kontaktformulars ist unten zu sehen:
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 ist die Darstellung von HTML-Benutzereingabe-Tags in Django und kann verwendet werden, um benutzerdefinierte HTML-Formulare für Formularfelder darzustellen.
attrs
sind Attribute, die in das gerenderte HTML für das Formular übernommen werden.
ZB: content.render("name", "Your Name")
gibt an
<input title="Your name" type="text" name="name" value="Your Name" class="form-control" />
Das Entfernen eines Feldes von modelForm basierend auf den Bedingungen aus views.py
Wenn wir ein Modell wie folgt haben,
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
Und eine Modellform, die dieses Modell wie folgt verwendet,
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']
Beachten Sie, dass ich unterhalb der Meta-Klasse im Formular eine Init- Funktion hinzugefügt habe, die wir beim Initialisieren des Formulars aus views.py verwenden können, um ein Formularfeld (oder einige andere Aktionen) zu löschen. Ich werde das später erklären.
Dieses Formular kann also für Benutzerregistrierungszwecke verwendet werden und wir möchten, dass alle Felder in der Metaklasse des Formulars definiert werden. Aber was ist, wenn wir dasselbe Formular verwenden möchten, wenn wir den Benutzer bearbeiten, aber wenn wir das Admin-Feld des Formulars nicht anzeigen möchten?
Wir können einfach ein zusätzliches Argument senden, wenn wir das Formular basierend auf einer Logik initialisieren und das Admin-Feld aus dem Backend löschen.
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)
Wie Sie sehen, habe ich hier ein einfaches Bearbeitungsbeispiel mit dem zuvor erstellten Formular gezeigt. Wenn ich das Formular initialisiert habe, habe ich eine zusätzliche admin_check
Variable übergeben, die entweder True
oder False
.
profile_form = UserProfileForm(instance = profile,admin_check=admin_check)
Wenn Sie das Formular bemerken, das wir zuvor geschrieben haben, können Sie sehen, dass wir in der init versuchen, den admin_check
admin_check abzufangen, den wir hier übergeben. Wenn der Wert False ist, löschen wir einfach das admin
Feld aus dem Formular und verwenden es. Und da dies ein Modell-Formularadministratorfeld ist, das im Modell nicht null sein kann, prüfen wir einfach, ob das Formularposting ein Adminfeld im Formularposting hatte. Andernfalls setzen wir es im folgenden Code der Ansicht auf False
.
form_bool = request.POST.get("admin", "xxx")
if form_bool == "xxx":
form_bool_value = False
else:
form_bool_value = True
Datei-Uploads mit Django-Formularen
Zunächst müssen wir MEDIA_ROOT
und MEDIA_URL
unserer Datei settings.py
hinzufügen
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Auch hier werden Sie mit ImageField
arbeiten. ImageField
in solchen Fällen daran, die Pillow-Bibliothek ( pip install pillow
) zu pip install pillow
. Andernfalls haben Sie einen solchen Fehler:
ImportError: No module named PIL
Kissen ist eine Abzweigung von PIL, der Python Imaging Library, die nicht mehr gepflegt wird. Kissen ist rückwärtskompatibel mit PIL.
Django enthält zwei Formularfelder, um Dateien auf den Server hochzuladen, FileField
und ImageField
. Im Folgenden finden Sie ein Beispiel für die Verwendung dieser beiden Felder in unserem Formular
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>
Validierung von Feldern und Commit to model (Benutzer-E-Mail ändern)
In Django sind bereits Formulare implementiert, um das Benutzerpasswort zu ändern. Ein Beispiel ist SetPasswordForm .
Es gibt jedoch keine Formulare zum Ändern der Benutzer-E-Mail, und ich denke, das folgende Beispiel ist wichtig, um zu verstehen, wie man ein Formular korrekt verwendet.
Das folgende Beispiel führt die folgenden Prüfungen durch:
- E-Mails haben sich tatsächlich geändert - sehr nützlich, wenn Sie die E-Mail-Adresse überprüfen oder den Mail-Schimpansen aktualisieren müssen.
- Sowohl E-Mail als auch Bestätigungs-E-Mail sind identisch. Das Formular enthält zwei Felder für E-Mail, sodass die Aktualisierung weniger fehleranfällig ist.
Am Ende speichert es die neue E-Mail im Benutzerobjekt (aktualisiert die E-Mail des Benutzers). Beachten Sie, dass für die Methode __init__()
ein Benutzerobjekt erforderlich ist.
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))