添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
苦闷的围巾  ·  【Docker学习笔记 ...·  1 年前    · 
路过的茴香  ·  FastChat/vicuna ...·  1 年前    · 
重感情的苦瓜  ·  __m128 | Microsoft Learn·  1 年前    · 
乖乖的马克杯  ·  Xampp 命令行 操作 ...·  1 年前    · 

在工作碰到了需要快速搭建原型的事情,Django在后台数据管理这方面有完善的解决方案。

admin后台对 models.FileField 的上传文件解决方式是直接在数据库中储存原始数据,对于数据库大小和迁移等都很不便,更多的解决方案是通过oss解决储存问题,cdn访问的方式提高速度。 所以需要对 models.FileField 进行改造,使其自动上传到oss中并储存url地址。 找遍了网络只有一个对此的解决方案,但不完整(有其他方案的话在评论区告知一下)

使用环境:python 3.8.8 django 3.2.5

注:我使用的是腾讯云的oss,所以下面例子都以腾讯云为例,其他云端oss对应替换我标注的位置就可以

0、上传文件部分代码(隐私信息使用000000表示,自行替换)

from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
from urllib.parse import quote
from config.config import TENCENTCloud_secret_id, TENCENTCloud_secret_key
class UploadToTencent(object):
    def __init__(self):
        self.region = 'ap-beijing'  # 替换为用户的 Region
        self.scheme = 'https'  # 指定使用 http/https 协议来访问 COS,默认为 https,可不填
        self.config = CosConfig(Region=self.region,
                                SecretId=TENCENTCloud_secret_id,
                                SecretKey=TENCENTCloud_secret_key,
                                Scheme=self.scheme)
    def upload_to_tencentcloud(self, body='', key='', bucket='000000', default_dir=True):
        tencent_client = CosS3Client(self.config)
        if "000000" not in key and default_dir:
            key = "000000" + key
        if '/' in key:
            filename = key.split('/')[-1]
            file_dir = '/'.join(key.split('/')[:-1])+'/'
        else:
            filename = key
            file_dir = ''
        response = tencent_client.put_object(
            Bucket=bucket,
            Body=body,
            Key=key,
            EnableMD5=False
        save_filename = quote(filename, 'utf-8')
        print(file_dir, save_filename)
        end_url = "https://download.000000.com/%s%s" % (file_dir, save_filename)
        return end_url

1、自定义Widget

继承了forms.FileInput,对页面输入文件进行接收

# -*-*-*-*-*- encoding: utf-8 -*-*-*-*-
# @File    :   TencentWidget.py
# @Author :   stonepy
# -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
from django import forms
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.template import loader
from django.utils.safestring import mark_safe
from utils.tencentUploadFile import UploadToTencent
class TencentWidgets(forms.FileInput):
    template_name = 'tencent_input.html'   #
    def __init__(self, attrs=None, unique_list=None):
        :param attrs:
        :param unique_list: 唯一标识列表,除了id
        super(TencentWidgets, self).__init__(attrs)
        self.unique = unique_list
    def format_value(self, value):
        return value
    def value_from_datadict(self, data, files, name):
        file = files.get(name)  # type:InMemoryUploadedFile
        if not file:
            return
        file_data = b''.join(chunk for chunk in file.chunks())  # 取出二进制数据
        upload_cloud = UploadToTencent()
        url = upload_cloud.upload_to_tencentcloud(file_data, file.name)  # 在更换其他云时替换此位置的方法,方法返回为url字符串
        return url
    def render(self, name, value, attrs=None, renderer=None):  # 模板渲染部分
        context = self.get_context(name, value, attrs)
        template = loader.get_template(self.template_name).render(context)
        return mark_safe(template)

2、自定义Field

继承了models.URLField,用来实现URL的处理

from django import forms
from django.db import models
from customField.TencentWidget import TencentWidgets
class TencentField(models.URLField):
    def __init__(self, *args, **kwargs):
        self.app = kwargs.pop('app', '')
        self.table = kwargs.pop('table', '')
        self.unique_list = kwargs.pop('unique_list', '')
        super(TencentField, self).__init__(*args, **kwargs)
    def formfield(self, **kwargs):
        defaults = {
            'form_class': TencentFormField,
            'unique_list': self.unique_list
        defaults.update(kwargs)
        return super(TencentField, self).formfield(**defaults)
class TencentFormField(forms.fields.URLField):
    def __init__(self, unique_list=None, **kwargs):
        kwargs.update({'widget': TencentWidgets(unique_list=unique_list)})
        super(TencentFormField, self).__init__(**kwargs)

3、自定义template

此处为自我摸索部分,有疑问请指出 在不使用自定义模板时,进入会报错找不到模板 翻阅源文件后发现在/lib/python3.8/site-packages/django/forms/templates/django/forms/widgets/file.html,推测是读不到对应位置的file.html 于是自定义一个模板html,代码如下:(直接复制file.html的部分,处理掉一些不识别的问题)

<input type="{{ widget.type }}" name="{{ widget.name }}"{% if widget.value != None %} value="{{ widget.value }}"{% endif %}{% for name, value in widget.attrs.items %}{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %}>`
`已上传文件:{% if widget.value != None %}<a href="{{ widget.value }}">{{ widget.value }}</a>{% endif %}

最后一行为个人增加对已上传的文件显示支持,不知道之前的是什么问题无法进行显示,不需要的话可直接删除

4、使用自定义field

from customField.TencentField import TencentField
file_url = TencentField(max_length=255, default='', verbose_name='文件地址', blank=True)

5.1 代码结构

5.2 使用效果

数据库储存信息

参考文章地址:www.jianshu.com/p/0522aaae3…

分类:
后端
标签: