python-django-07-demo

一、实例

1.1、生成并渲染图片方法

from django.shortcuts import render, HttpResponse
from PIL import Image
from io import StringIO, BytesIO
import random

# 使用 from PIL import Image, 新建一个图片
# 生成一张图片,第一个是模式:RGB, 第二个参数是图片大小,第三个参数是图片颜色
Image.new('RGB', (,), color="颜色") 或者 color=(0,0,0)

def vaild_random(count):
    return tuple([random.randint(0,233) for i in range(count)])

def valid_check(request):
    """  1、前台渲染图片
      <img src="{% url 'valid_check' %}" alt="" height="30" width="240">
    with open("static/image-20210220102205414.png", "rb") as f:
        data = f.read()
    return HttpResponse(data)
    """
    # pip install pillow
    # new(mode, size, color=0)

    """ 局限性、每次生成img都会在本地保存为一个文件,增加了IO对性能的压力
    img = Image.new("RGB", (320, 33), vaild_random(3))
    with open("static/img.png", "wb") as f:		# 保存图片
        img.save(f, "png")
    with open("static/img.png", "rb") as f:		# 获取图片数据
        data = f.read()
    return HttpResponse(data)
    """

    # 第三种,推荐使用这种
    img = Image.new("RGB", (320, 33), vaild_random(3))
    io = BytesIO()
    img.save(io, "png")     # 直接通过二进制形式写到内存中
    data = io.getvalue()    # 获取到数据给它返回
    return HttpResponse(data)
  1. 方式一
def valid_check(request):
    # 1、前台渲染图片
      # <img src="{% url 'valid_check' %}" alt="" height="30" width="240">
    with open("static/image-20210220102205414.png", "rb") as f:
        data = f.read()
    return HttpResponse(data)

在这里插入图片描述

  1. 方式二、三
def valid_check(request):
    """ 局限性、每次生成img都会在本地保存为一个文件,增加了IO对性能的压力
    img = Image.new("RGB", (320, 33), vaild_random(3))
    with open("static/img.png", "wb") as f:		# 保存图片
        img.save(f, "png")
    with open("static/img.png", "rb") as f:		# 获取图片数据
        data = f.read()
    return HttpResponse(data)
    """
    
    # 第三种,推荐使用这种
    img = Image.new("RGB", (320, 33), vaild_random(3))
    io = BytesIO()
    img.save(io, "png")     # 直接通过二进制形式写到内存中
    data = io.getvalue()    # 获取到数据给它返回
    return HttpResponse(data)

在这里插入图片描述

1.2、在画板中生成随机字符串

def vaild_random(count):
    return tuple([random.randint(0,233) for i in range(count)])

def get_vaild_num(count):
    f = StringIO()
    for i in range(count):
        ran_num = random.choice([random.randint(65, 90), random.randint(97, 122), random.randint(0, 9)])
        get_num = chr(ran_num) if ran_num > 9 else ran_num
        f.write(str(get_num))
    return f.getvalue()


def valid_check(request):
    """
    	先画个图(img), 打开个画板(ImageDraw),放个图片(ImageDraw.Draw)
    	画板中操作, 写点字 整个字体(draw.text)
    """
    
    # 1、先画一个图
    img = Image.new("RGB", (320, 33), vaild_random(3))
	# 2、获取一支画笔
    draw = ImageDraw.Draw(img, "RGB")
    # 3、添加字符集
    font = ImageFont.truetype("static/font/fzht.TTF", size=20)
    # xy: x横轴 y竖轴,text:文本内容,fill=None: 字体颜色 ,font=None:要用哪种字体
    vaild_num = get_vaild_num(6)
    # 4、在画笔中添加随机字符串,fill是字符的颜色 
    draw.text((120,0), vaild_num, fill=vaild_random(3), font=font)
	# 5、在内存中保存图片并将它直接返回
    io = BytesIO()
    img.save(io, "png")     # 直接通过二进制形式写到内存中
    data = io.getvalue()    # 获取到数据给它返回
    return HttpResponse(data)

1.2.1、添加点线

    width= 270
    height = 40
    for i in range(10):
        x1 = random.randint(0,width)
        x2 = random.randint(0,width)
        y1 = random.randint(0,height)
        y2 = random.randint(0,height)
        draw.line((x1,x2,y1,y2), fill=vaild_random(3))

    for i in range(50):
        draw.point([random.randint(0,width), random.randint(0,height)], fill=vaild_random(3))
        x= random.randint(0,width)
        y= random.randint(0,height)
        draw.arc((x,y, x+4, y+4),0 ,90,fill=vaild_random(3))

1.2.2、验证码更新

<div class="col-md-6 vaild_check">
    <img id="vaild_img" src="{% url 'valid_check' %}" alt="">
</div>

$(".vaild_check").on("click", function () {
    $.ajax({
        url: "{% url 'valid_check' %}",
        type: "get",
        success: function (data) {
        # 先删除
            $(".vaild_check").children("#vaild_img").remove()
        # 然后在添加一个html标签
            $(".vaild_check").html(
                '<img id="vaild_img" src="{% url "valid_check" %}">'
            )
        }
    })
})

1.2.3、时区配置

TIME_ZONE = 'Asia/Shanghai'		# 时区使用 UTF8
USE_TZ = Fase					# 不使用UTC时间,改用本地配置的时间

1.3、前端头像预览

#img_avatar {
	width: 50px;
	height: 50px;
}

#avatar { display: none;}

<div class="form-group">
    <label for="avatar">头像
        <img src="/static/image/default.png" alt="" id="img_avatar">
    </label>
    <input type="file" name="avatar" id="avatar">
</div>

<script>
    $("#avatar").on("change", function () {
        var get_pre_avatar = $("#avatar")[0].files[0]
        // js前端文件阅读器
        var filereader = new FileReader()
        // 将图片对象传到文件阅读器中
        filereader.readAsDataURL(get_pre_avatar)
        // 打开文件filereader.result
        // 直接将文件对象渲染到img标签上是不可行的,需要加载完成才能进行操作 .onload
        filereader.onload = function() {
            $("#img_avatar").attr("src", filereader.result)
        }
    })
</script>

在这里插入图片描述

1.4、头像上传处理

关键字: request.FILES, FileField(upload_to="upload/")serializeArray

  1. 前端-html
# 具体前端页面: https://blog.csdn.net/u010304195/article/details/113944437

$(".btn").on("click", function () {
    var forms = new FormData()
    {# 对象.serialize() #}
    var forms_serialize = $(".get_froms").serializeArray();
    // console.log(forms_serialize) 获取的类型为: [{}, {}, {}, {}, {}]

    //jquery的循环,传参数,第一个参数是要循环的对象,第二个参数是一个匿名对象
    $.each(forms_serialize, function (key,items) {
        forms.append(items.name, items.value)
    })
    forms.append("avatar", $("#avatar")[0].files[0])

    $.ajax({
        url: "{% url 'register' %}",
        type: "post",
        processData: false,
        contentType: false,
        data: forms,
        success: function (data) {
            console.log(data)
            $("#error").html(data["msg"]);
        }
    })
})
  1. 后端
class Register(View):
    def get(self, request):
        return render(request, "bbs/register.html")

    def post(self, request):
        username = request.POST.get("username")
        pwd = request.POST.get("pwd")
        email = request.POST.get("email")
        phone = request.POST.get("phone")
        msg = {"code": 1000, "msg": ""}
		# 取到图片,模型是 FileField 上传会直接处理,目录也会一并创建
        avatar = request.FILES.get("avatar")
        # 如果不用FileField模型 就需要使用下面这种方式处理
        // with open("upload/{}11".format(avatar.name), "wb") as f:
        //    # from django.core.files.base import File
        //    for line in avatar.chunks():
        //       f.write(line)

        if all([username, pwd, email, phone]):
            if not UserInfo.objects.filter(username=username).first():
                user = UserInfo.objects.create_user(username=username, password=pwd, email=email, phone=phone, avatar=avatar)
                msg["msg"] = "注册成功"
            else:
                msg["msg"] = "注册失败,用户已存在"
        else:
            msg["msg"] = "选项不能为空"
        return JsonResponse(msg)
  1. 模型
from django.contrib.auth.models import AbstractUser

# Create your models here.

class UserInfo(AbstractUser):
    id = models.AutoField(primary_key=True)
    phone = models.CharField(max_length=14, null=True)
    avatar = models.FileField(upload_to="upload/", default="static/img/default.png")
    blog = models.OneToOneField(to="Blog", to_field="id", on_delete=models.CASCADE, null=True)

1.4.1、media上传处理

from django.views.static import serve

    # serve  图片处理,需要传递有名参数 path
    # 第一个是有名分组,正则表达式,
    # 第二参数, 函数的内存地址
    # 第三个参数: 字典,它会以关键字参数传递
    re_path('media/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}),

# 当使用FileField使用上传时,可以将图片上传到media中,通过配置settings.py可直接定义
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

# 模型
    avatar = models.FileField(upload_to="upload/", default="static/img/default.png")
# 当指定上传目录为upload时,如果配置了media_url,那么真实上传的目录是  
	# 项目 media/upload/file.name 
    
    

urls.py文件
# avatar = models.FileField(upload_to='avatar/', default='/static/avatar/default.png')
# 如果不配置保存就是 avatar/文件.xx ,  配置之后就是 media/avatar/文件.xx
# 数据库中保存的格式是 avatar/Tulips.jpg
MEDIA_URL = "/media/"

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

1.5、分页器

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
from django.core.paginator import Paginator

def paginators(object, page):
    paginator = Paginator(object, 5)
    # 用django自带的检验处理
    try:
        page = paginator.validate_number(page)
    except Exception:
        page = 1

    # 这里获取的是文章
    object = paginator.page(page)

    # 这里处理下边页码数
    count_paginator = paginator.num_pages
    """
        - 判断是否大于11,如果小于则有多少返回多少
        - 判断 获取页码-5是否小于等于1, 如果是则返回 1到11页
        - 判断 获取页码+5是否大于总页面, 如果是 则总的页面左边减10,右边加1直到最后一行
        - 其它情况则 获取的页码 左右各减5
    """
    if count_paginator > 11:
        if page - 5 <= 1:
            per_list = range(1, 11)
        elif page + 5 > count_paginator:
            per_list = range(count_paginator - 10, count_paginator + 1)
        else:
            per_list = range(page - 5, page + 5)
    else:
        per_list = paginator.page_range
    return object, per_list, page


# 使用
def index(request, page=1):
    # 查询出所有的数据
    articles = Article.objects.all()
    # 获取分页后的所有数据, 文章, 页码, 当前页
    articles, per_list, page = paginators(articles, page)
    return render(request, 'bbs/index.html', locals())

1.6、多URL处理

以点赞为例

  • URL
re_path("(?P<digg>digg_up|digg_down)/", views.digg, name="digg"),
  • html
function clicks(obj, urls) {
    obj.on("click", function () {
        console.log(obj)
        $.ajax({
            url: urls,
            type: "post",
            data: {
                "archive_id": "{{ articles.id }}",
                "user_id": "{{ user.userinfo.pk }}",
                "csrfmiddlewaretoken": '{{ csrf_token }}'
            },
            success: function (data) {
                $("#digg_tips").html(data["msg"])
            }
        })
        setTimeout(function () {
            $("#digg_tips").html("")
        }, 3000)
    })

}

# 获取点击事件,然后传一个url
clicks($(".diggit"), "/digg_up/")
clicks($(".buryit"), "/digg_down/")
  • views
from django.http import JsonResponse

def digg(request, digg):
    if request.method == "POST":
        result = {"status": 100, "msg": None}
        archive_id = request.POST.get("archive_id")
        user_id = request.POST.get("user_id")
        article = Article.objects.filter(pk=archive_id).first()
        auther = UserInfo.objects.filter(pk=user_id).first()

        upanddown = Upanddown.objects.filter(article=article, user_id=auther)
        if upanddown:
            result["msg"] = "您已经点过了"
        else:
            if digg == "digg_up":
                Upanddown.objects.create(article=article, user_id=auther, is_check=True)
                Article.objects.filter(pk=archive_id).update(up_num=F("up_num") + 1)
                ret = "点赞成功"
            elif digg == "digg_down":
                Upanddown.objects.create(article=article, user_id=auther, is_check=False)
                Article.objects.filter(pk=archive_id).update(down_num=F("down_num") + 1)
                ret = "反对成功"
        return JsonResponse(result)
  • 模型

    class Upanddown(models.Model):
        id = models.AutoField(primary_key=True)
        article = models.ForeignKey(to="Article", to_field="id", on_delete=models.CASCADE)
        user_id = models.ForeignKey(to="UserInfo", to_field="id", on_delete=models.CASCADE)
        is_check = models.BooleanField()
    
        class Meta:
            unique_together = (("user_id", "article", "is_check"),)
    

1.7、django发送邮件

可直接参考

二、前台

2.1、es6 拼接语法

if (data["status"] == 1000) {
    // 提交完后台之后,将内容填充到评论页中
    var xx = `
        <li class="list-group-item">
            <p class="small"> <span>${data["user"]}: </span> </p>
            <p class="list-group-item-success p_content">${contents}</p>
        </li>
    `
    # ul中定义的类
    $(".p_comm_append").append(xx)
}

2.1.1、获取内容切割文件

var contents = $("#contents").val()
if (pid) {
    var index = contents.indexOf("\n") + 1;
//    拿到某个值的起始位置indexOf,取到指定值的索引值的后面所有值
    contents = contents.slice(index);
}

2.2、kindedit

上传文件, 编辑器, 获取内容

# 先引用js
<script src="/static/kindeditor/kindeditor-all-min.js"></script>
<script charset="utf-8" src="/static/kindeditor/lang/zh-CN.js"></script>

2.2.1、上传文件

  • 前台
<script>
    KindEditor.ready(function (K) {
    {#editor.sync();#}
        window.editor = K.create('#editor_id', {
            uploadJson: '/article_upload/',  // 后端的url
            extraFileUploadParams : {
                // csrf处理
                "csrfmiddlewaretoken": '{{ csrf_token }}',
            },
            allowFileManager: true,
            resizeType: 1,		// 不允许拖拉
        });
    });
</script>
  • 后台
def article_upload(request):
    if request.method == "POST":
        abs_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))

        response = {"error": 1, "url": os.path.join(abs_path, "static", "image", "default.png")}
        imgFile = request.FILES.get("imgFile")

        path = os.path.join(abs_path, "media", "article")
        if not os.path.isdir(path): os.mkdir(path)
        filename = os.path.join(path, imgFile.name)
        with open(filename, "wb") as f:
            for line in imgFile.chunks():
                f.write(line)
            response["error"] = 0
            response["url"] = "/media/article/{}".format(imgFile.name)
        return JsonResponse(response)

2.2.2、标签处理

可参考:https://www.cnblogs.com/linhaifeng/articles/7783586.html

# 三步曲
	一、安装 pip install beautifulsoup4
    二、引用 from bs4 import BeautifulSoup
    三、使用  xx = BeautifulSoup()

# 后台使用, 第一个参数是内容,第二个是要使用的解析器
    content_bs = BeautifulSoup(content,"html.parser")

    for bs in content_bs.find_all():
        # 找着sciprt标签,给它删除
        if bs.name == "script": bs.decompose()

FAQ

Django开发“ ‘X-Frame-Options’ to ‘deny’“报错处理

# settings.py中添加 原因分析:https://blog.csdn.net/ora_dy/article/details/104984482
	X_FRAME_OPTIONS = 'SAMEORIGIN'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值