Django
формы
Поиск…
Пример модели
Создайте ModelForm из существующего класса Model, подклассифицируя ModelForm
:
from django import forms
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['item', 'order_date', 'customer', 'status']
Определение формы Django с нуля (с виджетами)
Формы могут быть определены аналогично моделям путем подкласса django.forms.Form
.
Доступны различные варианты ввода полей, такие как CharField
, URLField
, IntegerField
и т. Д.
Определение простой формы контакта можно увидеть ниже:
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'}))
Виджет представляет собой Django представление HTML-тегов, вводимых пользователем, и может использоваться для визуализации настраиваемого html для полей формы (например: как текстовое поле отображается для ввода содержимого здесь)
attrs
- атрибуты, которые будут скопированы так же, как и отображаемый html для формы.
Например: content.render("name", "Your Name")
дает
<input title="Your name" type="text" name="name" value="Your Name" class="form-control" />
Удаление поля modelForm на основе условия из views.py
Если у нас есть Модель как следующая,
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
И модельная форма, которая использует эту модель как следующую,
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']
Обратите внимание, что ниже класса Meta в форме я добавил функцию init, которую мы можем использовать при инициализации формы из views.py, чтобы удалить поле формы (или некоторые другие действия). Я объясню это позже.
Таким образом, эта форма может использоваться для целей регистрации пользователей, и мы хотим, чтобы все поля были определены в мета-классе формы. Но что, если мы хотим использовать ту же форму при редактировании пользователя, но когда мы это делаем, мы не хотим показывать поле admin формы?
Мы можем просто отправить дополнительный аргумент, когда мы инициализируем форму на основе некоторой логики и удаляем поле admin из бэкэнд.
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)
Как вы можете видеть, я показал здесь простой пример редактирования, используя форму, которую мы создали ранее. Обратите внимание, когда я инициализировал форму, я передал дополнительную переменную admin_check
которая содержит либо True
либо False
.
profile_form = UserProfileForm(instance = profile,admin_check=admin_check)
Теперь, если вы заметили форму, которую мы написали ранее, вы можете увидеть, что в init мы пытаемся поймать параметр admin_check
который мы передаем отсюда. Если значение False, мы просто удаляем поле admin
из формы и используем его. И так как это модельное поле для администратора формы не может быть пустым в модели, мы просто проверяем, было ли в поле формы поле admin в сообщении формы, если мы не установили его в False
в коде вида в следующем коде представления.
form_bool = request.POST.get("admin", "xxx")
if form_bool == "xxx":
form_bool_value = False
else:
form_bool_value = True
Загрузка файлов с помощью форм Django
Прежде всего, нам нужно добавить MEDIA_ROOT
и MEDIA_URL
в наш файл settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Также здесь вы будете работать с ImageField
, так что помните в таких случаях, установите Pillow library ( pip install pillow
). В противном случае у вас будет такая ошибка:
ImportError: No module named PIL
Подушка - это вилка PIL, Python Imaging Library, которая больше не поддерживается. Подушка обратно совместима с PIL.
Django поставляется с двумя полями формы для загрузки файлов на сервер, FileField
и ImageField
, следующий пример использования этих двух полей в нашей форме
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>
Проверка полей и Commit to model (Изменение электронной почты пользователя)
В Django уже реализованы формы для изменения пароля пользователя, одним из которых является SetPasswordForm .
Однако не существует форм для изменения электронной почты пользователя, и я думаю, что следующий пример очень важен, чтобы понять, как правильно использовать форму.
Следующий пример выполняет следующие проверки:
- Электронная почта на самом деле изменилась - очень полезно, если вам нужно проверить электронную почту или обновить шимпанзе;
- Как по электронной почте, так и по электронной почте с подтверждением совпадают - у формы есть два поля для электронной почты, поэтому обновление меньше подвержено ошибкам.
И в итоге он сохраняет новое электронное письмо в пользовательском объекте (обновляет электронную почту пользователя). Обратите внимание, что для метода __init__()
требуется объект пользователя.
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))