Django(9): ModelForm 작업

22577 단어 Django
1. 내용 회고
    Model
        -      
        -   
        class A(MOdel):
            user = 
            email = 
            pwd = 

    Form
        - class LoginForm(Form): 
            email = fields.EmailField()
            user = 
            pwd = 

        - is_valid ->          (      )+clean_   -> clean(__all__)  -> _post_clean
        - cleand_data
        - error
    -------->    

2. ModelForm 작업 및 검증
Model + Form ==> ModelForm.모델과form의 결합체이기 때문에 다음과 같은 기능이 있습니다.
  • 검증
  • 데이터베이스 작업
  • 모델은 데이터베이스를 조작하는 필드가 있고form검증도 그 몇 개의 필드가 있는데 결합도는 낮지만 코드는 중복된다.모델의 필드를 이용하면form의 필드인지 아닌지는 쓸 필요가 없습니다.
    1. 모델 + Form(이전 작업)
    models.py
    class UserType(models.Model):
        caption = models.CharField(max_length=32)
    
    class UserInfo(models.Model):
        username = models.CharField(max_length=32)
        email = models.EmailField()
        user_type = models.ForeignKey(to='UserType',to_field='id')

    forms.py
    from django import forms
    from django.forms import fields
    
    class UserInfoForm(forms.Form):
        # username = models.CharField(max_length=32)    
        username = fields.CharField(max_length=32)
        # email = models.EmailField()    
        email = fields.EmailField()
        # user_type = models.ForeignKey(to='UserType',to_field='id')    
        user_type = fields.ChoiceField(
            choices=models.UserType.objects.values_list('id','caption')
        )
    
        #                  。
        def __init__(self, *args, **kwargs):
            super(UserInfoForm,self).__init__(*args, **kwargs)
            self.fields['user_type'].choices = models.UserType.objects.values_list('id','caption')

    index.html
    <body>
        <form action="/index/" method="POST" novalidate="novalidate">
            {% csrf_token %}
            {{ obj.as_p }}
            <input type="submit" value="  ">
        form>
    body>

    novalidate 참고: HTML5 가져오기 유형 및 브라우저 유효성 검사
    만약 폼에 URLField, EmailField, 기타 정수 필드가 유사하다면, Django는 URL, 이메일,number 같은 HTML5 입력 형식을 사용할 것입니다.기본적으로 브라우저는 이 필드에 대해 자신만의 검증을 할 수 있으며, 이 검증은 Django의 검증보다 더 엄격할 수 있습니다.이 동작을 사용하지 않으려면 form 탭의novalidate 속성을 설정하거나 TextInput과 같은 다른 필드를 설정하십시오.
    2. ModelForm 기본 작업
    다음은 모델form을 통해 실현됩니다
    forms.py
    class UserInfoModelForm(forms.ModelForm):
    
        class Meta:
            model = models.UserInfo    #  models       
            fields = "__all__"

    views.py
    def index(request):
        if request.method == "GET":
            obj = UserInfoModelForm()
            return render(request,"index.html",{'obj':obj})
        elif request.method == "POST":
            obj = UserInfoModelForm(request.POST)
            print(obj.is_valid())  #     ,       
            print(obj.cleaned_data)
            print(obj.errors)
            return render(request,"index.html",{'obj':obj})

    사용자 정의 필드 이름
    http에서 정의한 필드를 어떻게 정의합니까? 중국어로 사용자 정의합니까?이전의 용법은 Form에 label을 쓰는 것이다.Model Form 정의는verbosename
    models.py
    class UserInfo(models.Model):
        username = models.CharField(max_length=32, verbose_name='  ')
        email = models.EmailField(verbose_name='  ')
        user_type = models.ForeignKey(to='UserType',to_field='id', verbose_name='  ')

    모델에 정의되지 않으면 모델Form에서 실행되며 labels를 사용합니다
    class UserInfoModelForm(forms.ModelForm):
    
        class Meta:
            model = models.UserInfo
            fields = "__all__"
            labels = {
                'username':'   ',
                'email':'  ',
            }

    지정된 열을 표시합니다.fields = "__all__" 위에 표시된 모든 열을 보여줄 수 있습니까?
            fields = ['username','email']   #      
            exclude = ['username']          #      

    왜 모델포엠에서도 검증을 할 수 있습니까?
    form에는 is_valid,cleaned_data,errors,
    # Form  :
        UserInfoForm -> Form -> BaseForm(   is_valid   )
    
    # ModelForm  :
        UserInfoModelForm -> ModelForm -> BaseModelForm -> BaseForm

    3. ModelForm 구성 요소
    ModelForm
        a.  class Meta:
                model,                           #   Model 
                fields=None,                     #   
                exclude=None,                    #     
                labels=None,                     #     
                help_texts=None,                 #       
                widgets=None,                    #      
                error_messages=None,             #        (      from django.core.exceptions import NON_FIELD_ERRORS)
                field_classes=None               #        (        )
                localized_fields=('birth_date',) #    , :          2016-12-27 04:10:57
                    setting    
                        TIME_ZONE = 'Asia/Shanghai'
                        USE_TZ = True
                       :
                        2016-12-27 12:10:57
        b.       
            is_valid -> full_clean ->    ->     
    
        c.       
            def clean_   (self):
                #       
                # from django.core.exceptions import ValidationError
                return "  "
        d.     
            model_form_obj = XXOOModelForm()
            model_form_obj.is_valid()
            model_form_obj.errors.as_json()
            model_form_obj.clean()
            model_form_obj.cleaned_data
        e.     
            model_form_obj = XXOOModelForm(request.POST)
            ####     ,    #####
            #        
                obj = form.save(commit=True)
            #       ,     save_m2m(       )
                obj = form.save(commit=False)
                obj.save()      #       
                obj.save_m2m()  #          
    
        f.         
            obj = model.tb.objects.get(id=1)
            model_form_obj = XXOOModelForm(request.POST,instance=obj)
            ...
    
            PS:      
                model_form_obj = XXOOModelForm(initial={...})

    주의: 모듈 이름 (fields,widgets) 과 필드 이름이 중복되기 때문에 가져올 때 별명을 붙여야 합니다.
    from django import forms
    from django.forms import fields as Ffields
    from django.forms import widgets as Fwidgets
    class UserInfoModelForm(forms.ModelForm):
    
        is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())
    
        class Meta:
            model = models.UserInfo
            fields = '__all__'
            # fields =  ['username','email']
            # exclude = ['username']
            labels = {
                'username': '   ',
                'email': '  ',
            }
            help_texts = {
                'username': '...'
            }
            widgets = {
                'username': Fwidgets.Textarea(attrs={'class': 'c1'})
            }
            error_messages = {
                '__all__':{    #       
    
                },
                'email': {
                    'required': '      ',
                    'invalid': '      ..',
                }
            }
            field_classes = {  #          
                # 'email': Ffields.URLField  #       ,         。
            }
    
            # localized_fields=('ctime',)  #         

    4. ModelForm 데이터베이스 작업
    1.1 데이터 저장 만들기
    만약 데이터 검증이 ok라면save는 데이터베이스에 데이터를 직접 생성합니다
            if obj.is_valid():
                obj.save()      #     

    다음 일대다 관계식에서
    class UserType(models.Model):
        caption = models.CharField(max_length=32)
    
    class UserGroup(models.Model):
        name = models.CharField(max_length=32)
    
    class UserInfo(models.Model):
        username = models.CharField(max_length=32)
        email = models.EmailField()
        user_type = models.ForeignKey(to='UserType',to_field='id')
        u2g = models.ManyToManyField(UserGroup)

    이렇게 하면 위의 obj.save()를 실행하면 UserInfo표와 다대다관계표에 데이터가 추가됩니다.
    views.py
    def index(request):
        if request.method == "GET":
            obj = UserInfoModelForm()
            return render(request,'index.html',{'obj': obj})
        elif request.method == "POST":
            obj = UserInfoModelForm(request.POST)
            if obj.is_valid():
                obj.save()  #       
                # instance = obj.save(False)
                # instance.save()
                # obj.save_m2m()
            return render(request,'index.html',{'obj': obj})

    1.2 save는 어떤 조작을 했습니까?
    save 소스:
    def save(self, commit=True):
        """"""
        if commit:
            self.instance.save()    #     model  
            self._save_m2m()        #  :  m2m  
        else:
            self.save_m2m = self._save_m2m
        return self.instance    # model     
        """"""

    그래서 instance = obj.save(False)시에는 아무것도 조작하지 않는다.
    if obj.is_valid():
        instance = obj.save(False)
        instance.save()     #          
        obj.save_m2m()      #         
        #              obj.save      。           

    2. 데이터 수정
    수정표 데이터는 instance 정보도 전송해야 한다. 그렇지 않으면 새로운 데이터이지 한 줄의 데이터를 수정하는 것이 아니다.
    사용자 정보 편집, 새 URL 방식으로 기본 데이터 보존
    urls.py
        url(r'^user_list/', views.user_list),
        url(r'^edit-(\d+)/', views.user_edit),

    views.py
    def user_list(request):
        li = models.UserInfo.objects.all().select_related('user_type')  #        ,         
        return render(request,'user_list.html',{'li': li})
    
    def user_edit(request, nid):
        #     id       
        #           
        if request.method == "GET":
            user_obj = models.UserInfo.objects.filter(id=nid).first()
            mf = UserInfoModelForm(instance=user_obj)   #          
            return render(request,'user_edit.html',{'mf': mf, 'nid': nid})
        elif request.method == 'POST':
            #        ,           ?
            user_obj = models.UserInfo.objects.filter(id=nid).first()
            mf = UserInfoModelForm(request.POST,instance=user_obj)  #        
            if mf.is_valid():
                mf.save()
            else:
                print(mf.errors.as_json())
            return render(request,'user_edit.html',{'mf': mf, 'nid': nid})

    user_list.html
    <body>
        <ul>
            {% for row in li %}
                <li>{{ row.username }} - {{ row.user_type.caption }} - <a href="/edit-{{ row.id }}/">  a>li>
            {% endfor %}
        ul>
    body>

    user_edit.html
    
        
    "POST" action="/edit-{{ nid }}/"> {% csrf_token %} {{ mf.as_p }} "submit" value=" " />

    5, ModelForm 갈고리, 추가 필드
    데이터 검증 갈고리
    위의Form과ModelForm에서 그들은 모두BaseForm을 계승하였고is_valid는BaseForm에서 정의한 것이기 때문에ModelForm도Form과 같이 각종 갈고리를 사용할 수 있다
    추가 필드
    웹 페이지의 checkbox처럼 한 달 안에 로그인을 면제하고 데이터베이스에 제출합니까?이것은 세션과 쿠키만 설정하면 됩니다.
    views.py
    class UserInfoModelForm(forms.ModelForm):
    
        is_rmb = fields.CharField(widget=widgets.CheckboxInput())  #     
    
        class Meta:
            model = models.UserInfo
            fields = '__all__'

    6. 총결산
        1.   HTML  :class Meta: ...
        2. mf = xxxModelForm(instance=ModelObj)      
        3.      , is_rmb = Ffields.CharField(widget=Fwidgets.CheckboxInput())
        4.      is_valid() ->     ...
        5.  mf.save()
            #  
            instance = mf.save(False)
            instance.save()
            mf.save_m2m()

    ModelForm은 모델과form의 결합이 너무 밀접하기 때문에 보통 작은 프로그램을 써서 사용합니다.
    전재는 반드시 이 출처를 보존하십시오:http://blog.csdn.net/fgf00/article/details/54917396

    좋은 웹페이지 즐겨찾기