Django基础篇-3(前端tag、cvb模式)

这一篇接触的内容是前后端分离的。关于前后端分离与不分离的区别,我自己的了解是前后端分离的情况会使他们的耦合度更低,后端实现接口的部分,前端根据接口返回实现展示。而前后端不分离可能会用到一些 Django 的模版语言去识别和渲染。

一、前端 tag 和自定义 tag

新建一个 html 文件用于展示本次页面,在 views 中定义要展示的数据。

 1 def test(request):
 2     import datetime
 3     cur_time = datetime.datetime.now()
 4     age = 18
 5     name = 'marry'
 6     article_content = "朝鲜一哥金三胖,已经登上太阳,为了避免太阳太热,选择晚上奔上太阳"
 7     say = "今天吃饭的时候,碰到一个傻x,那个家伙实在是太213了,公然插队,吃完饭在马路上随地大小便,够sb的。"
 8     navs = ["我的日记", "我的相册", '我的心情', '我的心情1', '我的心情2', '我的心情3']
 9     comment = "<h1 style='font-size:100px'>你好呀</h1>"
10     h1_str = '<p>哈哈哈</p>'
11     js_str="<script>alert('哈哈哈哈')</script>"
12     return render(request,'test.html',locals())#locals把当前所有局部变量返回

1. add

传过来的内容可以直接加上指定的内容,如对传过来的 age 加1:

{{ age|add:'1' }}

当 age 是字符串类型时,加上指定的字符串即代表两个字符串的拼接。

2. 切片(slice)

如果对传过来的内容截取想要的范围,可以使用 slice 这个方法,具体使用:{{ comment|slice:'0:20' }}。填的参数即角标,也是顾头不顾尾。

3. truncatechars(截取前多少个字符显示)

这个用在文章的概览中,如一篇文章,不可能把所有内容都放在文章的列表中展示,此时可以使用这个方法截取指定个数的字符: {{ comment|truncatechars:'40' }} 

如果截取的内容少于原来的内容,则截取的结果会用‘...’代替。

4. list 拼接(join)

如上定义的 navs 是一个 list,如果想把其内容拿出来展示,可以使用 join 方法,举例: {{ navs|join:'===' }} 

5. 长度(length)

使用方法:{{ navs|length }}

可用于字符串也可用于 list。

6. 取指定元素

{{ navs.0 }} 为取第一个元素,但是不能使用 ‘-1’,在上篇写分页的时候遇到了这个问题,如何自动拿到最后一页。思路:可以使用 length 方法

7. 对英文字符的大小写处理

全部大写:{{ name|upper }}

全部小写:{{ name|lower }}

另外,多个方法可以连接使用,如:{{ name|upper|add:'小仙女' }}

8. 默认值

对某个要处理的字段增加默认值,拿不到的话显示默认值:{{ author|default:'焦丽妃' }}

9. 对时间的处理

指定时间的格式:{{ cur_time|date:'Y-m-d h-i-s' }}

需要注意的是,这里的分是用 i 表示的,不同于以往接触到的用 m 表示。

10. js 和 css 注入

这个知识点也牵扯到安全性方面的知识,当前端接收到的数据是带有 html 标签时该如何处理。

通常不做任何操作的话,前端会把标签当作普通字符串来处理,如果我们想让它识别为标签,可以在后面加上‘safe’,表示是安全的。

{{ js_str|safe }}

11. 自定义标签

当现有的功能无法满足我们的需求,比如说对敏感词的替换。

添加自定义标签时,在创建的项目下添加一个 python package,名为“templatetags”

 1 from django import template
 2 
 3 register = template.Library()
 4 
 5 # 自定义filter最多两个参数
 6 @register.filter
 7 def mingan(value,aim='金正恩'):
 8     if '金三胖' in value:
 9         value = value.replace('金三胖',aim)
10     return value

以上实现的是,如果包含上面定义的敏感词,可以替换为使用者自定义的替换词,替换词为空则使用默认值。

在 html 中的应用: {{ comment|mingan:'***' }} 

也可以在 @register.filter(name='你想要的名字') 后面添加 name,这样之后在用的时候就把 mingan 替换为你定义的名字。

自定义标签仅支持输入两个参数,当参数过多时,可以使用 simple_tag,用法如下(接上面的内容写在同一个文件中):

1 @register.simple_tag
2 def mingan3(value,*args):
3     for s in args:
4         if s in value:
5             value = value.replace(s,'**')
6     return value

这种方法可以接收多个参数,使用起来更方便灵活。

 二、fvb 和 cvb

所谓 fvb,就是基于函数的视图;cvb 则是基于类的视图。

配置一个新的 URL,如 stu,目的是实现学生信息的增删改查,如果每个功能都写一个URL的话,未免过于杂乱,可以用同一个URL,通过不同的请求方式实现不同的功能。

  • GET→获取学生信息
  • POST→修改学生信息
  • PUT→新增学生信息
  • DELETE→删除学生信息

例如定义一个名为 StudentView 的类,里面包含了以上四种请求方式的实现。在URL的配置时,类视图不同于函数视图。

path('stu',views2.StudentView.as_view())

补充: as_view() 方法里面实现了根据请求方式去找类里面对应的方法名,如果是 get 请求,它就去找 get 这个函数,找不到就是不支持 get 请求。 

1. 使用 get 请求获取用户信息。

class StudentView(View):    #urls中的配置不一样
    search_field = ['name','phone','addr','work_addr'] #存放支持搜索的字段
    filter_field = ['name','phone','id'] 
    
        def get(self, request):  # request 必须要传
        limit = request.GET.get('limit', 10)
        page = request.GET.get('page', 1)
        search = request.GET.get('search')
        # 过滤
        filter_dict = {}  # 用来过滤的字典
        for field in self.filter_field:  # 循环获取到有哪些过滤的字段
            value = request.GET.get(field)
            if value:
                filter_dict[field] = value
        # 模糊查询
        q_result = Q()
        if search:
            for field in self.search_field:
                d = {'%s__contains' % field: search}
                q_result = Q(**d) | q_result
        all_students = Student.objects.filter(**filter_dict).filter(q_result).values()

        page_obj = Paginator(all_students, limit)
        stus = list(page_obj.get_page(page))
        data = {"error_code": 0, "msg": "操作成功", "count": page_obj.count, "stus": stus}
        return JsonResponse(data, json_dumps_params={'ensure_ascii': False}, encoder=NbJSONEncoder)

以上,request.GET 中包含了URL中填写的信息,是一个QuerySet,可以以字典的方式取值,当我们在URL中传参时,需要用 request.GET.get('***') 来获取参数的具体内容。

模糊查询和过滤的功能,代码值得好好看。

2. 使用 post 请求新增数据。

    def post(self,request):
        stu_form = StudentForm(request.POST)
        if stu_form.is_valid():
            Student.objects.create(**stu_form.cleaned_data)
            data = {"error_code":0,"msg":"添加成功"}
        else:
            data = {"error_code":-1,"msg":stu_form.errors.get_json_data()}

        return JsonResponse(data,json_dumps_params={'ensure_ascii':False},encoder=NbJSONEncoder)

需要补充说明的是,原来使用 HttpResponse 返回数据,需要将数据转成 json 格式的(json_dumps),其实也可以直接用 JsonResponse 返回 json 数据,这个方法接收字典,返回 json。需要注意的是之后的参数定义也要用 json 格式的,如:json_dumps_params={'ensure_ascii':False}

3. 使用 put 请求修改数据

修改数据存在一个问题,简单的实现时,一是不能实现局部修改,二是数据校验的部分如何拿到传过来的数据。已知可以用 request.GET 拿到写在URL中的参数,也可以通过 request.POST 拿到 post 请求的数据,但是没有一个 request.PUT 方法可供使用。

补充:request.META 可以拿到所有的请求数据

put_data,files = request.parse_file_upload(request.META,request)

使用以上方法可以解决获取数据的问题。

以下为解决部分修改和数据校验

    put_data,files = request.parse_file_upload(request.META,request)
    stu_form = StudentForm(put_data) #它校验的是全部的字段
    if stu_form.is_valid(): #通过校验
        Student.objects.filter(id=id).update(**stu_form.cleaned_data)
        data = {"error_code": 0, "msg": "修改成功"}
    else:
        error_keys = set(stu_form.errors.get_json_data().keys())
        put_keys = set(put_data.keys())
        if error_keys & put_keys: #有交集说明有未校验通过的
            data = {"error_code": -1, "msg": stu_form.errors.get_json_data()}
        else: #没有交集说明有未填字段,需要部分更新
            for k in put_keys: #put_data给的字典value默认是list,需要处理一下
                clean_data[k] = put_data.get(k)
            Student.objects.filter(id=id).update(**clean_data)
            data = {"error_code": 0, "msg": "修改成功"}
    return JsonResponse(data, json_dumps_params={'ensure_ascii': False})

put_data 为传过来的数据

stu_form 校验的是全部的字段,如果通过,说明修改的是全部字段,如果未通过,进一步判断。

校验未通过分为两种情况:

  1. 全部字段有不符合要求的情况

  2. 部分修改

先定义报错的信息,因为如果某个字段未通过校验,会把这个字段当作key,错误信息当作 value 存放在stu_form.errors.get_json_data()。所以,error_keys 存放报错的 key,put_keys 存在传过来的 key。

对第一种情况,就是 error_keys 和 put_keys 有交集,意思是传了值但没通过校验;对第二种情况,两个 keys 没有交集,说明传过来的都通过校验,没通过校验是因为没有传,对这部分字段不做修改,只修改 put_keys 传过来的,进而达到部分修改的目的。

 4. DELETE 实现删除数据功能

    def delete(self,request):
        id = request.GET.get('id',0)
        Student.objects.filter(id=id).delete()
        data = {"error_code":0,"msg":"删除成功"}
        return JsonResponse(data,json_dumps_params={'ensure_ascii':False},encoder=NbJSONEncoder)

除 get 请求,其他请求方式在测试时需要用 postman 来验证。

三、Form(用来校验请求数据)

 1 class StudentForm(forms.Form): #为student做数据校验
 2     name = forms.CharField(min_length=2,max_length=10,required=True) #required=True表示必填,默认必填
 3     phone = forms.CharField(min_length=11,max_length=11)
 4     money = forms.FloatField(required=False)
 5 #     自定义函数校验是否字段重复
 6     def clean_phone(self):
 7         '''钩子'''
 8         phone = self.cleaned_data['phone']
 9         if models.Student.objects.filter(phone=phone):
10             return self.errors.add('手机号错误','手机号已经存在')
11         return phone
12     # def clean(self):
13     #     '''多个字段校验'''
14     #     pass

这是一种稍微麻烦点的数据校验的方法,是把要校验的数据自己定义了写在函数中。

另外一种是直接继承 ModelForm,使用的校验方法是在数据库定义时的校验方法,如下:

class StudentForm(ModelForm):
    class Meta:
        model = Student
        # fields ='__all__'
        fields = ['name','phone']
        exclude = ['money'] #排除哪个字段

使用的方法为: stu_form = StudentForm(request.POST) 

后面括号中传的是要校验的数据。上面也提到了,这个方法是校验所有的字段,如果某个字段未通过校验,会把这个字段当作key,错误信息当作 value 存放在stu_form.errors.get_json_data()。

o

O

猜你喜欢

转载自www.cnblogs.com/april-aaa/p/11750236.html