八、Django2.1 搭建多用户的博客网站——头像上传

5字数 1510阅读 1325

目录:Django 2.1 从零开始搭建博客网站系列

服务器环境搭建(选学)

小试牛刀——简单的博客网站

庖丁解牛——多用户的博客网站之用户模块

庖丁解牛——多用户的博客网站之文章模块

华丽转身——多用户的博客网站之扩展功能

项目源码下载:https://github.com/jt1024/lehehe

正文:

在完善个人详细信息的时候,右侧我们那预留了一个地方,暂时用“picture”占位,本节我们将在这里展示用户的头像。

1、使用静态文件作为头像

新增资源文件 ./static/images/avatar.png
在 ./templates/account/myself.html 中用以下代码代替 <p>picture</p>

{% load staticfiles %}
            <div style="margin-right:100px">
                <img name="user_face" src="{% static 'images/avatar.png' %}" class="img-circle" width="270px" id="my_photo">
            </div>
            <div style="margin-right:100px">
                <button class="btn btn-primary btn-lg" id="upload_image" onclick="upload_image_layer()">upload my photo</button>
            </div>

访问 http://127.0.0.1:8000/account/my-information/ 页面如图

静态头像.png

2、头像上传

2.1 下载插件并整合到项目

下载 ImgCrop 文件包

复制 ImgCrop/css/style.css 到本项目的 static/css 并更名为 imagecrop.css ,然后修改一下样式:

.container {
    width: 400px;
    margin: 0 auto 0 0;
    position: relative;
    font-family: 微软雅黑;
    font-size: 12px;
}

复制 ImgCrop/jquery-1.11.1.min.js 到本项目的 ./static/js
复制 ImgCrop/js/cropbox-min.js 到本项目的 ./static/js

2.2 简单地使用插件模拟头像上传

在 ./account/views.py 中增加 my_image 方法

def my_image(request):
    return render(request, 'account/imagecrop.html')

创建 ./templates/account/imagecrop.html 并把 ImgCrop/index.html的代码复制过来,最后结合项目修改代码如下:

{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/imagecrop.css' %}">
<div class="container">
    <div class="imageBox">
        <div class="thumbBox"></div>
        <div class="spinner" style="display: none"></div>
    </div>

    <div class="action">
        <!-- <input type="file" id="file" style=" width: 200px">-->
        <div class="new-contentarea tc">
            <a href="javascript:void(0)" class="upload-img">
                <label for="upload-file">请先选择图片...</label>
            </a>
            <input type="file" class="" name="upload-file" id="upload-file"/>
        </div>
        <input type="button" id="btnCrop" class="Btnsty_peyton" value="OK"><!--注意这行代码,添加了 id="btnCrop" -->
        <input type="button" id="btnZoomIn" class="Btnsty_peyton" value="+">
        <input type="button" id="btnZoomOut" class="Btnsty_peyton" value="-">
    </div>
    <div class="cropped"></div>
</div>

<script src="{% static 'js/jquery-1.11.1.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/cropbox-min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/csrf.js' %}"></script>
<script type="text/javascript">
    $(window).load(function() {
        var options =
        {
            thumbBox: '.thumbBox',
            spinner: '.spinner',
            imgSrc: ''
        }
        var cropper = $('.imageBox').cropbox(options);
        var img="";
        $('#upload-file').on('change', function(){
            var reader = new FileReader();
            reader.onload = function(e) {
                options.imgSrc = e.target.result;
                cropper = $('.imageBox').cropbox(options);
                getImg();
            }
            reader.readAsDataURL(this.files[0]);
            this.files = [];
        })
        $('#btnCrop').on('click', function(){
            alert("图片上传喽");
        })

        function getImg(){
            img = cropper.getDataURL();
            $('.cropped').html('');
            $('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:180px; margin-top:4px; border-radius:180px; box-shadow:0px 0px 12px #7E7E7E;"> <p>180px*180px</p>');
            $('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:128px; margin-top:4px; border-radius:128px; box-shadow:0px 0px 12px #7E7E7E;"> <p>128px*128px</p>');
            $('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:64px; margin-top:4px; border-radius:64px; box-shadow:0px 0px 12px #7E7E7E;" > <p>64px*64px</p>');
        }

        $(".imageBox").on("mouseup",function(){ getImg();});
        $('#btnZoomIn').on('click', function(){ cropper.zoomIn();})
        $('#btnZoomOut').on('click', function(){cropper.zoomOut(); })
    });
</script>

在 ./account/urls.py 增加以下代码

path('my-image/', views.my_image, name="my_image"),

运行Django,访问 http://127.0.0.1:8000/account/my-image/

测试头像插件1.png

点击“OK”,弹出一个弹窗,此时只是模拟效果,头像并没有真正上传


测试头像插件2.png

2.3 实现真正的头像上传功能

修改 ./account/models.py 中的数据模型 UserInfo,增加如下字段

photo = models.ImageField(blank=True)

执行如下代码迁移数据库

python manage.py make migrations
python manage.py migrate

此时数据库中新增数据表account_userinfo


account_userinfo.png

在 ./account/forms.py 中修改 UserInfoForm

class UserInfoForm(forms.ModelForm):
    class Meta:
        model = UserInfo
        fields = ("school", "company", "profession", "address", "aboutme", "photo")

修改 ./account/views.py 中的 my_image 方法

@login_required(login_url='/account/login')
def my_image(request):
    if request.method == 'POST':
        img = request.POST['img']
        userinfo = UserInfo.objects.get(user=request.user.id)
        userinfo.photo = img
        userinfo.save()
        return HttpResponse("1")
    else:
        return render(request, 'account/imagecrop.html', )

把 csrf.js 文件(附下载链接)复制到 ./static/js 里
修改 ./templates/account/imagecrop.html 中的 $('#btnCrop')方法
把这几行代码

$('#btnCrop').on('click', function(){
            alert("图片上传喽");
        })

替换为下面的代码

$('#btnCrop').on('click', function(){
            //alert("图片上传喽");
            $.ajax({
                url: '{% url "account:my_image" %}',
                type: 'POST',
                data: {"img": img},
                success: function(e){
                    location.href= "{% url 'account:my_information' %}"
                },
            })
        })

修改 ./templates/account/myself.html 中的头像显示代码为下面的代码

{% load staticfiles %}
            <div style="margin-right:100px">
                <!--img name="user_face" src="{% static 'images/newton.jpg' %}" class="img-circle" width="270px" id="my_photo"-->
                {% if userinfo.photo %}
                <img src="{{ userinfo.photo | striptags }}" class="img-circle" id="my_photo" name="user_face">
                {% else %}
                <img name="user_face" src="{% static 'images/avatar.png' %}" class="img-circle" id="my_photo">
                {% endif %}
            </div>

运行Django,访问 http://127.0.0.1:8000/account/my-image/ 最后点击 “OK”,头像替换成功:

头像替换成功.png

查看数据表中的 photo 字段,已存入


头像已存入数据库.png

3、优化头像上传

比较好的体验是,点击“upload my photo”按钮,弹出上传头像的弹窗,在弹窗中进行上传操作。layui 插件可以很好的满足我们的需求。

通过本链接下载layui插件或者官网http://www.layui.com下载,下载后把 layer.js 文件和 skin 目录都复制到本项目的 ./static/js 目录里。

修改 ./templates/account/myself.html,在{% endblock %} 之前增加以下代码

<script type="text/javascript" src='{% static "js/jquery.js" %}'></script>
<script type="text/javascript" src="{% static 'js/layer.js'%}"></script>
<script>
function upload_image_layer(){
    layer.open({
        title:"上传头像",
        area: ['650px', '600px'],
        type:2,
        content:"{% url 'account:my_image' %}",
    });
}
</script>

修改 ./templates/account/imagecrop.html 中的 $('#btnCrop')方法如下

$('#btnCrop').on('click', function(){
            //alert("图片上传喽");
            $.ajax({
                url: '{% url "account:my_image" %}',
                type: 'POST',
                data: {"img": img},
                success: function(e){
                    //location.href= "{% url 'account:my_information' %}"
                    if(e == "1"){
                        parent.location.reload();
                    } else {
                        alert("sorry, you are not lucky. the picutre can't been uploaded.")
                    }
                },
            })
        })

运行Django,访问 http://127.0.0.1:8000/account/my-information/ 点击“upload my photo”按钮,效果如下图

优化后的头像上传弹窗.png

选择图片,最后点击 “OK”,头像替换成功:


头像替换成功.png

4、超级管理员管理个人详细信息

我们用户的详细信息能不能在超级管理员后台的界面中管理呢?当然能!

在 ./account/admin.py 增加以下代码

from .models import UserInfo

class UserInfoAdmin(admin.ModelAdmin):
    list_display = ("user", 'school', 'company', 'profession', 'address', 'aboutme', 'photo')
    list_filter = ("school", "company", "profession")


admin.site.register(UserInfo, UserInfoAdmin)

访问http://127.0.0.1:8000/admin/登录后可见页面如下图:

超级管理员后台.png

点击 User infos 栏目会打开如下页面:


User infos.png

5、遗留问题

访问 http://127.0.0.1:8000/admin/ 登录admin(密码:helloworld)时,会提示密码错误,但是我没有修改过admin的密码,所以导致超级用户无法登陆。不知道是什么原因导致的。

在无法找回超级管理员的密码时,可以新建一个超级管理员的账号,然后再进入后台修改admin的密码。

新建一个超级管理员的账号的命令:

python manage.py createsuperuser

推荐阅读更多精彩内容