当前位置:首页 > 正文

Django_自定义存储上传文件的文件名_django post save

更新时间:2025-02-16 16:59 阅读量:91
Django实现自定义文件名存储文件
使文件名看起来统一
避免收到中文文件导致传输、存储等问题
相同的文件也需要使用不同的文件名

思路:
生成14位随机字母加数字、后10位采用时间戳.从而实现相同文件不同文件名

1.view版:
在view接收到文件名之后进行重命名,不修改Django默认的文件存储逻辑.从而实现需求
2.upload_to版
参考链接:https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.FileField.upload_to
官方原文:
upload_to may also be a callable, such as a function. This will be called to obtain the upload path, including the filename. 
upload_to也可以是可调用的,例如函数.这将被调用以获得上载路径,包括文件名.
3.自定义存储系统:
暂时没那个必要:只是单纯的修改个文件名而已
4.forms版(20210206补充):
使用clean方法对文件格式验证并修改文件名

第三段:具体实现:

views版:

涉及views.py 、utils.py(自定义)

views.py:

class UploadIdentImageView(APIView):
def get(self, request, *args, **kwargs):
    return Response({"msg":"ident", "status_code": True})

def post(self, request, *args, **kwargs):
    # from somewhere import handle_uploaded_file
    file_name = request.FILES.get("file", None)
    if not file_name:
        return Response({"msg": "ident", "status_code": False})

    from test_app.utils import custom_file_name
    file_name.name = custom_file_name(file_name)

    models_object = models.IdCardImage(image_path=file_name)
    models_object.save()
    print(models_object)
    return Response({"msg":"ident", "status_code": True})

test_app\utils.py

def random_str():
import random
import time

num_set = [chr(i) for i in range(48, 58)]
char_set = [chr(i) for i in range(97, 123)]
total_set = num_set + char_set
bits = 14
value_set = "".join(random.sample(total_set, bits))
return value_set + str(int(time.time()))

def custom_file_name(file_name):
file_type = str(file_name).split(".")[-1]
new_file_name = random_str().upper()

return ".".join([new_file_name,file_type])

upload_to版:

涉及models.py.test_app\utils.py沿用上面内容

models.py

def user_directory_path(upload_to):
def wrapper(instance, filename):
    import datetime
    import os
    from mini_programe.utils import custom_file_name

    filename = custom_file_name(filename)

    dirname = datetime.datetime.now().strftime(upload_to)
    new_upload_to = os.path.join(dirname,filename)
    return new_upload_to
return wrapper


class IdCardImage(models.Model):
f_id = models.ForeignKey(Users, on_delete=models.SET_NULL,null=True,verbose_name="用户",related_name="user_id_card_img")
# image_path = models.FileField(upload_to='media/id_card_img/%Y/%m/')
image_path = models.FileField(upload_to=user_directory_path('media/id_card_img/%Y/%m/'))


forms.py

class IdCardImageForm(forms.ModelForm):
class Meta:
    model = models.IdCardImage
    fields = "__all__"

def clean_image_path(self):   #clean_字段名
    file = self.cleaned_data["image_path"]
    ext = file.name.split(".")[-1].lower()
    
    if ext != "png":
        raise forms.ValidationError("仅允许上传png文件")
    new_file_name = random.randint(111111111,9999999999)
    file.name = "%d.png"%new_file_name
    
    return file

class IdCardImage(models.Model):
f_id = models.ForeignKey(Users, on_delete=models.SET_NULL,null=True,verbose_name="用户",related_name="user_id_card_img")
image_path = models.FileField(upload_to='media/id_card_img/%Y/%m/')

views.py

class UploadIdentImageView(TemplateView):
def get(self,....)
    ....
def post(self,request,*args,**kwargs):
    check_form = forms.IdCardImageForm(request.POST,request.FILES)
    if not check_form.is_valid():
        return JsonResponse({'message': check_form.errors, "code": 400})
    instance = check_form.save()
    return JsonResponse({'message': instance.name + ",保存成功","code":200})

upload.html

function getCookie(name) {
let cookieValue = null;
if (document.cookie  document.cookie !== '') {
    const cookies = document.cookie.split(';');
    for (let i = 0; i < cookies.length; i++) {
        const cookie = cookies[i].trim();
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) === (name + '=')) {
            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
            break;
        }
    }
}
return cookieValue;
}

function upload_pdf() {
const csrftoken = getCookie('csrftoken');

var form = new FormData();
form.append("f_id", $("#f_id").val());
form.append("image_path", $("#image_path")[0].files[0]);
$.ajax({
    headers: {'X-CSRFToken': csrftoken},
    url: "{% url 'add_data' %}",
    type: "POST",
    data: form,
    
    processData: false,
    contentType: false,
    cache: false,
    
    success: function (result) {
        if (result.code === 200) {
            alert_message(JSON.stringify(result.message));
                } else {
                    console.log("success", result);
                    alert_message(JSON.stringify(result.message));
                }
            },
            fail: function (result) {
                console.log("fail",);
                alert_message(result.info);
            },
            error: function (result) {
                alert_message(result.status + ": " + result.statusText);
            }
        });

    }

第四段:最终效果:图片:

Django_自定义存储上传文件的文件名

个人更倾向于方案二或方案四,理由是:views.py文件中的处理函数的处理逻辑应该看起来简单一些.例如采用方案二整理后的view.py看起来像这样:

class UploadIdentImageView(APIView):
def get(self, request, *args, **kwargs):
    return Response({"msg":"ident", "status_code": True})

def post(self, request, *args, **kwargs):
    file_name = request.FILES.get("file", None)
    if not file_name:
        return Response({"msg": "ident", "status_code": False})

    models_object = models.IdCardImage(image_path=file_name)
    models_object.save()
    return Response({"msg":"ident", "status_code": True})

以上就是皇拓小常识小编为大家整理的Django_自定义存储上传文件的文件名相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!