我的网站搭建(第46天) 在线头像

  • 发布时间:2017年2月27日 18:08
  • 作者:杨仕航
* 该文是基于Python2.7开发的,最新Python3.x和Django2.x视频教程可以前往 >> Django2.0视频教程

我的网站搭建の头像功能,文章回顾:

我的网站搭建(第44天) 添加头像字段

我的网站搭建(第45天) 上传头像


前面在开发上传头像功能的时候,留了位置写在线头像的功能。

有了在线头像功能,可以快速直接设置头像。效果如下,我选了16个萌萌的头像 ^_^

20170227/20170227171608867.jpg


这16张图片存放在固定的静态目录中。使用Bootstrap的模态框弹窗显示。

由于该部分的头像不需要经常修改,为了节省服务器开支,将html代码直接写死。

<div class="modal fade avatar-online-modal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">&times;</span>
            </button>
            <h4 class="modal-title">捏脸 - 歪脖 (点一个试试)</h4>
        </div>

        <div class="modal-body" style="text-align: center;">
            <div class="avatar_online_img">
            <div>
                <img src="/static/media/avatar/online/n_1.jpg" />
                <img src="/static/media/avatar/online/n_2.jpg" />
                <img src="/static/media/avatar/online/n_3.jpg" />
                <img src="/static/media/avatar/online/n_4.jpg" />
            </div>
            <div>
                <img src="/static/media/avatar/online/n_5.jpg" />
                <img src="/static/media/avatar/online/n_6.jpg" />
                <img src="/static/media/avatar/online/n_7.jpg" />
                <img src="/static/media/avatar/online/n_8.jpg" />
            </div>
            <div>
                <img src="/static/media/avatar/online/w_1.jpg" />
                <img src="/static/media/avatar/online/w_2.jpg" />
                <img src="/static/media/avatar/online/w_3.jpg" />
                <img src="/static/media/avatar/online/w_4.jpg" />
            </div>
            <div>
                <img src="/static/media/avatar/online/w_5.jpg" />
                <img src="/static/media/avatar/online/w_6.jpg" />
                <img src="/static/media/avatar/online/w_7.jpg" />
                <img src="/static/media/avatar/online/w_8.jpg" />
            </div>
            </div>
        </div>
    </div>
  </div>
</div>

再简单设置样式:

/*在线图片*/
.avatar_online_img img{ 
    width: 96px; 
    margin: 0 0 5px 5px; 
    border: 1px #ccc solid; 
    border-radius: 4px; 
    cursor: pointer;
}
.avatar_online_img img:hover{ 
    border-color: #bbb; 
    box-shadow: 0 0 5px rgba(0,0,0,.25);
}

/*不同屏幕改变头像大小*/
@media (max-width:485px){
  .avatar_online_img img{ width: 72px;}
}
@media (max-width:388px){
  .avatar_online_img img{ width: 48px;}
}


这个模态框我还没绑定按钮打开,因为“在线图片”那个按钮我还需要写其他代码。可以在“在线图片”按钮写代码弹出。

这里还需要思考一个问题。我们在后台如何分辨用户使用本地图片还是在线图片上传头像


这个需要前端提交数据跟后台说清楚。

用户选择了在线图片,也就需要提交在线图片的地址给后台。

在form表单中添加隐藏字段。

<input type="hidden" id="avatar_online" name="avatar_online">

和前面文章我的网站搭建(第45天) 上传头像创建的form中一共有6个字段。

<!--图片裁剪参数-->
<input type="hidden" id="avatar_x" name="avatar_x">
<input type="hidden" id="avatar_y" name="avatar_y">
<input type="hidden" id="avatar_width" name="avatar_width">
<input type="hidden" id="avatar_height" name="avatar_height">

<!--在线图片地址-->
<input type="hidden" id="avatar_online" name="avatar_online">

<!--本地图片文件-->
<input type="file" class="avatar-input" id="avatar-input" name="avatar_file" style="display:none">

那么,我们可以在后台处理提交数据的时候,判断avatar_file字段是否提交文件。

若没有提交,再判断avatar_online是否有填写在线图片的地址。

通过该方法可以分辨清楚用户采用哪种方式上传头像。


为了不让“本地图片”和“在线图片”两个字段相互干扰。

我们可以选择本地图片之后,清除“在线图片”相关字段的数据;

在选择在线图片之后,清除“本地图片”相关字段的数据。js代码如下:

//选择本地图片
function choose_local_img(){
    var URL = window.URL || window.webkitURL;
    if(URL){
        var files = this.files;
        if (files && files.length){
            var file = files[0];
            if (/^image\/\w+$/.test(file.type)) {
              var blobURL = URL.createObjectURL(file);
              image.cropper('reset').cropper('replace', blobURL);
              $('.avatar_crop .disabled').removeClass('disabled');
              normal_tip('本地图片:可调整到最佳状态再上传');

              $("#avatar_online").val(''); //去掉在线图片数据
            } else {
              error_tip('请选择一张图片');
            }
        }
    }
}
$("#avatar-input").bind('change', choose_local_img); //绑定事件

//在线图片
$('#online-img').click(function(){
    normal_tip('在线图片:捏脸和歪脖系列头像,萌不');
    $(".avatar-online-modal").modal('show');
});
//选择在线图片
$(".avatar_online_img img").click(function(){
    $(".avatar-online-modal").modal('hide');

    //设置在线图片
    var path = $(this).attr('src');
    image.cropper('replace', path);
    $("#avatar_online").val(path);
    $('.avatar_crop .disabled').removeClass('disabled');

    //移除本地图片选择
    var file = $("#avatar-input") 
    file.after(file.clone().val("")); 
    file.remove(); 
    $("#avatar-input").bind('change', choose_local_img); //绑定事件
});

这里为了兼容清除file标签的文件选择信息。先移除标签,再添加进来。

但再添加进来的时候,需要重新绑定一次。

(相关上传头像代码,看我的网站搭建(第45天) 上传头像


Django后台的代码,也修改如下:

@check_login
def user_avatar_upload(request):
    """上传头像"""
    data = {}

    ##获取临时路径,用于保存图片
    temp_folder = os.path.join(settings.BASE_DIR, 'static', 'temp')
    if not os.path.isdir(temp_folder):
        os.makedirs(temp_folder)

    temp_filename = uuid.uuid1().hex #纯文件名,没有后缀名
    temp_path = os.path.join(temp_folder, temp_filename)

    #判断图片来源(本地上传 or 在线图片)
    if request.FILES.has_key('avatar_file'):
        #本地上传
        avatar_file = request.FILES['avatar_file']
        temp_path = temp_path + os.path.splitext(avatar_file.name)[-1] #加后缀名

        #保存上传的文件
        with open(temp_path, 'wb') as f:
            for chunk in avatar_file.chunks():
                f.write(chunk)
    else:
        avatar_online = request.POST.get('avatar_online', '')
        print('-'*30+'1')
        print(avatar_online)

        #在线图片有效性验证
        avatar_is_valid = False
        if len(avatar_online)>0:
            filename = os.path.split(avatar_online)[-1]
            avatar_online_path = os.path.join(settings.BASE_DIR, 'static/media/avatar/online', filename)
            #判断文件是否存在
            avatar_is_valid = os.path.isfile(avatar_online_path)

        if not avatar_is_valid:
            data['success'] = False
            return HttpResponse(json.dumps(data), content_type="application/json")

        #复制图片到临时路径
        temp_path = temp_path + os.path.splitext(avatar_online_path)[-1]
        shutil.copy(avatar_online_path, temp_path)

    #裁剪图片
    top = int(float(request.POST['avatar_y']))
    buttom = top + int(float(request.POST['avatar_height']))
    left = int(float(request.POST['avatar_x']))
    right = left + int(float(request.POST['avatar_width']))

    #python2.7 pillow
    from PIL import Image
    im = Image.open(temp_path)
    #裁剪图片
    crop_im = im.convert("RGBA").crop((left, top, right, buttom)).resize((64, 64), Image.ANTIALIAS)

    #设置背景颜色为白色
    out = Image.new('RGBA', crop_im.size, (255,255,255))
    out.paste(crop_im, (0, 0, 64, 64), crop_im)

    #保存图片
    out.save(temp_path)

    #保存记录
    avatar = request.user.set_avatar_url(temp_path)
    os.remove(temp_path)
    
    data['success'] = True
    data['avatar_url'] = avatar.avatar.url
    return HttpResponse(json.dumps(data), content_type="application/json")

大部分代码和我的网站搭建(第45天) 上传头像一样,前面部分加入在线图片判断和处理即可。


这里还有一个地方需要注意的。我将头像获取和设置代码使用了get方法获取头像记录。

在开发的过程中,发生一些错误。导致出现多条记录,get方法在获取多条记录会出错,改成filter即可解决问题。

avatar = User_Avatar.objects.filter(user=self.id)[0]

(本篇文章和前面两篇文章一脉相承,看不明白的话,先看看前面两篇文章。)

上一篇:我的网站搭建(第47天) 修改评论列表的样式

下一篇:我的网站搭建(第45天) 上传头像

相关专题: Django评论库开发   

评论列表

智慧如你,不想发表一下意见吗?

新的评论

清空