Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)

第二周学习记录

接上周的django继续学习,这周的目标是能够利用python搭建图片处理的后台,继续根据官方文档完成mysite搭建并自己搭建证件照换底色后台

一、django学习

(一)应用模板的视图

在自己定义的app中的views.py里定义不同的响应函数,并在urls指定调用view.function的方式,例如:

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('/vote/', views.vote, name='vote'),
]

不同级别的访问会对应不同的path,从而调用不同的函数的HTTP响应,从而显示到页面上,<>中的匹配为正则匹配

结果显示为:

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第1张图片

一个真正可以利用的视图必须能够从数据库中读取记录,可以使用模板等功能,官方文档给了以下实例,polls/views.py的代码如下:

from django.http import HttpResponse

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

从models下导入Question,然后再polls下建立templates目录,然后再新建一个polls目录,目录下放index.html,此为模板文件,官方文档指出,由于APP_DIRS设置为TRUE,所以可以直接利用模板加载器,使用路径为polls/index.html

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

接下来使用模板

from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

loader获取到index.html模板,并导入问题列表,生成超链接,每一个连接都连接到对应的具体的问题

然而官方提到一个更快捷的函数render(),该函数通过from django.shortcuts import render导入

from django.shortcuts import render

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

直接将模板作为参数放在render里执行

(二)抛出404错误

from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

直接在http包中导入404,然后通过异常检测的方式,如果没有获取到对应的问题号,就返回404页面

get_object_or_404()可以直接判断而不用使用异常判断,返回根据情况而定

(三)使用模板系统

去除模板中的硬编码URL

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}a>li>

改写为

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}a>li>

这样在改变polls时,只用改变一处即可

(四)多应用

为URL名称添加命名空间

也就是说在应用很多的情况下,同样是detail视图,URL应该对应哪一个应用

官方文档指出:在根 URLconf 中添加命名空间,例如:

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('/', views.detail, name='detail'),
    path('/results/', views.results, name='results'),
    path('/vote/', views.vote, name='vote'),
]

加上app_name=polls设置命名空间

这样一来,index.html中的url'detail'应改为url'polls:detail'

(五)表单

使用官方给我们的表单模板,更改vote()的具体实现

polls/templates/polls/detail.html

<h1>{{ question.question_text }}h1>

{% if error_message %}<p><strong>{{ error_message }}strong>p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}label><br>
{% endfor %}
<input type="submit" value="Vote">
form>

polls/views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse

from .models import Choice, Question
# ...
def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
      //选中的项目的投票数加1
        selected_choice.votes += 1
        //保存
        selected_choice.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        //转到结果界面
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

这样以后,在跳转到detail界面时,可以将所有choice以单选框的形式打印在界面上,每个单选框的 name"choice" 。这意味着,当有人选择一个单选按钮并提交表单提交时,它将发送一个 POST 数据 choice=# ,其中# 为选择的 Choice 的 ID。

POST完成后返回页面重定向,定向到result界面,reverse()调用返回'/polls/3/results/'

接下来编写results.py视图

def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

然后在static文件夹下写入result.html

<h1>{{ question.question_text }}</h1>

<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

还是以这种模板的方法写入

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第2张图片

点击投票,会跳转到results页面

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第3张图片

(六)通用视图

由以上例子可以看出代码存在冗余,django官方文档支出了通用视图

在应用下的urls.py中更改path()中的参数,以polls为例,在polls/urls.py

 path('', views.IndexView.as_view(), name='index'),
 path('/', views.DetailView.as_view(), name='detail'),
 path('/results/', views.ResultsView.as_view(), name='results'),

路径字符串中匹配模式的名称已经由 改为

改良视图,打开polls/views.py

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]


class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'


class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'

原来的视图可以对应删除

二、网上demo结构学习

在学习django过程中也找到了一些网上有人做出来的网站demo,找到了一个图书管理网站,github地址:https://github.com/hyyc554/mydjango

项目的md文件列出了一个django框架示意图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第4张图片

项目目录

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第5张图片

然后就是连接mysql

先下载mysql,我用的是Apache的XAMPP管理工具,默认端口号为3306,终端输入mysql -uroot -p回车,然后输入密码进入mysql界面,进入mysql数据库管理工具,我用的是NavicatMysql,连接数据库,创建数据库名等操作,数据库名和连接密码需要依据settings.py文件的配置

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第6张图片

我没有设置数据库连接密码,如果有设置这里可以添加,然后创建orm3数据库,在项目的终端运行python manage.py migrate将会执行数据库迁移,这个时候你就会看到数据库中设置了表,但是全为空值,可以在里面插入数值

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第7张图片

然后在网页中打开localhost:8000/app01/books

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第8张图片

这里我手动添加了一个书籍,一开始应该为空,可以添加书籍,但是注意数据库中必须有作者和出版社的日期,才能成功添加书籍

至此,这个django实例就运行成功,内部的项目结构逻辑其实类似官方文档所讲述的那样

三、上手证件照换底色后台django

和伙伴一起搜集了几天资料,终于在14号开始后台django搭建,他给了我几篇参考文章,我觉得十分有帮助

https://blog.csdn.net/qq_41775298/article/details/105301801?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase

https://blog.csdn.net/wf021017/article/details/105417547/?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-3&spm=1001.2101.3001.4242

https://blog.csdn.net/qq_29391809/article/details/104002696

(一)从小程序获取用户上传的图片

关于小程序的相关知识可以参考我的第一周学习记录博客https://blog.csdn.net/weixin_43951163/article/details/107928486,然后也可以参考我伙伴的博客https://blog.csdn.net/qq_44933075/article/details/107735724

根据三篇文章的前两篇先进行后台获取用户上传图片

首先搭建django框架,pycharm新建一个项目,在项目终端输入python manage.py startapp 'app名称'然后在新建app下新建urls.py

更改settings.py的ALLOWED_HOSTS = ['*'],然后添加app到序列中

我的项目目录如下

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第9张图片

我创建的app名为pc_change,然后我把前端的css文件放在静态文件夹下,前端index代码放在templates模板下

添加cqc_01下的urls.py的代码

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('app/', include('pc_change.urls'))
]

然后更改pc_change下的urls.py和views.py

urls.py

from django.urls import path

from . import views


urlpatterns = [
    path('get_image/', views.get_image),
]

views.py

from django.shortcuts import render
import pc_change.method
import os
from django.http import HttpResponse,HttpResponseRedirect
# Create your views here.

def get_image(request):
    if request.method == 'POST':
        image = request.FILES['image']
        print(image)
        open_id = request.POST.get('openid')
        //这里是项目的绝对路径
        basedir = '/Users/shall/PycharmProjects/cqc_01'
        //我这里把图片放在静态文件资源下的images文件夹下,之后进行数据库开发会将其放在数据库中
        path = basedir + '/static/images/'
        if not os.path.exists(path + open_id + '.jpg'):
            with open(path + open_id + '.jpg', 'wb') as f:
                f.write(image.read())
                f.close()
                return HttpResponse('上传成功')
    else:
        return HttpResponse('上传失败')

然后对于小程序的wx.upload编写

wx.uploadFile({ // 调用接口上传文件
  				//url测试为本主机测试,可以根据自己的app更改
          url: 'http://localhost:8000/app/get_image/',
          // url: 'http://www.baidu.com',
          filePath: filePath,
          name: 'image',
          method: 'POST',
          
          formData: {
            openid: that.data.openID
          },
          success: res => { // 调用成功时的回调函数
            console.log('[上传文件] 成功:', res)
            wx.showToast({
              title: '上传成功',
              icon:'success'
              
            })  
            
          },
          fail: e => { // 调用失败时的回调函数
            console.error('[上传文件] 失败:', e);
            wx.showToast({ // 显示消息提示框
              icon: 'none',
              title: '上传失败',
            })
          },
          complete: () => { // 调用完成时的回调函数
            wx.hideLoading() // 隐藏加载提示框
          }
        })
      },
      fail: e => { // 调用失败时的回调函数
        console.error(e)
      }
    })
  }},

这个时候要注意将微信小程序界面中的详情中的如下打钩

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第10张图片

然后上传图片,这个时候还会报错,console会显示app not found

找了一下解决方案,需要将settings.py中的一行注释掉

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第11张图片

csrf这一行注释,然后就可以成功上传图片了,图片名为filepath+.jpg,存在images文件目录下

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第12张图片

至此,本地后台的文件接收就完成了

(二)连接MySQL数据库

同第一章的记录,打开mysql服务,然后在database中添加信息,然后不要忘记在_init_.py中加入

import pymysql
pymysql.install_as_MySQLdb()

然后就可以正常连接了

(三)数据库存储图片

首先创建model,model的创建要根据你拟定的表的格式,我创建的如下:

from django.db import models

# Create your models here.


class Before_Pic(models.Model):
    name = models.CharField(max_length=200)
    image = models.ImageField(upload_to='logo')

    def __str__(self):
        return self.name

在settings的数据库设置下加几条语句

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

然后要执行迁移:

python manage.py makemigrations

python manage.py migrate 

随后要注意一点要在mysql中运行

SET @@global.sql_mode='';

在这里插入图片描述

这样避免了后面对于数据类型的报错

于是再次来到小程序点击上传,可以发现media目录下出现了logo文件下,文件夹下是我们的图片

Django实现证件照换底色小程序后台图片接收和处理(第二周学习记录)_第13张图片

然而这里图片显得很长,但是我先没有解决

mysql数据库中新增了一个数据

在这里插入图片描述

这样,用户上传的图片就成功存储在mysql中,但这与我想的不太一样,存入的图片是项目下的相对路径,也就是说图片仍然存储在项目文件中,数据库只是存储一个处理和调用的路径

这两天有事离开家,过几天继续更新

你可能感兴趣的:(小程序云开发,django,python,django,小程序)