第八章(6)


  1. modelform
  2. 原生ajax
  3. 上传文件,XMLHttpRequest,jquery,iframe 
  4. XMLHttpRequest,jquery,iframe 应用场景
  5. 图片验证码 + session
  6. KindEdittor博客插件
  7. 前端组合搜索
  8. jsonp
  9. xss过滤

1,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={...})
            
            http://www.cnblogs.com/wupeiqi/articles/6229414.html

urls.py

from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from app01 import views
urlpatterns = [
    #path('admin/', admin.site.urls),
    url(r'^index/',views.index),
    url(r'^user_list/',views.user_list),
    url(r'^edit-(\d+)',views.user_edit)
]

models.py

from django.db import models

# Create your models here.

class UserType(models.Model):
    caption = models.CharField(max_length=32)

    def __str__(self):
        return self.caption


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

    def __str__(self):
        return self.name



class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    email = models.EmailField()
    user_type = models.ForeignKey(to='UserType',to_field='id',on_delete=models.CASCADE)
    u2g = models.ManyToManyField(UserGroup)

    def __unicode__(self):
        return self.username,self.email

views.py

from django.shortcuts import render,HttpResponse
from app01 import models

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': '邮箱',
            'u2g' : '用户组',
            'user_type' : '用户类型'
        }
        help_texts = {
            'username': '帮助'
        }
        widgets = {
            'username': Fwidgets.Textarea(attrs={'class': 'c1'})
        }
        error_messages = {
            '__all__':{

            },
            'email': {
                'required': '邮箱不能为空',
                'invalid': '邮箱格式错误..',
            }
        }
        field_classes = {
            # 'email': Ffields.URLField
        }

        # localized_fields=('ctime',)

    def clean_username(self):
        old = self.cleaned_data['username']
        return old

# class UserInfoForm(forms.Form):
#     username = Ffields.CharField(max_length=32)
#     email = Ffields.EmailField()
#     user_type = Ffields.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')


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()


        # print(obj.is_valid())
        # print(obj.cleaned_data)
        # print(obj.errors.as_json())
        return render(request,'index.html',{'obj': obj})


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})

index.html




    
    Title


    
{% csrf_token %} {{ obj.as_p }}

user_edit.html




    
    Title


    
{% csrf_token %} {{ mf.as_p }}

user_list.html




    
    Title


       
    {% for row in li %}
  • {{ row.username }} - {{ row.user_type.caption }} - 编辑
  • {% endfor %}

modelsfrom验证过程

1,models字段正则表达式验证
2,models验证通过返回is_valid()
2,错误验证过程(errors.as_data)	
	2.1 error下的self.full_clean()
	2.2 def full_clean(self):
	2.3 
		 self._clean_fields()
          self._clean_form()
          self._post_clean()
           def clean(self):

2,原生ajax

http://www.cnblogs.com/wupeiqi/articles/5703697.html

1、XmlHttpRequest对象介绍 

    XmlHttpRequest对象的主要方法: 
a. void open(String method,String url,Boolen async)
   用于创建请求
    
   参数:
       method: 请求方式(字符串类型),如:POST、GET、DELETE...
       url:    要请求的地址(字符串类型)
       async:  是否异步(布尔类型)
 
b. void send(String body)
    用于发送请求
 
    参数:
        body: 要发送的数据(字符串类型)
 
c. void setRequestHeader(String header,String value)
    用于设置请求头
 
    参数:
        header: 请求头的key(字符串类型)
        vlaue:  请求头的value(字符串类型)
 
d. String getAllResponseHeaders()
    获取所有响应头
 
    返回值:
        响应头数据(字符串类型)
 
e. String getResponseHeader(String header)
    获取响应头中指定header的值
 
    参数:
        header: 响应头的key(字符串类型)
 
    返回值:
        响应头中指定的header对应的值
 
f. void abort()
 
    终止请求

XmlHttpRequest对象的主要属性:

a. Number readyState
   状态值(整数)
 
   详细:
      0-未初始化,尚未调用open()方法;
      1-启动,调用了open()方法,未调用send()方法;
      2-发送,已经调用了send()方法,未接收到响应;
      3-接收,已经接收到部分响应数据;
      4-完成,已经接收到全部响应数据;
 
b. Function onreadystatechange
   当readyState的值改变时自动触发执行其对应的函数(回调函数)
 
c. String responseText
   服务器返回的数据(字符串类型)
 
d. XmlDocument responseXML
   服务器返回的数据(Xml对象)
 
e. Number states
   状态码(整数),如:200、404...
 
f. String statesText
   状态文本(字符串),如:OK、NotFound...

views.py

def ajax(request):
    return render(request, 'ajax.html')

ajax.html




    
    


    
    


    

    

4,上传文件,XMLHttpRequest,jquery,iframe 

from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from app01 import views
urlpatterns = [
    #path('admin/', admin.site.urls),
    url(r'^index/',views.index),
    url(r'^user_list/',views.user_list),
    url(r'^edit-(\d+)',views.user_edit),
    url(r'^ajax/',views.ajax),
    url(r'^ajax_json/$',views.ajax_json),
    url(r'^upload/$',views.upload),
    url(r'^upload_file/$', views.upload_file),

]

views.py

def upload(request):
    return render(request,'upload.html')

def upload_file(request):
    username = request.POST.get('username')
    fafafa = request.FILES.get('fafafa')
    import os
    img_path = os.path.join('static/imgs/',fafafa.name)
    with open(img_path,'wb') as f:
        for item in fafafa.chunks():
            f.write(item)
    ret = {'code': True,'data': img_path}
    import json
    return HttpResponse(json.dumps(ret))

html




    
    Title
    


    
    
    
    

4,原生jquery,jquery,iframe应用场景

如果发送的是普通数--> 1,jquery 2,XMLHttpRequest 3,iframe
如果是文件 ----> 1,iframe 2,XMLHttpRequest(ajax和原生)

5,图片验证码 + session

1,session
2,check_code.py(依赖:Pillow,字体文件)
3,src属性后面加 (刷新)
 

urls.py

urlpatterns = [
    url(r'^check_code.html$', account.check_code),
]

views.py

from utils.check_code import create_validate_code

def check_code(request):
    """
    验证码
    :param request:
    :return:
    """
    # stream = BytesIO()
    # img, code = create_validate_code()
    # img.save(stream, 'PNG')
    # request.session['CheckCode'] = code
    # return HttpResponse(stream.getvalue())

    # data = open('static/imgs/avatar/20130809170025.png','rb').read()
    # return HttpResponse(data)

    # 1. 创建一张图片 pip3 install Pillow
    # 2. 在图片中写入随机字符串
    # obj = object()
    # 3. 将图片写入到制定文件
    # 4. 打开制定目录文件,读取内容
    # 5. HttpResponse(data)

    stream = BytesIO()
    img, code = create_validate_code()
    img.save(stream,'PNG')
    request.session['CheckCode'] = code
    return HttpResponse(stream.getvalue())

check_code.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter

_letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小写字母,去除可能干扰的i,l,o,z
_upper_cases = _letter_cases.upper()  # 大写字母
_numbers = ''.join(map(str, range(3, 10)))  # 数字
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))


def create_validate_code(size=(120, 30),
                         chars=init_chars,
                         img_type="GIF",
                         mode="RGB",
                         bg_color=(255, 255, 255),
                         fg_color=(0, 0, 255),
                         font_size=18,
                         font_type="Monaco.ttf",
                         length=4,
                         draw_lines=True,
                         n_line=(1, 2),
                         draw_points=True,
                         point_chance=2):
    """
    @todo: 生成验证码图片
    @param size: 图片的大小,格式(宽,高),默认为(120, 30)
    @param chars: 允许的字符集合,格式字符串
    @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
    @param mode: 图片模式,默认为RGB
    @param bg_color: 背景颜色,默认为白色
    @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
    @param font_size: 验证码字体大小
    @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
    @param length: 验证码字符个数
    @param draw_lines: 是否划干扰线
    @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
    @param draw_points: 是否画干扰点
    @param point_chance: 干扰点出现的概率,大小范围[0, 100]
    @return: [0]: PIL Image实例
    @return: [1]: 验证码图片中的字符串
    """

    width, height = size  # 宽高
    # 创建图形
    img = Image.new(mode, size, bg_color)
    draw = ImageDraw.Draw(img)  # 创建画笔

    def get_chars():
        """生成给定长度的字符串,返回列表格式"""
        return random.sample(chars, length)

    def create_lines():
        """绘制干扰线"""
        line_num = random.randint(*n_line)  # 干扰线条数

        for i in range(line_num):
            # 起始点
            begin = (random.randint(0, size[0]), random.randint(0, size[1]))
            # 结束点
            end = (random.randint(0, size[0]), random.randint(0, size[1]))
            draw.line([begin, end], fill=(0, 0, 0))

    def create_points():
        """绘制干扰点"""
        chance = min(100, max(0, int(point_chance)))  # 大小限制在[0, 100]

        for w in range(width):
            for h in range(height):
                tmp = random.randint(0, 100)
                if tmp > 100 - chance:
                    draw.point((w, h), fill=(0, 0, 0))

    def create_strs():
        """绘制验证码字符"""
        c_chars = get_chars()
        strs = ' %s ' % ' '.join(c_chars)  # 每个字符前后以空格隔开

        font = ImageFont.truetype(font_type, font_size)
        font_width, font_height = font.getsize(strs)

        draw.text(((width - font_width) / 3, (height - font_height) / 3),
                  strs, font=font, fill=fg_color)

        return ''.join(c_chars)

    if draw_lines:
        create_lines()
    if draw_points:
        create_points()
    strs = create_strs()

    # 图形扭曲参数
    params = [1 - float(random.randint(1, 2)) / 100,
              0,
              0,
              0,
              1 - float(random.randint(1, 10)) / 100,
              float(random.randint(1, 2)) / 500,
              0.001,
              float(random.randint(1, 2)) / 500
              ]
    img = img.transform(size, Image.PERSPECTIVE, params)  # 创建扭曲

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)  # 滤镜,边界加强(阈值更大)

    return img, strs

6,KindEdittor博客插件

上传文件

urlpatterns = [
    url(r'^upload/$', views.upload),
    url(r'^upload_file/$', views.upload_file),
    url(r'^kind/$', views.kind),
    url(r'^upload_img/$', views.upload_img),
    url(r'^file_manager/$', views.file_manager),
]



    
    


{% csrf_token %}
\
def upload(request):
    return render(request,'upload.html')


def kind(request):
    return render(request, 'kind.html')
    
#上传文件
def upload_img(request):
    #dir可以用来判断是文件或图片
    request.GET.get('dir')
    print(request.FILES.get('fafafa'))
    # 获取文件保存
    import json
    dic = {
        'error': 0,
        'url': '/static/imgs/20130809170025.png',
        'message': '错误了...'
    }

    return HttpResponse(json.dumps(dic))
import os
import time
import json

#文件空间管理
def file_manager(request):
    """
    文件管理
    :param request:
    :return:
    {
        moveup_dir_path:
        current_dir_path:
        current_url:
        file_list: [
            {
                'is_dir': True,
                'has_file': True,
                'filesize': 0,
                'dir_path': '',
                'is_photo': False,
                'filetype': '',
                'filename': xxx.png,
                'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
            },
            {
                'is_dir': True,
                'has_file': True,
                'filesize': 0,
                'dir_path': '',
                'is_photo': False,
                'filetype': '',
                'filename': xxx.png,
                'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
            }
        ]

    }
    """
    
    
    dic = {}
    root_path = 'C:/Users/Administrator/PycharmProjects/day24/static/'
    static_root_path = '/static/'
    request_path = request.GET.get('path')
    if request_path:
        #上传文件目录
        abs_current_dir_path = os.path.join(root_path, request_path)
        #去掉 /
        move_up_dir_path = os.path.dirname(request_path.rstrip('/'))
        dic['moveup_dir_path'] = move_up_dir_path + '/' if move_up_dir_path else move_up_dir_path

    else:
        abs_current_dir_path = root_path
        dic['moveup_dir_path'] = ''

    dic['current_dir_path'] = request_path
    dic['current_url'] = os.path.join(static_root_path, request_path)

    file_list = []
    for item in os.listdir(abs_current_dir_path):
        abs_item_path = os.path.join(abs_current_dir_path, item)
        a, exts = os.path.splitext(item)
        is_dir = os.path.isdir(abs_item_path)
        #判断是文件或目录
        if is_dir:
            temp = {
                'is_dir': True,
                'has_file': True,
                'filesize': 0,
                'dir_path': '',
                'is_photo': False,
                'filetype': '',
                'filename': item,
                'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
            }
        else:
            temp = {
                'is_dir': False,
                'has_file': False,
                'filesize': os.stat(abs_item_path).st_size,
                'dir_path': '',
                'is_photo': True if exts.lower() in ['.jpg', '.png', '.jpeg'] else False,
                'filetype': exts.lower().strip('.'),
                'filename': item,
                'datetime': time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(os.path.getctime(abs_item_path)))
            }

        file_list.append(temp)
    dic['file_list'] = file_list
    return HttpResponse(json.dumps(dic))

http://www.cnblogs.com/wupeiqi/articles/6307554.html

7,前端组合搜索

 1 from django.contrib import admin
 2 from django.urls import path
 3 from django.conf.urls import url
 4 from app import views
 5 
 6 urlpatterns = [
 7     #path('admin/', admin.site.urls),
 8     url(r'^article-(?P\d+)-(?P\d+).html',views.article,name='article'),
 9 
10 ]
url.py
 1 from django.db import models
 2 
 3 # Create your models here.
 4 
 5 class Category(models.Model):
 6     caption = models.CharField(max_length=16)
 7 
 8 class ArticleType(models.Model):
 9     caption = models.CharField(max_length=16)
10 
11 class Article(models.Model):
12     title = models.CharField(max_length=32)
13     content = models.CharField(max_length=255)
14 
15     category = models.ForeignKey(Category,on_delete=models.CASCADE)
16     article_type = models.ForeignKey(ArticleType,on_delete=models.CASCADE)
models.py
 1 from django.shortcuts import render
 2 from app import models
 3 # Create your views here.
 4 
 5 def article(request,*args,**kwargs):
 6     print(kwargs)
 7     condition = {}
 8     for k,v in kwargs.items():
 9         kwargs[k] = int(v)
10         if v == '0':
11             pass
12         else:
13             condition[k] = v
14 
15     article_type_list = models.ArticleType.objects.all()
16     category_list = models.Category.objects.all()
17     result = models.Article.objects.filter(**condition)
18     return render(
19         request,'article.html',{'result':result,
20                                 'article_type_list':article_type_list,
21                                 'category':category_list,
22                                 'arg_dict': kwargs,
23                                 }
24     )
views.py
 1 
 2 "en">
 3 
 4     "UTF-8">
 5     Title
 6     
17 
18 
19 

过滤条件

20
class="condition"> 21 {% if arg_dict.article_type_id == 0 %} 22 class="active" href="/article-0-{{ arg_dict.category_id }}.html">全部 23 {% else %} 24 "/article-0-{{ arg_dict.category_id }}.html">全部 25 {% endif %} 26 {% for row in article_type_list %} 27 {% if row.id == arg_dict.article_type_id %} 28 class="active" href="/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }} 29 {% else %} 30 "/article-{{ row.id }}-{{ arg_dict.category_id }}.html">{{ row.caption }} 31 {% endif %} 32 {% endfor %} 33
34 35
class="condition"> 36 {% if arg_dict.category_id == 0 %} 37 class="active" href="/article-{{ arg_dict.article_type_id }}-0.html">全部 38 {% else %} 39 "/article-{{ arg_dict.article_type_id }}-0.html">全部 40 {% endif %} 41 {% for row in category %} 42 {% if row.id == arg_dict.category_id %} 43 class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html">{{ row.caption }} 44 {% else %} 45 "/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html">{{ row.caption }} 46 {% endif %} 47 {% endfor %} 48
49

查询结果

50 {% for row in result %} 51
  • {{ row.id }}-{{ row.title }}-{{ row.content }}
  • 52 {% endfor %} 53 54
    article.html

    优化版

     1 from django.db import models
     2 
     3 # Create your models here.
     4 
     5 class Category(models.Model):
     6     caption = models.CharField(max_length=16)
     7 
     8 # class ArticleType(models.Model):
     9 #     caption = models.CharField(max_length=16)
    10 
    11 class Article(models.Model):
    12     title = models.CharField(max_length=32)
    13     content = models.CharField(max_length=255)
    14 
    15     category = models.ForeignKey(Category)
    16     # article_type = models.ForeignKey(ArticleType)
    17 
    18     type_choice = (
    19         (1,'Python'),
    20         (2,'OpenStack'),
    21         (3,'Linux'),
    22     )
    23     article_type_id = models.IntegerField(choices=type_choice)
    models.py
     1 from django.shortcuts import render
     2 from app01 import models
     3 
     4 def article(request,*args,**kwargs):
     5     print(kwargs)
     6     # print(request.path_info) # 获取当前URL
     7     # from django.urls import reverse
     8     # # {'article_type_id': '0', 'category_id': '0'}
     9     # url = reverse('article',kwargs={'article_type_id': '1', 'category_id': '0'})
    10     # print(url)
    11     # print(kwargs) # {'article_type_id': '0', 'category_id': '0'}
    12     condition = {}
    13     for k,v in kwargs.items():
    14         kwargs[k] = int(v)
    15         if v == '0':
    16             pass
    17         else:
    18             condition[k] = v
    19 
    20     # article_type_list = models.ArticleType.objects.all()
    21     article_type_list = models.Article.type_choice
    22     category_list = models.Category.objects.all()
    23     result = models.Article.objects.filter(**condition)
    24     return  render(
    25         request,
    26         'article.html',
    27         {
    28             'result': result,
    29             'article_type_list': article_type_list,
    30             'category_list': category_list,
    31             'arg_dict': kwargs
    32         }
    33     )
    views.py
     1 from django import template
     2 from django.utils.safestring import mark_safe
     3 register = template.Library()
     4 
     5 @register.simple_tag
     6 def filter_all(arg_dict,k):
     7     """
     8     {% if arg_dict.article_type_id == 0 %}
     9         全部
    10     {% else %}
    11         全部
    12     {% endif %}
    13     :return:
    14     """
    15     if k == 'article_type_id':
    16         n1 = arg_dict['article_type_id']
    17         n2 = arg_dict['category_id']
    18         if n1 == 0:
    19             ret = '全部' % n2
    20         else:
    21             ret = '全部' % n2
    22     else:
    23         n1 = arg_dict['category_id']
    24         n2 = arg_dict['article_type_id']
    25         if n1 == 0:
    26             ret = '全部' % n2
    27         else:
    28             ret = '全部' % n2
    29 
    30     return mark_safe(ret)
    31 
    32 @register.simple_tag
    33 def filter_article_type(article_type_list,arg_dict):
    34     """
    35     {% for row in article_type_list %}
    36         {% if row.id == arg_dict.article_type_id %}
    37 
    38         {% else %}
    39             {{ row.caption }}
    40         {% endif %}
    41     {% endfor %}
    42     :return:
    43     """
    44     ret = []
    45     for row in article_type_list:
    46         if row[0] == arg_dict['article_type_id']:
    47             temp = '%s' %(row[0],arg_dict['category_id'],row[1],)
    48         else:
    49             temp = '%s' %(row[0],arg_dict['category_id'],row[1],)
    50         ret.append(temp)
    51     return mark_safe(''.join(ret))
    templatetags/filter.py
     1 {% load filter %}
     2 
     3 "en">
     4 
     5     "UTF-8">
     6     
     7     
    18 
    19 
    20     

    过滤条件

    21
    class="condition"> 22
    23 {% filter_all arg_dict 'article_type_id' %} 24 {% filter_article_type article_type_list arg_dict %} 25
    26 27
    28 {% filter_all arg_dict 'category_id' %} 29 {% for row in category_list %} 30 {% if row.id == arg_dict.category_id %} 31 class="active" href="/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html">{{ row.caption }} 32 {% else %} 33 "/article-{{ arg_dict.article_type_id }}-{{ row.id }}.html">{{ row.caption }} 34 {% endif %} 35 {% endfor %} 36
    37
    38

    查询结果

    39
      40 {% for row in result %} 41
    • {{ row.id }}-{{ row.title }}
    • 42 {% endfor %} 43
    44 45
    article.html

    8,jsonp

    由于浏览器具有同源策略(阻止Ajax请求,无法阻止 13 34 35 req.html

    9,xss过滤(防攻击)

     1 import os
     2 import json
     3 import uuid
     4 from django.shortcuts import render
     5 from django.shortcuts import HttpResponse
     6 from django.shortcuts import redirect
     7 from django.db import transaction
     8 from django.urls import reverse
     9 
    10 from ..forms.article import ArticleForm
    11 from ..auth.auth import check_login
    12 from repository import models
    13 from utils.pagination import Pagination
    14 from utils.xss import XSSFilter
    15 
    16 
    17 def add_article(request):
    18     """
    19     添加文章
    20     :param request:
    21     :return:
    22     """
    23     if request.method == 'GET':
    24         form = ArticleForm(request=request)
    25         return render(request, 'backend_add_article.html', {'form': form})
    26     elif request.method == 'POST':
    27         form = ArticleForm(request=request, data=request.POST)
    28         if form.is_valid():
    29 
    30             with transaction.atomic():
    31                 tags = form.cleaned_data.pop('tags')
    32                 content = form.cleaned_data.pop('content')
    33                 print(content)
    34                 #调用防攻击类
    35                 content = XSSFilter().process(content)
    36                 form.cleaned_data['blog_id'] = request.session['user_info']['blog__nid']
    37                 obj = models.Article.objects.create(**form.cleaned_data)
    38                 models.ArticleDetail.objects.create(content=content, article=obj)
    39                 tag_list = []
    40                 for tag_id in tags:
    41                     tag_id = int(tag_id)
    42                     tag_list.append(models.Article2Tag(article_id=obj.nid, tag_id=tag_id))
    43                 models.Article2Tag.objects.bulk_create(tag_list)
    44 
    45             return redirect('/backend/article-0-0.html')
    46         else:
    47             return render(request, 'backend_add_article.html', {'form': form})
    48     else:
    49         return redirect('/')
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from bs4 import BeautifulSoup
     4 
     5 
     6 class XSSFilter(object):
     7     __instance = None
     8 
     9     def __init__(self):
    10         # XSS白名单
    11         self.valid_tags = {
    12             "font": ['color', 'size', 'face', 'style'],
    13             'b': [],
    14             'div': [],
    15             "span": [],
    16             "table": [
    17                 'border', 'cellspacing', 'cellpadding'
    18             ],
    19             'th': [
    20                 'colspan', 'rowspan'
    21             ],
    22             'td': [
    23                 'colspan', 'rowspan'
    24             ],
    25             "a": ['href', 'target', 'name'],
    26             "img": ['src', 'alt', 'title'],
    27             'p': [
    28                 'align'
    29             ],
    30             "pre": ['class'],
    31             "hr": ['class'],
    32             'strong': []
    33         }
    34 
    35     def __new__(cls, *args, **kwargs):
    36         """
    37         单例模式
    38         :param cls:
    39         :param args:
    40         :param kwargs:
    41         :return:
    42         """
    43         if not cls.__instance:
    44             obj = object.__new__(cls, *args, **kwargs)
    45             cls.__instance = obj
    46         return cls.__instance
    47 
    48     def process(self, content):
    49         soup = BeautifulSoup(content, 'html.parser')
    50         # 遍历所有HTML标签
    51         for tag in soup.find_all(recursive=True):
    52             # 判断标签名是否在白名单中
    53             if tag.name not in self.valid_tags:
    54                 tag.hidden = True
    55                 if tag.name not in ['html', 'body']:
    56                     tag.hidden = True
    57                     tag.clear()
    58                 continue
    59             # 当前标签的所有属性白名单
    60             attr_rules = self.valid_tags[tag.name]
    61             keys = list(tag.attrs.keys())
    62             for key in keys:
    63                 if key not in attr_rules:
    64                     del tag[key]
    65 
    66         return soup.decode()
    67 
    68 
    69 if __name__ == '__main__':
    70     html = """

    71 The Dormouse's story 72

    73

    74

    75 Once upon a time there were three little sisters; and their names were 76 77 Lacie and 78 Tilffffffffffffflie; 79 and they lived at the bottom of a well. 80 81
    82

    83

    ...

    """ 84 85 obj = XSSFilter() 86 v = obj.process(html) 87 print(v)

    相关