图片上传
2023年8月3日大约 2 分钟
图片上传
static 和 media 都是存放文件的地方,但是又有区别,以下是两个文件夹的区别和用法
static
static 是静态文件,主要存的是 CSS, JavaScript, 网站 logo 等不变的文件。
配置 settings.py
STATIC_URL = '/static/' # 静态文件别名(相对路径) 和 绝对路径
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'app01/static'),
]
# STATIC_ROOT 配置部署的时候才用
在项目中将模板层用到的静态文件都放入该文件夹中
media
media 主要用来保存用户上传的文件,例如图片等
配置 settings.py
MEDIA_URL = "/media/" # 媒体文件别名(相对路径) 和 绝对路径
MEDIA_ROOT = [
os.path.join(BASE_DIR, 'app01/media')
]
如果需要使用Django服务展示图片,则在项目的主路由中对使用 static静态服务器展示图片信息。
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
from django01 import settings
urlpatterns = [
...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# 对外展示图片的地址信息
图片上传示例
模型
定义包含图片字段的模型类
class Goods(models.Model):
name = models.CharField(max_length=20, verbose_name="名称")
price = models.DecimalField(max_digits=7, decimal_places=2, verbose_name="单价")
nums = models.IntegerField(verbose_name="数量")
img = models.ImageField(upload_to='img', verbose_name="图片")
class Meta:
db_table = "tb_goods"
verbose_name = "商品"
verbose_name_plural = verbose_name
def __str__(self):
return self.name
模板
添加页面
<form action="{% url 'goods:create' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
名称:<input type="text" name="name"> <br>
价格:<input type="text" name="price"> <br>
数量:<input type="text" name="nums"> <br>
图片:<input type="file" name="img"> <br>
<input type="submit" value="提交">
</form>
展示页面
<table>
{% for good in goods %}
<tr>
<td>{{ good.id }}</td>
<td>{{ good.name }}</td>
<td>{{ good.price }}</td>
<td>{{ good.nums }}</td>
<td>
<img src="/media/{{ good.img }}" alt="" style="width: 300px;height: 200px">
</td>
</tr>
{% endfor %}
</table>
视图
添加商品
from django.shortcuts import render, redirect
from django.views import View
from app01.models import Goods
# Create your views here.
class GoodsCreateView(View):
def get(self, request):
return render(request, 'goods.html')
def post(self, request):
name = request.POST.get('name')
price = request.POST.get('price')
nums = request.POST.get('nums')
img = request.FILES.get('img')
if not all([name, price, nums, img]):
return redirect('goods:create')
try:
Goods.objects.create(name=name, price=price, nums=nums, img=img)
except Exception as e:
print(e)
return redirect('goods:create')
return redirect('goods:index')
展示商品
class IndexView(View):
def get(self, request):
goods = Goods.objects.all()
return render(request, 'index.html', context={'goods': goods})
路由
在子应用正常配置路由
from django.urls import path
from app01.views import *
app_name = 'goods'
urlpatterns = [
path('goods/', GoodsCreateView.as_view(), name='create'),
path('', IndexView.as_view(), name='index'),
]
在主路由中包含子路由即可。
from django.conf.urls.static import static
from django.urls import path, include
from django01 import settings
urlpatterns = [
path('', include("goods.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)