Django上传图片和显示图片

Django上传图片和显示图片

 在搭建网站时,难免需要上传图片,比如用户头像或者相册图片等等,这里简单记录一下过程。

上传和显示

新建一个工程

$ django-admin startproject django_upload_example

$ tree django_upload_example
django_upload_example
  ├── django_upload_example
  │       ├── __init__.py
  │       ├── settings.py
  │       ├── urls.py
  │       └── wsgi.py
  └── manage.py


$ cd django_upload_example

$ pwd
/home/user/django_upload_example

新建一个应用

$ python manage.py startapp users

注册应用

# django_upload_example/settings.py
...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users'
]
...

数据模型

# users/models.py
from django.db import models

# Create your models here.
class User(models.Model):
    name = models.CharField(max_length=50)
    # upload_to 指定上传文件位置
    # 这里指定存放在 img/ 目录下
    headimg = models.FileField(upload_to="img/")
    
    # 返回名称
    def __str__(self):
        return self.name
# django_upload_example/settings.py
...
# 指定上传文件目录
# replace() 将 "\\" 替换为 "/"
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace("\\", "/")
MEDIA_URL = '/media/'
...

数据库迁移

$ python manage.py makemigrations
Migrations for 'users':
  users/migrations/0001_initial.py
    - Create model User

$ python manage.py migrate 
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK
  Applying users.0001_initial... OK


url

# django_upload_example/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    # 使用 include() 将 users 应用的 urls 模块包含进来
    path('users/', include('users.urls'))
]
# users/urls.py
from django.urls import path
from . import views

app_name = 'users'
urlpatterns = [
    path('add/', views.add, name='add'),
]

forms

# users/forms.py
from django import forms

# 表单类用以生成表单
class AddForm(forms.Form):
    name = forms.CharField()
    headimg = forms.FileField()

视图函数

# users/views.py

from django.shortcuts import render
from .models import User
from .forms import AddForm

# Create your views here.
def add(request):
    # 判断是否为 post 方法提交 
    if request.method == "POST":
        af = AddForm(request.POST, request.FILES)
        # 判断表单值是否和法
        if af.is_valid():
            name = af.cleaned_data['name']
            headimg = af.cleaned_data['headimg']
            user = User(name=name, headimg=headimg)
            user.save()
            return render(request, 'users/index.html', context={"user":user}) 
    else:
        af = AddForm()
        return render(request, 'users/add.html', context={"af":af})

模板

# django_upload_example/settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

<!-- templates/users/add.html -->
<!doctype html>
<html>
<head>
    <title>Add</title>
    <meta charset="utf-8">
</head>
<body>
    <h1>Add!</h1>

    <form method="post" enctype="multipart/form-data" action="{% url 'users:add' %}">
        {% csrf_token %}
        {{ af.as_p }}
        <input type="submit" value="OK"/>
    </form>
</body>
</html>
<!-- templates/users/index.html -->
<!doctype html>
<html>
<head>
    <title>Detail</title>
    <meta charset="utf-8">
</head>
<body>
    <p>{{ user.name }}</p>
    <img width="50%" height="50%" src="/media/{{ user.headimg }}">
</body>
</html>

测试

$ python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).
July 24, 2018 - 07:28:55
Django version 2.0.4, using settings 'django_upload_example.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

登陆 127.0.0.1:8000/users/add/

image

填写表单之后点击确定,发现图片无法显示
image

# 查看目录发现 已经上传了
$ ls
db.sqlite3  django_upload_example  manage.py  media  templates  users

$ tree media
media
└── img
     └── 1.jpg

配置

# django_upload_example/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('users/', include('users.urls'))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
image

完成

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容