静态文件配置

在settings.py中最底下有一个叫做static的文件夹,主要用来加载一些模板中用到的资源,提供给全局使用
这个静态文件主要用来配置CSS,HTML,图片,字体文件等 

STATIC_URL
= '/static/'
STATICFILES_DIRS
= [
    os.path.join(BASE_DIR,'static')
]

之后在模板中,首先加载静态文件,之后调用静态,就不用写绝对全路径了

模板中的声明
{% load static%} `或 {% load staticfiles %}`<br />在引用资源的时候使用<br />`{% static 'xxx' %}   xxx 就是相对于staticfiles_dirs`一个位置

静态文件和模板文件的区别

先建静态文件夹
记得settings添加配置:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

新建url: 

    url('^index/', views.index, name='index'),

在Templates中新建html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h2>这是一个首页</h2>
<h4>{{ username }}</h4>
</body>
</html>

views:

def index(request):
    # 模板html支持模板语言,可以挖坑填坑
    return render(request, 'index.html')

我们可以访问模板html文件

我们先前在html中进行了挖坑,只是没有填坑,而在访问时服务器自动优化了挖坑的代码

接着在static文件夹中新建html文件夹,在其中新建index.html文件

static文件夹用于存放静态资源,我们可以直接通过网址访问其中的静态资源
我们可以上传图片,静态页面。
**

可以观察到静态html中不支持模板语言是静态的
而在模板中的HTML是动态的,会帮我们处理渲染

以后将静态资源放入static中,效率会比放在模板中的效率高,因为MTV中对模板会渲染处理。

文件上传

原理类似于文件复制,一边读取文件,一边写入文件,而文件上传是从网络上读取文件。

文件数据存储在request.FILES属性中
form表单上传文件需要添加enctype='multipart/form-data'

请求方式

文件上传必须使用POST请求方式

存储

  在static文件夹下创建uploadefiles用与存储接收上传的文件
  在settings中配置,MEDIA_ROOT=os.path.join(BASE_DIR,r'static/uploadefiles')
 
在开发中通常是存储的时候,我们要存储到关联用户的表中

实践:文件上传

url:

  url('^uploadfile', views.upload_files, name='upload_files'),

模板:upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
<form action="{% url 'app:upload_files' %} " method='post' enctype="multipart/form-data">
    {# 因为上传文件,一个文件可能很大,所以在传输过程中会将文件分块,打包,然后加密传输 #}
    {% csrf_token %}  {# post提交需要csrf_token #}
    <span>文件</span><input type="file" name="icon">
    <br>
    <input type="submit" name="上传">
</form>
</body>
</html>

views:

def upload_files(request):
    # 判断请求方式
    if request.method == 'GET': # 如果是get,就返回一个渲染页面
        return render(request, 'upload.html')
    elif request.method == 'POST':  # 用来接收客户端上传的数据
        icon = request.FILES.get('icon')
        # 打印上传的文件
        print(icon)
        return HttpResponse('上传成功')

我们先打印出来刚刚客户端上传的文件,后续再实现保存文件的功能。
然后进行测试:


可以看到成功打印上传文件

接着我们实现保存功能
views改为:

def upload_files(request):
    # 判断请求方式
    if request.method == 'GET': # 如果是get,就返回一个渲染页面
        return render(request, 'upload.html')
    elif request.method == 'POST':  # 用来接收客户端上传的数据
        icon = request.FILES.get('icon')
        print(type(icon))
        # 新建一个文件,然后将上传的文件写入数据,写入形式是二进制文件
        with open(r'static/img/icon.jpg', 'wb') as save_file:
            for part in icon.chunks():  # 将传过来的文件一行一行的读取
                save_file.write(part)   # 将传过来的文件一行一行的写入
                save_file.flush()
        return HttpResponse('上传成功')

下面来尝试:

选择一张照片然后点击提交

我们也可以在文件夹中找到图片

这样我们就成功上传了图片,这种方法是“万金油”,是原生写法,因为不光在DJango中可以,在flask中也这一这样写,但是这样写不够简洁。

实践:文件上传Pro
我们可以在models添加模型:

class UerModel(models.Model):
    u_name = models.CharField(max_length=16)
    # upload_to代表将文件传到哪个地方,我们的路径写的是相对路径,相对于MTDIA_ROOT 媒体根目录
    u_icon = models.ImageField(upload_to='icons')

接着我们在static文件夹中创建upload文件夹(也可以在其他地方进行创建,只需要能够访问到即可)
另外我们还要在settings.py中注册路径:

MEDIA_ROOT = os.path.join(BASE_DIR, 'static/upload')

我们在model中用到了ImageField来保存图像,但是辨别文件是否为图像,处理图像,我们需要专门处理图像的库Pillow。
安装Pillow(目前观察到这个库已经内置了,在安装的时候提示已安装)

新建url:这个url做为我们上传图片

   url('^imagefield/', views.image_field, name='image_field'),

views:

def image_field(request):
    if request.method == 'GET':
        return render(request, 'image_field.html')
    elif request.method == 'POST':
        # 获取用户名
        username = request.POST.get('username')
        # 获取图片
        icon = request.FILES.get('icon')
        print(icon)
        print(username)
        user = UserModel()
        user.u_name = username
        user.u_icon = icon
        user.save()
        return HttpResponse('上传成功%d' % user.id)

注意获取username是用POST.get,
而获取图片文件使用FILES.get来获取,假如获取形式不对应会造成获取值为None


也可以看到成功打印出了上传文件名以及用户名。
而且这种方法,上传文件名相同时,会在重复图片后面自动追加一串混淆字符串。

接着我们新建url用来获取用户头像:

url('^mine/', views.mine, name='mine'),

views:

def mine(request):
    # 获取username
    username = request.GET.get('username')
    user = UserModel.objects.get(u_name=username)
    # 获取图片保存的路径
    print('/static/upload/'+user.u_icon.url)
    data = {
        'username': username,
        'icon_url': '/static/upload/'+user.u_icon.url
    }
    return render(request, 'mine.html', context=data)

新建mine.html用来当作个人中心的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>mine</title>
</head>
<body>
<h3>{{ username }}</h3>
<img src="{{ icon_url }}" alt="{{ username }}">
</body>
</html>

可以看到访问username=2时:

linux有个bug当一个文件夹里面的直接子文件数大于65535时,文件夹再也打不开。

有时候只有接触到大量数据,真实的生产环境时,才能遇到更深的问题。

为了将上传的文件规划存放起来,并且控制每一个文件夹中的文件数量。
我们可以在upload_to=''中调整:
(记得修改完迁移文件)

class UserModel(models.Model):
    u_name = models.CharField(max_length=16)
    # upload_to后面填路径,表示上传的图片存放文件夹,我们的路径写的是相对路径,相对于MTDIA_ROOT 媒体根目录
    u_icon = models.ImageField(upload_to='%Y/icons')

%Y/  代表了按年划分文件夹

我们还可以进一步使用%Y%m%d/icons一直细化到天来自动创建文件夹用于存放

最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏