python运维开发(二十二)---JSONP、瀑布流、组合搜索、多级评论、tornado框架简介

时间:2022-11-20 09:44:47

内容目录:

  • JSONP应用
  • 瀑布流布局
  • 组合搜索
  • 多级评论
  • tornado框架简介

JSONP应用

由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。

特别的:由于同源策略是浏览器的限制,所以请求的发送和响应是可以进行,只不过浏览器不接受罢了。

浏览器同源策略并不是对所有的请求均制约:

  • 制约: XmlHttpRequest
  • 不制约(不生效)的标签: img、iframe、script等具有src属性的标签

JSONP(JSONP - JSON with Padding是JSON的一种“使用模式”),利用script标签的src属性(浏览器允许script标签跨域)

几种方式的对比查看,本机访问另一个域名方式采用另一个django项目方式

访问过程中需要绑定hosts 127.0.0.1 jabe.com

django项目jsonp1

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^get_data/', views.get_data),

url code

from django.shortcuts import render,HttpResponse

# Create your views here.

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

def get_data(request):
    return HttpResponse('ok')
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Index</h1>

    <input type="button" onclick="Ajax();" value="普通AJax"/>
    <input type="button" onclick="Ajax2();" value="跨域普通AJax"/>
    <input type="button" onclick="Ajax3();" value="跨域牛逼AJax"/>
    <input type="button" onclick="Ajax4();" value="江西TV"/>

    <script src="/static/jquery-2.1.4.min.js"></script>
    <script>
        function Ajax(){
            $.ajax({
                url: '/get_data/',
                type: 'POST',
                data: {'k1': 'v1'},
                success: function (arg) {
                    alert(arg);
                }
            })
        }

        function Ajax2(){
            $.ajax({
                url: 'http://jabe.com:8001/api/',
                type: 'GET',
                data: {'k1': 'v1'},
                success: function (arg) {
                    alert(arg);
                }
            })
        }
        function Ajax3(){
            // script
            // alert(api)
            var tag = document.createElement('script');
            tag.src = 'http://jabe.com:8001/api/';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function fafafa(arg){
            console.log(arg);
        }
        function Ajax4(){
            // script
            // alert(api)
            var tag = document.createElement('script');
            tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }
        function list(arg){
            console.log(arg);
        }
    </script>
</body>
</html>

index html code

第二个项目jsonp2

from django.conf.urls import url
from django.contrib import admin
from app001 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', views.api),
]

url code

def api(request):
    li = ['jabe', 'ljb', 'tony']
    temp = "fafafa(%s)" %(json.dumps(li))
    return HttpResponse(temp)

同时可以直接设置ajax发送请求类型设置为JSONP,即dataType:JSONP,

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="Jsonp1();"  value='提交'/>
    </p>

    <p>
        <input type="button" onclick="Jsonp2();" value='提交'/>
    </p>

    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>
        function Jsonp1(){
            var tag = document.createElement('script');
            tag.src = "http://c2.com:8000/test/";
            document.head.appendChild(tag);
            document.head.removeChild(tag);

        }

        function Jsonp2(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'GET',
                dataType: 'JSONP',
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }

    </script>
</body>
</html>

demo

jsonp的callback和list

dataType: jsonp
jsonp: 'callback',
jsonpCallback: 'list'

function list(arg){
            console.log(arg);
}

- jsonp: callback      # request.GET.get("callback")
- jsonpCallback: 'list' # list(...)

jsonp不能发送POST请求

==> 最终全部都会转换成GET请求  

扩展

CORS-跨站资源共享,浏览器版本要求

瀑布流布局

在实际的环境中我们的网页可能会出现并排的布局,但是图片和内容大小不一致,我们希望下面并排挨着上面紧凑布局方式,因此就用到了瀑布流布局。

实例展示

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^student/', views.student),
]

url code

from django.shortcuts import render

# Create your views here.

def student(request):
    img_list = [
        {
        {
        {'src': '3.jpg', 'title': 'asdfasdfasdf','content': 'asdf'},
        {'src': '4.jpg', 'title': 'asdfasdfasdf','content': 'asdf'},
        {
        {'src': '21.jpg', 'title': 'asdfasdfasdf','content': 'asdf'},
    ]

    return render(request, 'student.html', {"img_list":img_list})
{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .container{
            width: 980px;
            margin: 0 auto;
        }
        .container .column{
            float: left;
            width: 245px;
        }
        .container .item img{
            width: 245px;
        }
    </style>
</head>
<body>

    <div class="container">
        <div class="column">
            {% for i in img_list %}
                {% if forloop.counter|detail1:"4,1" %}
                    <div class="item">
                        {{ forloop.counter }}
                        <img src="/static/{{ i.src }}">
                    </div>
                {% endif %}
            {% endfor %}
        </div>
        <div class="column">
            {% for i in img_list %}
                {% if forloop.counter|detail1:"4,2" %}
                    <div class="item">
                        {{ forloop.counter }}
                        <img src="/static/{{ i.src }}">
                    </div>
                {% endif %}
            {% endfor %}
        </div>
        <div class="column">
            {% for i in img_list %}
                {% if forloop.counter|detail1:"4,3" %}
                    <div class="item">
                        {{ forloop.counter }}
                        <img src="/static/{{ i.src }}">
                    </div>
                {% endif %}
            {% endfor %}
        </div>
        <div class="column">
            {% for i in img_list %}
                {% if forloop.counter|detail1:"4,0" %}
                    <div class="item">
                        {{ forloop.counter }}
                        <img src="/static/{{ i.src }}">
                    </div>
                {% endif %}
            {% endfor %}
        </div>
    </div>

</body>
</html>

student html code

# Author:Alex Li
from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError

register = template.Library()

@register.filter
def detail1(value,arg):

    """
    查看余数是否等于remainder arg="1,2"
    :param counter:
    :param allcount:
    :param remainder:
    :return:
    """
    allcount, remainder = arg.split(',')
    allcount = int(allcount)
    remainder = int(remainder)
    if value%allcount == remainder:
        return True
    return False

templatetags xx.py

组合搜索

在很多的电商网站类似京东和淘宝都有多级组合的筛选条件来找到自己想要的商品,我们来做一下这个组合搜索的功能

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # url(r'^student/', views.student),
    url(r'^video-(?P<direction_id>\d+)-(?P<classfication_id>\d+)-(?P<level_id>\d+).html', views.video),
]

Url Code

from django.shortcuts import render
from app01 import models
# Create your views here.

def video(request,**kwargs):
    print(kwargs)
    print(request.path_info)
    current_url = request.path_info
    direction_id = kwargs.get(')
    classfication_id = kwargs.get(')
    q = {}
    # 方向是0
    ':
        cList = models.Classification.objects.values('id', 'name')
        # 分类是0
        ':
            # video-0-0
            pass
        else:
            # video-0-1
            # 选中了某个分类
            q['classification__id'] = classfication_id
    else:
        obj = models.Direction.objects.get(id=direction_id)
        temp = obj.classification.all().values('id','name')
        id_list = list(map(lambda x:x['id'],temp))

        cList = obj.classification.all().values('id','name')

        ':
            # video-1-0
            # 根据风向ID,找到所属的分类ID

            print(id_list)
            q['classification__id__in'] = id_list
        else:
            # video-1-1
            if int(classfication_id) in id_list:
                q['classification__id'] = classfication_id
            else:
                q['classification__id__in'] = id_list
                url_list = current_url.split('-')
                url_list[2] = "
                current_url = '-'.join(url_list)
    level_id = kwargs.get('level_id',None)
    ':
        q['level'] = level_id

    result = models.Video.objects.filter(**q)

    dList = models.Direction.objects.values('id', 'name')

    lList = models.Video.level_choice
    # level_choice = (
    #     (1, u'初级'),
    #     (2, u'中级'),
    #     (3, u'高级'),
    # )
    return render(request, 'video.html', {"dList":dList,
                                            'cList': cList,
                                            'lList': lList,
                                          'current_url': current_url})
from django.db import models

# 技术方向,
class Direction(models.Model):
    name = models.CharField(verbose_name='名称', max_length=32)

    classification = models.ManyToManyField('Classification')

    class Meta:
        db_table = 'Direction'
        verbose_name_plural = u'方向(视频方向)'

    def __str__(self):
        return self.name

# 技术分类、语言
class Classification(models.Model):
    name = models.CharField(verbose_name='名称', max_length=32)

    class Meta:
        db_table = 'Classification'
        verbose_name_plural = u'分类(视频分类)'

    def __str__(self):
        return self.name

# 技术视频,
class Video(models.Model):
    level_choice = (
        (1, u'初级'),
        (2, u'中级'),
        (3, u'高级'),
    )
    level = models.IntegerField(verbose_name='级别', choices=level_choice, default=1)

    classification = models.ForeignKey('Classification', null=True, blank=True)

    title = models.CharField(verbose_name='标题', max_length=32)
    summary = models.CharField(verbose_name='简介', max_length=32)
    img = models.ImageField(verbose_name='图片', upload_to='./static/images/Video/')
    href = models.CharField(verbose_name='视频地址', max_length=256)

    create_date = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'Video'
        verbose_name_plural = u'视频'

    def __str__(self):
        return self.title

Models Code

{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .condition a{
            display: inline-block;
            padding: 5px;
        }
        .condition a.active{
            background-color: coral;
            color: white;
        }
    </style>
</head>
<body>
    <div class="condition">
        <div>
            {% all_menu current_url %} :
            {% for i in dList %}
                {% ac1 current_url i.id i.name %}
            {% endfor %}
        </div>
        <div>
            {% for i in cList %}
                {% ac2 current_url i.id i.name %}
            {% endfor %}
        </div>
        <div>
            {% for i in lList %}
                {% ac3 current_url i.0 i.1 %}

            {% endfor %}
        </div>
    </div>

</body>
</html>

Video html Code

多级评论

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^comment/', views.comment),

]

url code

from django.shortcuts import render
import collections
# Create your views here.

def tree_search(d_dic, comment_obj):
    # 在comment_dic中一个一个的寻找其回复的评论
    # 检查当前评论的 reply_id 和 comment_dic中已有评论的nid是否相同,
    # 如果相同,表示就是回复的此信息
    #   如果不同,则需要去 comment_dic 的所有子元素中寻找,一直找,如果一系列中未找,则继续向下找
    for k, v_dic in d_dic.items():
        # 找回复的评论,将自己添加到其对应的字典中,例如: {评论一: {回复一:{},回复二:{}}}
        if k[0] == comment_obj[2]:
            d_dic[k][comment_obj] = collections.OrderedDict()
            return
        else:
            # 在当前第一个跟元素中递归的去寻找父亲
            tree_search(d_dic[k], comment_obj)

def build_tree(comment_list):
    comment_dic = collections.OrderedDict()

    for comment_obj in comment_list:
        if comment_obj[2] is None:
            # 如果是根评论,添加到comment_dic[评论对象] = {}
            comment_dic[comment_obj] = collections.OrderedDict()
        else:
            # 如果是回复的评论,则需要在 comment_dic 中找到其回复的评论
            tree_search(comment_dic, comment_obj)
    return comment_dic

comment_list = [
    (1, ', None),
    (2, ', None),
    (3, ', None),
    (9, ', 5),
    (4, ', 2),
    (5, ', 1),
    (6, ', 4),
    (7, ', 2),
    (8, ', 4),
]

def comment(request):
    comment_dict = build_tree(comment_list)

    return render(request, 'comment.html', {'comment_dict': comment_dict})

Views Code

from django.db import models

# Create your models here.

class SendMsg(models.Model):

    nid = models.AutoField(primary_key=True)
    code = models.CharField(max_length=6)
    email = models.CharField(max_length=32, db_index=True)
    times = models.IntegerField(default=0)
    ctime = models.DateTimeField()

class UserInfo(models.Model):
    nid = models.AutoField(primary_key=True)
    username = models.CharField(max_length=32, unique=True)
    password = models.CharField(max_length=32)
    email = models.CharField(max_length=32, unique=True)
    ctime = models.DateTimeField()

class NewsType(models.Model):
    nid = models.AutoField(primary_key=True)

    caption = models.CharField(max_length=32)

class News(models.Model):
    nid = models.AutoField(primary_key=True)
    user_info = models.ForeignKey('UserInfo')
    news_type = models.ForeignKey('NewsType')
    title = models.CharField(max_length=32, db_index=True)
    url = models.CharField(max_length=128)
    content = models.CharField(max_length=50)
    favor_count = models.IntegerField(default=0)
    comment_count = models.IntegerField(default=0)
    ctime = models.DateTimeField()

class Favor(models.Model):

    nid = models.AutoField(primary_key=True)

    user_info = models.ForeignKey('UserInfo')
    news = models.ForeignKey('News')

    ctime = models.DateTimeField()

    class Meta:
        unique_together = (("user_info", "news"),)

class Comment(models.Model):
    nid = models.AutoField(primary_key=True)

    user_info = models.ForeignKey('UserInfo')
    news = models.ForeignKey('News')

    up = models.IntegerField(default=0)
    down = models.IntegerField(default=0)
    ctime = models.DateTimeField()

    device = models.CharField(max_length=16)
    content = models.CharField(max_length=150)

    reply_id = models.ForeignKey('Comment', related_name='b', null=True, blank=True)

Models Code

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import template
from django.utils.safestring import mark_safe

register = template.Library()

TEMP1 = """
<div class='content' style='margin-left:%s;'>
    <span>%s</span>
"""

def generate_comment_html(sub_comment_dic, margin_left_val):
    html = '<div class="comment">'
    for k, v_dic in sub_comment_dic.items():
        html += TEMP1 % (margin_left_val, k[1])
        if v_dic:
            html += generate_comment_html(v_dic, margin_left_val)
        html += "</div>"
    html += "</div>"
    return html

@register.simple_tag
def tree(comment_dic):
    html = '<div class="comment">'
    for k, v in comment_dic.items():
        html += TEMP1 % (0, k[1])
        html += generate_comment_html(v, 30)
        html += "</div>"
    html += '</div>'

    return mark_safe(html)

templatetags xx.py

{% load xx %}

{% tree comment_dict %}

comment html code

Tornado框架简介

Tornado 是 FriendFeed 使用的可扩展的非阻塞式 web 服务器及其相关工具的开源版本。这个 Web 框架看起来有些像web.py 或者 Google 的 webapp,不过为了能有效利用非阻塞式服务器环境,这个 Web 框架还包含了一些相关的有用工具 和优化。

Tornado 和现在的主流 Web 服务器框架(包括大多数 Python 的框架)有着明显的区别:它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接,这意味着对于实时 Web 服务来说,Tornado 是一个理想的 Web 框架。我们开发这个 Web 服务器的主要目的就是为了处理 FriendFeed 的实时功能 ——在 FriendFeed 的应用里每一个活动用户都会保持着一个服务器连接。(关于如何扩容 服务器,以处理数以千计的客户端的连接的问题,请参阅 C10K problem。)

安装:

pip3 install tornado

简单应用

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

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

application = tornado.web.Application([
    (r"/index", MainHandler),
])

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

执行过程:

  • 第一步:执行脚本,监听 8888 端口
  • 第二步:浏览器客户端访问 /index  -->  http://127.0.0.1:8888/index
  • 第三步:服务器接受请求,并交由对应的类处理该请求
  • 第四步:类接受到请求之后,根据请求方式(post / get / delete ...)的不同调用并执行相应的方法
  • 第五步:方法返回值的字符串内容发送浏览器

参考url:http://www.cnblogs.com/wupeiqi/articles/5702910.html