수색…


ModelForm 예제

서브 클래스로, 기존 모델 클래스의 ModelForm 만들기 ModelForm :

from django import forms

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

Django 폼을 처음부터 정의하기 (위젯 사용)

양식은 django.forms.Form 을 하위 클래스 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" />

views.py에서 조건에 따라 modelForm의 필드 제거하기

우리가 다음과 같은 모델을 가지고 있다면,

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 클래스 아래에 폼 필드 (또는 다른 액션)를 삭제하기 위해 views.py에서 폼을 초기화하는 동안 사용할 수있는 init 함수를 추가했습니다. 나는 이것을 나중에 설명 할 것이다.

그래서이 양식은 사용자 등록 목적으로 사용할 수 있으며 우리는 양식의 메타 클래스에 정의 된 모든 필드를 원합니다. 하지만 사용자를 편집 할 때 같은 양식을 사용하려고 할 때 양식의 관리 필드를 표시하지 않으려면 어떻게해야합니까?

일부 로직을 기반으로 양식을 초기화하고 백엔드에서 관리 필드를 삭제할 때 추가 인수를 보내면됩니다.

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)

보시다시피 이전에 만든 양식을 사용하여 간단한 편집 예제를 보여 드렸습니다. 유의할 점은 양식을 초기화 할 때 True 또는 False 를 포함하는 추가 admin_check 변수를 전달한 것입니다.

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

이제 우리가 이전에 작성한 양식을 발견하면 init 에서 여기에서 전달하는 admin_check 매개 변수를 catch하려고 시도한다는 것을 알 수 있습니다. 값이 False이면 양식에서 admin 필드를 삭제하고 사용하면됩니다. 그리고 이것은 모델 양식 admin 필드가 모델에서 null이 될 수 없기 때문에 양식 게시물에 양식 필드에 admin 필드가 있는지 단순히 확인합니다. 그렇지 않은 경우보기의 코드에서보기 코드에서 False 로 설정합니다.

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

장고 양식으로 파일 업로드

우선 settings.py 파일에 MEDIA_ROOTMEDIA_URL 을 추가해야합니다.

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

또한 여기에서는 ImageField 를 사용하기 때문에 베갯잇 라이브러리 ( pip install pillow )를 pip install pillow 하십시오. 그렇지 않으면 다음과 같은 오류가 발생합니다.

ImportError: No module named PIL

베개는 더 이상 유지 관리되지 않는 Python Imaging Library 인 PIL 포크입니다. 베개는 PIL과 역 호환됩니다.

Django는 FileFieldImageField 서버에 업로드하기 위해 두 개의 폼 필드를 제공합니다. 다음은이 두 필드를 우리의 폼에서 사용하는 예제입니다

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>

필드 유효성 검사 및 모델 작성 (사용자 전자 메일 변경)

장고 내에 이미 구현 된 폼들로 사용자 패스워드를 변경합니다. 한가지 예로 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