Django Form and ModelForm 의 차이 점 과 사용

22098 단어 DjangoFormModelForm
양식 소개
HTML 페이지 에서 form 폼 을 이용 하여 백 엔 드 에 데 이 터 를 제출 할 때 사용자 가 입력 한 탭 을 작성 하고 form 탭 으로 포장 합 니 다.
이 동시에 우 리 는 많은 장면 에서 사용자 의 입력 을 검증 해 야 한다.예 를 들 어 사용자 가 입력 했 는 지,입력 한 길이 와 형식 등 이 정확 하지 않다.사용자 가 입력 한 내용 에 오류 가 있 으 면 페이지 의 해당 위치 에 해당 하 는 오류 정 보 를 표시 해 야 합 니 다.
Django form 구성 요 소 는 위 에서 말 한 기능 을 실현 합 니 다.
요약 하면 form 구성 요소 의 주요 기능 은 다음 과 같 습 니 다.
  • 페이지 에 사용 가능 한 HTML 탭 생 성
  • 사용자 가 제출 한 데 이 터 를 검증 합 니 다
  • 마지막 입력 내용 유지
  • 일반 방식 필기 등록 기능
    views.py
    
    #   
    def register(request):
     error_msg = ""
     if request.method == "POST":
      username = request.POST.get("name")
      pwd = request.POST.get("pwd")
      #         
      if len(username) < 6:
       #       6 
       error_msg = "         6 "
      else:
       #             
       return HttpResponse("    ")
     return render(request, "register.html", {"error_msg": error_msg})
    
    login.html
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <title>    </title>
    </head>
    <body>
    <form action="/reg/" method="post">
     {% csrf_token %}
     <p>
         :
      <input type="text" name="name">
     </p>
     <p>
        :
      <input type="password" name="pwd">
     </p>
     <p>
      <input type="submit" value="  ">
      <p style="color: red">{{ error_msg }}</p>
     </p>
    </form>
    </body>
    </html>
    
    form 구성 요 소 를 사용 하여 등록 기능 을 실현 합 니 다.
    views.py
    먼저 RegForm 클래스 를 정의 합 니 다:
    
    from django import forms
    
    #   Django form           
    class RegForm(forms.Form):
     name = forms.CharField(label="   ")
     pwd = forms.CharField(label="  ")
    
    
    보기 함수 다시 쓰기:
    
    #   form        
    def register2(request):
     form_obj = RegForm()
     if request.method == "POST":
      #    form     , post            
      form_obj = RegForm(request.POST)
      #   form_obj       
      if form_obj.is_valid():
       return HttpResponse("    ")
     return render(request, "register2.html", {"form_obj": form_obj})
    
    login2.html
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <title>  2</title>
    </head>
    <body>
     <form action="/reg2/" method="post" novalidate autocomplete="off">
      {% csrf_token %}
      <div>
       <label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
       {{ form_obj.name }} {{ form_obj.name.errors.0 }}
      </div>
      <div>
       <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
       {{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
      </div>
      <div>
       <input type="submit" class="btn btn-success" value="  ">
      </div>
     </form>
    </body>
    </html>
    
    웹 페이지 효 과 를 보 니 form 의 기능 도 검증 되 었 습 니 다.
  • 전단 페이지 는 form 류 의 대상 이 생 성 한 것 입 니 다.                                      -->HTML 태그 생 성
  • 사용자 이름과 비밀번호 가 비어 있 거나 잘못 입력 되면 페이지 가 알려 집 니 다.        -->사용자 가 검사 기능 제출
  • 사용자 가 잘못 진 후에 지난번 내용 을 다시 입력 하면 input 상자 에 남아 있 습 니 다.   -->마지막 입력 내용 유지
  • 그런 일 들 을 만들어 라.
    상용 필드 와 플러그 인
    Form 클래스 를 만 들 때 주로[필드]와[플러그 인]과 관련 됩 니 다.필드 는 사용자 가 요청 한 데 이 터 를 검증 하 는 데 사 용 됩 니 다.플러그 인 은 자동 으로 HTML 을 생 성 하 는 데 사 용 됩 니 다.
    initial
    초기 값,input 상자 의 초기 값.
    
    class LoginForm(forms.Form):
     username = forms.CharField(
      min_length=8,
      label="   ",
      initial="  " #      
     )
     pwd = forms.CharField(min_length=6, label="  ")
    
    error_messages
    잘못된 메 시 지 를 다시 쓰다.
    
    class LoginForm(forms.Form):
     username = forms.CharField(
      min_length=8,
      label="   ",
      initial="  ",
      error_messages={
       "required": "    ",
       "invalid": "    ",
       "min_length": "     8 "
      }
     )
     pwd = forms.CharField(min_length=6, label="  ")
    
    password
    
    class LoginForm(forms.Form):
     ...
     pwd = forms.CharField(
      min_length=6,
      label="  ",
      widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
     )
    radioSelect
    단일 라디오 값 문자열
    
    class LoginForm(forms.Form):
     username = forms.CharField(
      min_length=8,
      label="   ",
      initial="  ",
      error_messages={
       "required": "    ",
       "invalid": "    ",
       "min_length": "     8 "
      }
     )
     pwd = forms.CharField(min_length=6, label="  ")
     gender = forms.fields.ChoiceField(
      choices=((1, " "), (2, " "), (3, "  ")),
      label="  ",
      initial=3,
      widget=forms.widgets.RadioSelect()
     )
    
    단일 선택
    
    class LoginForm(forms.Form):
     ...
     hobby = forms.fields.ChoiceField(
      choices=((1, "  "), (2, "  "), (3, "   "), ),
      label="  ",
      initial=3,
      widget=forms.widgets.Select()
     )
    
    다 중 선택
    
    class LoginForm(forms.Form):
     ...
     hobby = forms.fields.MultipleChoiceField(
      choices=((1, "  "), (2, "  "), (3, "   "), ),
      label="  ",
      initial=[1, 3],
      widget=forms.widgets.SelectMultiple()
     )
    
    체크 박스
    
    class LoginForm(forms.Form):
     ...
     keep = forms.fields.ChoiceField(
      label="      ",
      initial="checked",
      widget=forms.widgets.CheckboxInput()
     )
    
    다 중 선택 체크 박스
    
    class LoginForm(forms.Form):
     ...
     hobby = forms.fields.MultipleChoiceField(
      choices=((1, "  "), (2, "  "), (3, "   "),),
      label="  ",
      initial=[1, 3],
      widget=forms.widgets.CheckboxSelectMultiple()
     )
    
    choice 필드 주의사항
    탭 을 선택 할 때 choices 옵션 을 사용 하면 데이터베이스 에서 가 져 올 수 있 지만 정적 필드 이기 때문에 주의해 야 합 니 다. 가 져 온 값 은 실시 간 으로 업데이트 할 수 없 으 며,구조 재 작성 방법 으로 choice 실시 간 업 데 이 트 를 실현 해 야 합 니 다.
    방식 1:
    
    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields
    
     
    class MyForm(Form):
     
     user = fields.ChoiceField(
      # choices=((1, '  '), (2, '  '),),
      initial=2,
      widget=widgets.Select
     )
     
     def __init__(self, *args, **kwargs):
      super(MyForm,self).__init__(*args, **kwargs)
      # self.fields['user'].choices = ((1, '  '), (2, '  '),)
      #  
      self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')
    
    
    방식 2:
    
    from django import forms
    from django.forms import fields
    from django.forms import models as form_model
    
     
    class FInfo(forms.Form):
     authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all()) #   
     # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all()) #   
    Django Form      
    
    Field
     required=True,          
     widget=None,     HTML  
     label=None,         Label       
     initial=None,       
     help_text='',        (       )
     error_messages=None,        {'required': '    ', 'invalid': '    '}
     validators=[],           
     localize=False,           
     disabled=False,          
     label_suffix=None   Label    
     
     
    CharField(Field)
     max_length=None,        
     min_length=None,        
     strip=True               
     
    IntegerField(Field)
     max_value=None,       
     min_value=None,       
     
    FloatField(IntegerField)
     ...
     
    DecimalField(IntegerField)
     max_value=None,       
     min_value=None,       
     max_digits=None,       
     decimal_places=None,        
     
    BaseTemporalField(Field)
     input_formats=None         
     
    DateField(BaseTemporalField)   :2015-09-01
    TimeField(BaseTemporalField)   :11:12
    DateTimeField(BaseTemporalField)  :2015-09-01 11:12
     
    DurationField(Field)       :%d %H:%M:%S.%f
     ...
     
    RegexField(CharField)
     regex,              
     max_length=None,       
     min_length=None,       
     error_message=None,     ,       error_messages={'invalid': '...'}
     
    EmailField(CharField)  
     ...
     
    FileField(Field)
     allow_empty_file=False         
     
    ImageField(FileField)  
     ...
      :  PIL  ,pip3 install Pillow
              ,      :
      - form    enctype="multipart/form-data"
      - view    obj = MyForm(request.POST, request.FILES)
     
    URLField(Field)
     ...
     
     
    BooleanField(Field) 
     ...
     
    NullBooleanField(BooleanField)
     ...
     
    ChoiceField(Field)
     ...
     choices=(),      , :choices = ((0,'  '),(1,'  '),)
     required=True,        
     widget=None,      ,  select  
     label=None,    Label  
     initial=None,       
     help_text='',        
     
     
    ModelChoiceField(ChoiceField)
     ...      django.forms.models.ModelChoiceField
     queryset,     #          
     empty_label="---------", #        
     to_field_name=None,  # HTML value       
     limit_choices_to=None  # ModelForm  queryset    
      
    ModelMultipleChoiceField(ModelChoiceField)
     ...      django.forms.models.ModelMultipleChoiceField
     
     
      
    TypedChoiceField(ChoiceField)
     coerce = lambda val: val            
     empty_value= ''         
     
    MultipleChoiceField(ChoiceField)
     ...
     
    TypedMultipleChoiceField(MultipleChoiceField)
     coerce = lambda val: val               
     empty_value= ''         
     
    ComboField(Field)
     fields=()           ,  :       20,       
            fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
     
    MultiValueField(Field)
     PS:    ,                   ,   MultiWidget  
     
    SplitDateTimeField(MultiValueField)
     input_date_formats=None,     :['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
     input_time_formats=None     :['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
     
    FilePathField(ChoiceField)      ,           
     path,           
     match=None,        
     recursive=False,           
     allow_files=True,       
     allow_folders=False,       
     required=True,
     widget=None,
     label=None,
     initial=None,
     help_text=''
     
    GenericIPAddressField
     protocol='both',   both,ipv4,ipv6   IP  
     unpack_ipv4=False     ipv4  ,   ::ffff:192.0.2.1  ,    192.0.2.1, PS:protocol   both    
     
    SlugField(CharField)     ,  ,   ,  (   )
     ...
     
    UUIDField(CharField)   uuid  
    Django Form 내장 필드
    필드 검사
    Regex Validator 검증 기
    
    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields
    from django.core.validators import RegexValidator
     
    class MyForm(Form):
     user = fields.CharField(
      validators=[RegexValidator(r'^[0-9]+$', '     '), RegexValidator(r'^159[0-9]+$', '     159  ')],
     )
    
    사용자 정의 인증 함수
    
    import re
    from django.forms import Form
    from django.forms import widgets
    from django.forms import fields
    from django.core.exceptions import ValidationError
     
     
    #        
    def mobile_validate(value):
     mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
     if not mobile_re.match(value):
      raise ValidationError('        ')
     
     
    class PublishForm(Form):
     
     
     title = fields.CharField(max_length=20,
           min_length=5,
           error_messages={'required': '      ',
               'min_length': '     5   ',
               'max_length': '     20   '},
           widget=widgets.TextInput(attrs={'class': "form-control",
                   'placeholder': '  5-20   '}))
     
     
     #          
     phone = fields.CharField(validators=[mobile_validate, ],
           error_messages={'required': '      '},
           widget=widgets.TextInput(attrs={'class': "form-control",
                   'placeholder': u'    '}))
     
     email = fields.EmailField(required=False,
           error_messages={'required': u'      ','invalid': u'      '},
           widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'  '}))
    
    훅 방법
    위의 두 가지 방식 을 제외 하고 우 리 는 Form 류 에서 갈고리 함 수 를 정의 하여 사용자 정의 검증 기능 을 실현 할 수 있다.
    국부 갈고리
    우 리 는 Fom 류 에서 clean 을 정의 합 니 다.필드 이름()방법 은 특정 필드 를 검증 할 수 있 습 니 다.
    예 를 들 어:
    
    class LoginForm(forms.Form):
     username = forms.CharField(
      min_length=8,
      label="   ",
      initial="  ",
      error_messages={
       "required": "    ",
       "invalid": "    ",
       "min_length": "     8 "
      },
      widget=forms.widgets.TextInput(attrs={"class": "form-control"})
     )
     ...
     #       ,    username  
     def clean_username(self):
      value = self.cleaned_data.get("username")
      if "666" in value:
       raise ValidationError("  666    ")
      else:
       return value
    
    전역 갈고리
    우 리 는 Fom 클래스 에서 clean()방법 을 정의 하면 필드 에 대한 전역 검 사 를 실현 할 수 있 습 니 다.
    
    class LoginForm(forms.Form):
     ...
     password = forms.CharField(
      min_length=6,
      label="  ",
      widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True)
     )
     re_password = forms.CharField(
      min_length=6,
      label="    ",
      widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}, render_value=True)
     )
     ...
     #        ,                 
     def clean(self):
      password_value = self.cleaned_data.get('password')
      re_password_value = self.cleaned_data.get('re_password')
      if password_value == re_password_value:
       return self.cleaned_data
      else:
       self.add_error('re_password', '       ')
       raise ValidationError('       ')
    
    보충 진급
    부 트 스 트랩 스타일 적용
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
     <meta charset="UTF-8">
     <meta http-equiv="x-ua-compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css" rel="external nofollow" >
     <title>login</title>
    </head>
    <body>
    <div class="container">
     <div class="row">
     <form action="/login2/" method="post" novalidate class="form-horizontal">
      {% csrf_token %}
      <div class="form-group">
      <label for="{{ form_obj.username.id_for_label }}"
        class="col-md-2 control-label">{{ form_obj.username.label }}</label>
      <div class="col-md-10">
       {{ form_obj.username }}
       <span class="help-block">{{ form_obj.username.errors.0 }}</span>
      </div>
      </div>
      <div class="form-group">
      <label for="{{ form_obj.pwd.id_for_label }}" class="col-md-2 control-label">{{ form_obj.pwd.label }}</label>
      <div class="col-md-10">
       {{ form_obj.pwd }}
       <span class="help-block">{{ form_obj.pwd.errors.0 }}</span>
      </div>
      </div>
      <div class="form-group">
      <label class="col-md-2 control-label">{{ form_obj.gender.label }}</label>
      <div class="col-md-10">
       <div class="radio">
       {% for radio in form_obj.gender %}
        <label for="{{ radio.id_for_label }}">
        {{ radio.tag }}{{ radio.choice_label }}
        </label>
       {% endfor %}
       </div>
      </div>
      </div>
      <div class="form-group">
      <div class="col-md-offset-2 col-md-10">
       <button type="submit" class="btn btn-default">  </button>
      </div>
      </div>
     </form>
     </div>
    </div>
    
    <script src="/static/jquery-3.2.1.min.js"></script>
    <script src="/static/bootstrap/js/bootstrap.min.js"></script>
    </body>
    </html>
    
    
    일괄 추가 스타일
    form 류 를 다시 쓰 는 init 방법 으로 이 루어 집 니 다.
    
    class LoginForm(forms.Form):
     username = forms.CharField(
      min_length=8,
      label="   ",
      initial="  ",
      error_messages={
       "required": "    ",
       "invalid": "    ",
       "min_length": "     8 "
      }
     ...
    
     def __init__(self, *args, **kwargs):
      super(LoginForm, self).__init__(*args, **kwargs)
      for field in iter(self.fields):
       self.fields[field].widget.attrs.update({
        'class': 'form-control'
       })
    
    
    ModelForm
    일반적으로 Django 프로젝트 에서,우리 가 작성 한 대부분 은 Django 모델 과 긴밀 하 게 비 치 는 폼 입 니 다.예 를 들 어 북 모델 이 있 을 수도 있 고 이 모델 에 책 정 보 를 추가 하고 편집 하 는 form 폼 을 만 들 고 싶 습 니 다.이러한 상황 에서 form 폼 에서 필드 를 정의 하 는 것 은 불필요 할 것 입 니 다.왜냐하면 우 리 는 이미 모델 에서 그 필드 를 정 의 했 기 때 문 입 니 다.
    이 를 바탕 으로 Django 는 Django 모델 에서 Form 을 만 들 수 있 는 보조 클래스 를 제공 합 니 다.이것 이 바로 ModelForm 입 니 다.
    modelForm 정의
    form 과 model 의 궁극 적 결합.
    
    class BookForm(forms.ModelForm):
    
     class Meta:
      model = models.Book
      fields = "__all__"
      labels = {
       "title": "  ",
       "price": "  "
      }
      widgets = {
       "password": forms.widgets.PasswordInput(attrs={"class": "c1"}),
      }
    
    
    
    class StudentList(ModelForm):
     class Meta:
      model = models.UserInfo #   Model   
      fields = "__all__"  #  ,   __all__,           
      exclude = None   #     
      labels = None   #    
      help_texts = None  #      
      widgets = None   #     
      error_messages = None #       
      #error_messages  :
      error_messages = {
       'name':{'required':"       ",},
       'age':{'required':"      ",},
      }
    
      #widgets  ,         input   Textarea
      #       
      from django.forms import widgets as wid #    ,      
      widgets = {
       "name":wid.Textarea(attrs={"class":"c1"}) #        
      }
      #labels,           
      labels= {
       "name":"   "
    class Meta 에서 자주 사용 하 는 인자:
    
    model = models.Book #    Model   
    fields = "__all__" #   ,   __all__,           
    exclude = None #      
    labels = None #     
    help_texts = None #       
    widgets = None #      
    error_messages = None #        
    
    ModelForm 검증
    일반적인 Form 폼 검증 형식 과 유사 합 니 다.ModelForm 폼 의 검증 은 is 를 호출 합 니 다.valid()또는 errors 속성 에 접근 할 때 암시 적 으로 호출 합 니 다.
    우 리 는 Form 류 처럼 국부 갈고리 방법 과 전역 갈고리 방법 을 사용자 정의 하여 사용자 정의 검사 규칙 을 실현 할 수 있다.
    구체 적 인 필드 를 다시 쓰 지 않 고 vaidators 속성 화 를 설정 하지 않 으 면 ModelForm 은 모델 필드 의 vaidators 에 따라 검 사 됩 니 다.
    save()방법
    모든 ModelForm 에는 save()방법 이 있 습 니 다.이 방법 은 폼 에 연 결 된 데이터 에 따라 데이터베이스 대상 을 만 들 고 저장 합 니 다.ModelForm 의 하위 클래스 는 기 존의 모델 인 스 턴 스 를 키워드 파라미터 intance 로 받 아들 일 수 있 습 니 다.이 기능 을 제공 하면 save()는 이 인 스 턴 스 를 업데이트 합 니 다.제공 되 지 않 으 면 save()는 모델 의 새로운 인 스 턴 스 를 만 들 것 입 니 다.
    
    >>> from myapp.models import Book
    >>> from myapp.forms import BookForm
    
    #   POST        form  
    >>> form_obj = BookForm(request.POST)
    
    #       
    >>> new_ book = form_obj.save()
    
    #           form  
    >>> edit_obj = Book.objects.get(id=1)
    #   POST           
    >>> form_obj = BookForm(request.POST, instance=edit_obj)
    >>> form_obj.save()
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기