Django
양식
수색…
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_ROOT
및 MEDIA_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는 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>
필드 유효성 검사 및 모델 작성 (사용자 전자 메일 변경)
장고 내에 이미 구현 된 폼들로 사용자 패스워드를 변경합니다. 한가지 예로 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))