s14_示例:Form操作

- 示例(数据库操作补充之QuerySet方法、 Model数据验证以及钩子、动态Select数据、Form内置钩子、Django序列化)

    # urls.py
        urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^index/', test.index),
            url(r'^login.html$', account.login),

            url(r'^register/', test.register),
        ]
    # views/test.py
    
        from django.shortcuts import render,HttpResponse

        # Create your views here.
        from app01 import models
        def index(request):
            # models.UserType.objects.all().values('name','user__pwd')
            # models.UserInfo.objects.create(name='root',email='root')
            # 没有进行验证
            # obj = models.UserInfo(name='alex',email='alex')
            # obj.full_clean()  # 验证
            # obj.save()
            # 此方法会验证

            from app01.forms import UserInfoForm
            if request.method == 'GET':
                obj = UserInfoForm()
                # obj = UserInfoForm({'user':'alex'})
                # obj.fields['user_type'].choices = models.UserType.objects.values_list('id','name')
                return render(request, 'index.html',{'obj':obj})
            elif request.method=='POST':
                obj = UserInfoForm(request.POST,request.FILES)
                obj.is_valid()

        def register(request):
            from app01.forms import RegisterForm
            from django.core.exceptions import NON_FIELD_ERRORS
            # obj =RegisterForm(request.POST)
            # if obj.is_valid():
            #     obj.cleaned_data
            # else:
            #     obj.errors
            #     {
            #         '__all__':[],
            #         # 'NON_FIELD_ERRORS':[],
            #         # 整体错误信息在__all__里面
            #         'user':[{'code':'required','message':'xxx'}],
            #         'pwd':[{'code':'required','message':'xxx'}],
            #     }

            # djang 默认序列化
            # from django.core import serializers
            # ret = models.UserType.objects.all()
            # data = serializers.serialize("json", ret)
            # return HttpResponse(data)

            # 自定制
            import json
            v = models.UserType.objects.values_list('id','name')
            v=list(v)
            return HttpResponse(json.dumps(v))
            
    # views/account.py

        from django.shortcuts import render,HttpResponse
        from django import forms
        from django.forms import fields
        from django.forms import widgets
        import json
        class LoginForm(forms.Form):
            # 登陆
            username = fields.CharField()
            password = fields.CharField(
                max_length=64,
                min_length=12,
            )
        from django.core.exceptions import ValidationError
        class JsonCustomEncoder(json.JSONEncoder):
            def default(self, field):
                if isinstance(field,ValidationError):
                    return {'code':field.code,'message':field.messages}
                else:
                    return json.JSONEncoder.default(self,field)

        def login(request):
            ret = {'status':True,'error':None,'data':None}
            if request.method=='GET':
                return render(request,'login.html')
            elif request.method=='POST':
                obj = LoginForm(request.POST)
                if obj.is_valid():
                    print(obj.clean_data)
                else:
                    # print(obj.errors,type(obj.errors))
                    # ret['error'] = obj.errors.as_json()
                    # 前端需要对 arg parse两回才能得到error
                    from django.forms.utils import ErrorDict

                    print(type(obj.errors.as_data()))
                    for k,v in obj.errors.as_data().items():
                        print(k,v)
                    from django.core.exceptions import ValidationError
                    ret['error'] =obj.errors.as_data()
                result =json.dumps(ret,cls=JsonCustomEncoder)
                return HttpResponse(result)

    # models.py

        from django.db import models

        # Create your models here.
        class UserType(models.Model):
            name=models.CharField(max_length=32)

            def __str__(self):
                return self.name

        class User(models.Model):
            user =models.CharField(max_length=32)
            pwd =models.CharField(max_length=64)
            ut = models.ForeignKey(to='UserType',
                                   to_field='id',
                                   related_name='b',
                                   related_query_name='a',
                                   limit_choices_to={'id__gt':5},    # admin 中外键筛选
                                   # parent_link=False      #欠着
                                   )
        # 正向查找
        # v = User.objects.all()
        # for item in v:
        #     item.user
        #     item.pwd
        #     item.ut.name

        # User.objects.all().values('user','ut__name')


        # 反向查找
        # v= UserType.objects.all()
        # for item in v:
        #     item.name
        #     item.id
        #     item.user_set.all()
        # related_name='b' ==> item.b.all()
        # related_query_name='a' ==>  item.a_set.all()

        # UserType.objects.all().values('name','user__pwd')


        class Blog(models.Model):
            site = models.CharField(max_length=32)
            m =models.ManyToManyField('Tag',through='B2T',through_fields=['b','t1'])

        class Tag(models.Model):
            name = models.CharField(max_length=32)

        class B2T(models.Model):
            b = models.ForeignKey('Blog')
            t1 = models.ForeignKey('Tag')
            # t2 = models.ForeignKey('Tag')

        class UserInfo(models.Model):
            name=models.CharField(max_length=32)
            email = models.EmailField()
            # 预留的方法
            def clean(self):
                from django.core.exceptions import ValidationError
                c = UserInfo.objects.filter(name=self.name).count()
                if c:
                    # 主动报错
                    raise ValidationError(message='用户名已经存在',code='i1')    

    # login.html
    
        <form id="fm">
            {% csrf_token %}
            <p><input type="text"name="username"></p>
            <p><input type="password"name="password"></p>
            <p><a id = 'submit'>提交</a></p>
        </form>

        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            $(function () {
                $('#submit').click(function () {
                    $.ajax({
                        url:'/login.html',
                        type:'POST',
                        data:$('#fm').serialize(),
                        //自行打包了csrf_token
                        success: function (arg) {
                            console.log(arg);
                            arg = JSON.parse(arg);
                            console.log(arg);
                        },
                        error: function () {

                        }
                    })
                })
            });
        </script>
        
        
        
    # forms.py

        from django import forms
        from django.forms import fields
        from django.forms import widgets
        from django.forms.models import ModelChoiceField,ModelMultipleChoiceField
        from app01 import models

        class UserInfoForm(forms.Form):
            user = fields.CharField(
                required= False,
                widget=widgets.Textarea(attrs={'class':'c1'})
            )
            pwd =fields.CharField(
                max_length= 12,
                widget= widgets.PasswordInput(attrs={'class':'c1'})
            )
            user_type = fields.ChoiceField(
                # choices=[(1,'普通用户'),(2,'超级用户')],
                # choices=models.UserType.objects.values_list('id','name'),
                # 增加后无法更新,静态字段
                choices=[],
                widget = widgets.Select
            )
            user_type2 = fields.CharField(widget=widgets.Select(choices=[]))


            # 解决方法二
            user_type3 = ModelChoiceField(
                empty_label='请选择用户类型',
                queryset=models.UserType.objects.all(),
                to_field_name='id'
                # 依赖 models.py中的 def __str__(self): return self.name
                # 否则选项的是对象
            )
            # 解决方法一(推荐)
            def __init__(self,*args,**kwargs):
                # 自定义方法,重新获取
                super(UserInfoForm,self).__init__(*args,**kwargs)
                self.fields['user_type'].choices = models.UserType.objects.values_list('id','name')
                self.fields['user_type2'].widget.choices = models.UserType.objects.values_list('id','name')


            # 验证:
            # 生成html(保留上一次提交的数据)

            # 新URL方式操作(Form方式)
            # Ajax请求通常不使用Form生成html,只使用验证。

        from django.core.exceptions import ValidationError
        class RegisterForm(forms.Form):
            user =fields.CharField()
            email =fields.EmailField()
            # 单独字段
            def clean_user(self):
                c = models.UserInfo.objects.filter(name=self.cleaned_data['user']).count()
                if not c:
                    return self.cleaned_data['user']
                else:
                    raise ValidationError('用户名已经存在',code='xxx')

            def clean_email(self):
                return self.cleaned_data['email']


        class LoginForm(forms.Form):
            user =fields.CharField()
            pwd =fields.CharField()
            # 需整体显示错误信息(用户名是否存在)
            def clean_user(self):
                c = models.UserInfo.objects.filter(name=self.cleaned_data['user']).count()
                if not c:
                    return self.cleaned_data['user']
                else:
                    raise ValidationError('用户名已经存在',code='xxx')

            def clean_pwd(self):
                return self.cleaned_data['pwd']

            def clean(self):
                c = models.UserInfo.objects.filter(name=self.cleaned_data['user'],pwd=self.cleaned_data['pwd']).count()
                if c:
                    return self.clean_data
                else:
                    raise ValidationError('用户名或密码错误')
                    
            # 密码两次输入一致,可在此判断

            def _post_clean(self):
                pass
                
    #index.html            
                
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title></title>
        </head>
        <body>
            <p>{{ obj.user }}</p>
            <p>{{ obj.pwd }}</p>
            <p>{{ obj.user_type }}</p>
            <p>{{ obj.user_type2 }}</p>
            <p>{{ obj.user_type3 }}</p>
        </body>
        </html>   

posted @ 2020-01-18 21:42  badweather  阅读(84)  评论(0编辑  收藏  举报