Поиск…


Пример модели

Создайте 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))


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow