You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中实现商品图片上传:支持本地上传与URL输入

Django商品图片上传/URL输入功能解决方案

原代码核心问题

  1. HTML不允许嵌套<form>标签,你嵌套的子表单会导致提交行为异常,无法和商品信息一起保存
  2. 主表单未设置enctype="multipart/form-data",无法接收上传的文件
  3. 未显式定义图片URL输入字段,仅靠{{ form.as_p }}无法渲染出对应输入框
  4. 引入了PHP的upload.php,不符合Django的处理逻辑

步骤1:定义商品模型

先在models.py中创建包含图片字段的商品模型,同时支持本地上传和URL输入:

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

class Listing(models.Model):
    title = models.CharField(max_length=200)
    category = models.CharField(max_length=100)
    description = models.TextField()
    starting_price = models.DecimalField(max_digits=10, decimal_places=2)
    # 本地上传图片,存到media/listing_images目录下
    image = models.ImageField(upload_to='listing_images/', blank=True, null=True)
    # 图片URL字段,可选
    image_url = models.URLField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

配置媒体文件

在settings.py中添加媒体文件路径配置:

# settings.py
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'

在项目根路由urls.py中添加媒体文件访问路由:

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

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

步骤2:创建表单

在forms.py中定义商品表单,包含所有需要的字段:

# auctions/forms.py
from django import forms
from .models import Listing

class ListingForm(forms.ModelForm):
    class Meta:
        model = Listing
        fields = ['title', 'category', 'description', 'starting_price', 'image', 'image_url']
        widgets = {
            'description': forms.Textarea(attrs={'placeholder': '输入商品描述'}),
            'starting_price': forms.NumberInput(attrs={'placeholder': '起拍价'}),
            'image_url': forms.URLInput(attrs={'placeholder': '输入图片URL(可选)'}),
        }

步骤3:编写视图处理提交

在views.py中实现表单提交逻辑,同时处理文件上传:

# auctions/views.py
from django.shortcuts import render, redirect
from .forms import ListingForm

def create_listing(request):
    if request.method == 'POST':
        # 传入request.FILES处理文件上传
        form = ListingForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('index')  # 提交后跳转到商品列表页
    else:
        form = ListingForm()
    return render(request, 'auctions/create_list.html', {'form': form})

步骤4:修改模板

替换原模板,用单个表单包含所有字段,同时保留你的自定义样式:

{% extends "auctions/layout.html" %}

{% block body %}
    <h2 id="h2">Create List</h2>

    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        
        <h3 id="h3">Title:</h3>
        <input id="input" placeholder="Title" type="text" name="title" value="{{ form.title.value|default:'' }}"/>
        
        <h3 id="h3">Category:</h3>
        <input id="input" placeholder="Category" type="text" name="category" value="{{ form.category.value|default:'' }}"/>
        
        <h3 id="h3">Description:</h3>
        <textarea id="input" placeholder="Description" name="description">{{ form.description.value|default:'' }}</textarea>
        
        <h3 id="h3">Starting Price:</h3>
        <input id="input" placeholder="Starting price" type="number" step="0.01" name="starting_price" value="{{ form.starting_price.value|default:'' }}"/>
        
        <h3 id="h3">上传本地图片(可选):</h3>
        <input id="input" type="file" name="image">
        
        <h3 id="h3">或输入图片URL(可选):</h3>
        <input id="input" placeholder="Image URL" type="url" name="image_url" value="{{ form.image_url.value|default:'' }}"/>
            
        <button id="button" class="btn btn-outline-primary" type="submit">Submit</button>
    </form>
{% endblock %}

步骤5:商品列表页显示图片

在商品列表模板中,优先显示本地上传的图片,其次显示URL图片:

<!-- auctions/index.html 示例 -->
{% for listing in listings %}
<div class="listing-item">
    <h3>{{ listing.title }}</h3>
    {% if listing.image %}
        <img src="{{ listing.image.url }}" alt="{{ listing.title }}" width="200">
    {% elif listing.image_url %}
        <img src="{{ listing.image_url }}" alt="{{ listing.title }}" width="200">
    {% else %}
        <p>暂无图片</p>
    {% endif %}
    <p>{{ listing.description }}</p>
    <p>起拍价: ${{ listing.starting_price }}</p>
</div>
{% endfor %}

内容的提问来源于stack exchange,提问作者zahra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:57:50