文档章节

Django 图片上传upload_to路径指定失效的问题记录

Asktao
 Asktao
发布于 01/22 18:40
字数 1401
阅读 23
收藏 0

初始方法一:

疑虑:model使用upload_to自定义路径方法失效,指定路径也失效。最后以Views中指定MEDIA_URL和MEDIA_ROOT做拼接,并且自行判断并建立文件夹,手动chunk保存。不完美的解决。

model:    看avatar字段的upload_to

import uuid
from django.db import models
from django.contrib.auth.models import AbstractUser


class SysUser(AbstractUser):
    """
    用户扩展表,用于替换auth的user类,并添加头像和昵称。
    """
    uid = models.BigAutoField(primary_key=True)
    nickname = models.CharField(max_length=32, verbose_name="昵称")
    # 使用 models.ImageField 需要安装 Pillow ,cmd命令:pip install Pillow
    avatar = models.ImageField(verbose_name="头像", upload_to="avatar11")

    class Meta:
        # 数据库显示的表名
        db_table = "sys_user"

form:

from django.forms import Form
from django.forms import widgets
from django.forms import fields

class EditUserForm(Form):
    """..."""
    e_avatar = fields.ImageField(
        required=False,
        widget=widgets.FileInput(attrs={"hidden": "hidden"})
    )
    """..."""

Views:

def upload_user_avatar(request):
    """用户上传头像操作"""
    if request.method == "POST":
        user_id = request.user.uid        # 只是当前登录用户
        ret = {'state': True, 'error': None, 'data': None}
        # user_id = request.POST.get("uid", None)
        avatar = request.FILES.get("avatar", None)

        # 如果文件夹不存在,则建立
        dir_path = os.path.join(MEDIA_ROOT, "users", "{}_{}".format(request.user.uid, request.user.username), "avatar")
        if not os.path.exists(os.path.join(dir_path)):
            os.makedirs(os.path.join(dir_path))
        avatar_path = os.path.join(dir_path, avatar.name)
        try:
            with open(avatar_path, 'wb+') as img:
                for chunk in avatar.chunks():
                    img.write(chunk)
                print("文件接收成功")
            img_url = os.path.join("users", "{}_{}".format(request.user.uid, request.user.username), "avatar")
            SysUser.objects.filter(uid=user_id).update(avatar=img_url)
            ret["data"] = "头像更新成功"
        except Exception as e:
            ret["state"] = False
            ret["data"] = "头像更新失败,请确认图片格式"
            print(e)
        return HttpResponse(json.dumps(ret))

html:

<div class="form-group text-center">
    <label>
        {# request.user.avatar  是读取实例的avatar字段,也就是不加MEDIA_URL前缀的 #}
        {# request.user.avatar.url  是读取实例的avatar字段了,并且添加MEDIA_URL作为前缀的 #}
        <img id="avatar-img" src="{{ request.user.avatar.url }}" width="200px" height="200px">
        {{ edit_user_form.e_avatar }}
    </label>
</div>

 

  • SysUser.objects.filter(uid=user_id).update(avatar=img_url)
  • 这句话执行结束后,只保存文件名,无法使用upload_to指定的路径。
  • 页面加载时,直接使用拼接后路径。

初始方法二:

TMD,一个保存方式的问题,竟然能啰啰嗦嗦这么久。以后以此方法操作。

model:不变

views:

def upload_user_avatar(request):
    """用户上传头像操作"""
    if request.method == "POST":
        user_id = request.user.uid        # 只是当前登录用户
        ret = {'state': True, 'error': None, 'data': None}
        avatar = request.FILES.get("avatar", None)

        try:
            user_obj = SysUser.objects.filter(uid=user_id).first()
            user_obj.avatar = avatar
            user_obj.save()
            ret["data"] = "头像更新成功"
        except Exception as e:
            ret["state"] = False
            ret["data"] = "头像更新失败,请确认图片格式"
            print(e)
        return HttpResponse(json.dumps(ret))
  • user_obj.save()
  • 使用这种保存方式的好处:
  1. 会自动保存文件路径到数据库
  2. 会自动保存文件到指定路径
  3. 必要时会自动创建目录。

目前最终方法:

model:

import uuid
import os
from django.db import models
from django.contrib.auth.models import AbstractUser
"""
python-cmd : makemigrations
python-cmd : migrate
"""


def user_directory_path(instance, filename):
    """用户上传文件时的自定义操作"""
    ext = filename.split('.')[-1]                           # 获取上传的文件名的后缀
    filename = '{0}.{1}'.format(uuid.uuid4().hex[:8], ext)  # 修改文件名,谨防重名。(文档说重名后,会自动增加后缀)
    sub_folder = 'avatar'
    # 日后如果对上传文件的类型进行归档时可以COPY这个做参考。
    # if ext.lower() in ["jpg", "png", "gif", "ico"]:
    #    sub_folder = "avatar"
    # if ext.lower() in ["pdf", "docx"]:
    #     sub_folder = "document"
    return os.path.join("users", "%s-%s" % (instance.user.uid, instance.user.username), sub_folder, filename)


class SysUser(AbstractUser):
    """
    用户扩展表,用于替换auth的user类,并添加头像和昵称。
    """
    uid = models.BigAutoField(primary_key=True)
    nickname = models.CharField(max_length=32, verbose_name="昵称")
    # 使用 models.ImageField 需要安装 Pillow ,cmd命令:pip install Pillow
    avatar = models.ImageField(verbose_name="头像", upload_to=user_directory_path)

    class Meta:
        # 数据库显示的表名
        db_table = "sys_user"

form:

from django.forms import Form
from django.forms import widgets
from django.forms import fields

class EditUserForm(Form):
    """..."""
    e_avatar = fields.ImageField(
        required=False,
        widget=widgets.FileInput(attrs={"hidden": "hidden"})
    )
    """页面操作该元素时,使用的ajax方式,所以仅对此项进行操作。未使用EditUserForm做验证等操作。"""
    """..."""

views:

def upload_user_avatar(request):
    """用户上传头像操作"""
    if request.method == "POST":
        user_id = request.user.uid        # 只是当前登录用户
        ret = {'state': True, 'error': None, 'data': None}
        # user_id = request.POST.get("uid", None)   # 如果以后有需求修改其他人的信息时,再从页面获取。
        avatar = request.FILES.get("avatar", None)

        try:
            user_obj = SysUser.objects.filter(uid=user_id).first()
            user_obj.avatar = avatar
            user_obj.save()
            ret["data"] = "头像更新成功"
        except Exception as e:
            ret["state"] = False
            ret["data"] = "头像更新失败,请确认图片格式"
            print(e)
        return HttpResponse(json.dumps(ret))

html:

<div class="form-group text-center">
    <label>
        {# request.user.avatar  是读取实例的avatar字段,也就是不加MEDIA_URL前缀的 #}
        {# request.user.avatar.url  是读取实例的avatar字段了,并且添加MEDIA_URL作为前缀的 #}
        <img id="avatar-img" src="{{ request.user.avatar.url }}" width="200px" height="200px">
        {{ edit_user_form.e_avatar }}
    </label>
</div>

JS:

// 上传文件按钮(label里的图片)点击事件
$('#id_e_avatar').on('change',function () {

	// 文件上传之前在本地加载预览。
	{
		// 获取用户最后一次选择的图片
		var choose_file=$(this)[0].files[0];
		// 创建一个新的FileReader对象,用来读取文件信息
		var reader=new FileReader();
		// 读取用户上传的图片的路径
		reader.readAsDataURL(choose_file);
		// 读取完毕之后,将图片的src属性修改成用户上传的图片的本地路径
		reader.onload=function () {
			 $("#avatar-img").attr("src",reader.result)
		}
	}

	// 使用FormData格式,将文件上传至服务器
	formdata = new FormData();
	//formdata.append('uid',$('#id_e_id').val());
	formdata.append("avatar",$("#id_e_avatar")[0].files[0]);

	$.ajax({
		type: "POST",
		url: "/account/upload_user_avatar",
		data:formdata,
		processData:false,	//上传文件时需要如此设置1
		contentType:false,	//上传文件时需要如此设置2
		success:function (data) {
			data = JSON.parse(data);
			console.log(data);
			alert(data.data)	// 偷懒了,哈哈
         }
	});
});

media_url映射:

from django.urls import path, re_path, include
from django.views.generic.base import RedirectView
from django.views.static import serve    # 映射media_root路径,可以通过浏览器访问的操作-1
from django.contrib.auth.decorators import login_required
from WXH_DJANGOWEB import settings
from utils.required import required

urlpatterns = [
    path('account/', include("account.urls")),
    path('blog/', include("blog.urls")),
    re_path(r"^media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT, })
    # 映射media_url,可以通过浏览器访问的操作-2
]

至此,记录完毕。回家吃饭。坑爹的保存方式…… 愿同志们绕坑而行,用不遇坑。

© 著作权归作者所有

Asktao
粉丝 27
博文 100
码字总数 116095
作品 0
丰台
程序员
私信 提问
django ImageField保存上传的图片

1、在settings.py文件加配置: MEDIA_ROOT = ‘/home/myname/files/’MEDIA_URL = ‘media/’ 2、在models里的定义: class MyModel(models.Model): name = models.CharField(max_length=15......

wenguonideshou
2018/06/26
0
0
Django settings.py 的media路径设置

在一个 models 中使用 FileField 或 ImageField 需要以下步骤: 1. 在你的 settings 文件中, 定义一个完整路径给MEDIAROOT 以便让 Django在此处保存上传文件. (出于性能考虑,这些文件并不保存...

岭南六少
2011/08/18
563
0
Django模板静态文件处理和媒体文件处理

1.Django 对css静态文件的处理 我们先来看Django 对css静态文件是怎么处理的,一起来实现一下: 第一步:首先需要在settings文件中指定静态文件的存储路径,可以使用Django模板引擎语法提示,...

彩色泡泡糖
05/24
6
0
Django使用Uploadify组件实现图片上传

Uploadify组件上传文件很酷,可以实现文件进度上传,而且可以批量上传各种文件。好处还很多,具体详情登到官网看看文档了解吧。在同类组件中,Uploadify做的也很出色。打算在Django中用它,两...

岭南六少
2011/08/08
2.5K
4
Django-Upload-Avatar

jango-Upload-Avatar#头像上传APP A django app for upload avatars IE6 Compatible #兼容 IE6 You can find a showcase at youtube or youku # 在优酷上可以找到演示地址 Install#安装方法 ......

宁宁123韩
2013/04/16
933
0

没有更多内容

加载失败,请刷新页面

加载更多

3_数组

3_数组

行者终成事
今天
7
0
经典系统设计面试题解析:如何设计TinyURL(二)

原文链接:https://www.educative.io/courses/grokking-the-system-design-interview/m2ygV4E81AR 编者注:本文以一道经典的系统设计面试题:《如何设计TinyURL》的参考答案和解析为例,帮助...

APEMESH
今天
7
0
使用logstash同步MySQL数据到ES

概述   在生成业务常有将MySQL数据同步到ES的需求,如果需要很高的定制化,往往需要开发同步程序用于处理数据。但没有特殊业务需求,官方提供的logstash就很有优势了。   在使用logstas...

zxiaofan666
今天
10
0
X-MSG-IM-分布式信令跟踪能力

经过一周多的鏖战, X-MSG-IM的分布式信令跟踪能力已基本具备, 特点是: 实时. 只有要RX/TX就会实时产生信令跟踪事件, 先入kafka, 再入influxdb待查. 同时提供实时sub/pub接口. 完备. 可以完整...

dev5
今天
7
0
OpenJDK之CyclicBarrier

OpenJDK8,本人看的是openJDK。以前就看过,只是经常忘记,所以记录下 图1 CyclicBarrier是Doug Lea在JDK1.5中引入的,作用就不详细描述了,主要有如下俩个方法使用: await()方法,如果当前线...

克虏伯
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部