首页 > 解决方案 > 如何在django上发布图片?

问题描述

我一直在尝试使我的代码能够发布图像,但是当我创建帖子时,图片不会出现,但图像会保存在媒体/图像上我想知道是否有任何方法可以使代码工作,可能是什么当我调用图像 {{ request.user.image.url }} 时,base.html 中的错误

视图.py

     def create(request):
        if request.method == 'POST':
            created_date = timezone.now()
            header1 = request.POST['header']
            content1 = request.POST['content']
            user = request.user
            uploded_file = request.FILES['image']
            created_obj = Create.objects.create(added_date=created_date, title=header1, content=content1, user=user, image=uploded_file)
            created_obj.save()
            print('create created')
            return redirect('home')
        else:
            print('create not created')
            return render(request, 'create.html')

模型.py

    class Create(models.Model):
        added_date = models.DateTimeField()
        title = models.CharField(max_length=200)
        content = models.CharField(max_length=200)
        image = models.ImageField(null=True, blank=True, upload_to='images/')
        user = models.ForeignKey(User, related_name='user', on_delete=models.CASCADE, default=1)

    class Profile(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        image = models.ImageField(default='default.jpg', upload_to='profile_pics')

        def __str__(self):
            return f'{self.user.username} Profile'

创建.html

    {% extends 'home.html' %}
    {% block body %}
    <div style="margin-top: 200px; margin-left:200px;">
        <form action="create" method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <input type="text" name="header" placeholder="Add here...">
            <input type="text" name="content" placeholder="Add here...">
            <input type="file" name="image">
            <button type="submit"name="action" class="btn btn-primary mb-2">submit</button>
        </form>
    </div>
    {% endblock %}

base.html

    {% extends 'home.html' %}
    {% block body %}
    <ul action="{% url 'create' %}" class="container-sm list-group" style="margin-top: 200px;">
        {% for created_post in created_posts %}
        <li class="list-group-item">{{ created_post.title }}
          <a href="{% url 'profile_pk' pk=created_post.user.pk %}">{{ created_post.user }}</a>
          <img class="image" src="{{ create.image.url }}">
          <p>{{ created_post.content }}</p>
          <div class="float-right">
            <form action="delete_create/{{ created_post.id }}/" action="post">
              <button type="submit" class="btn btn-outline-danger btn-sm">Delete</button>
            </form>
          </div>
          <div class="float-right">
            <a href="{% url 'edit' created_post.id %}" class="btn btn-outline-warning btn-sm" style="margin-right: 5px;" role="button">Edit</a>
          </div>
        </li>     
        {% endfor %}            
    </ul>
    {% endblock %}

标签: pythonhtmldjangodjango-formsdjango-views

解决方案


在大多数网站中,我们经常处理图像,文件等媒体数据。在django中,我们可以借助模型字段ImageField来处理图像。

在本文中,我们在名为 image_upload 的示例项目中创建了应用程序 image_app。

第一步是在 settings.py 文件中添加以下代码。

filter_none
brightness_4
MEDIA_ROOT =  os.path.join(BASE_DIR, 'media') 
MEDIA_URL = '/media/'

MEDIA_ROOT 用于在计算机中存储文件的服务器路径。MEDIA_URL 是浏览器通过 Http 访问文件的参考 URL。

在 urls.py 我们应该像这样编辑配置

如果设置。调试:

urlpatterns += 静态(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)

示例 models.py 应该是这样的,因为我们创建了一个酒店模型,其中包含酒店名称及其图像。在这个项目中,我们从酒店预订网站的用户那里获取酒店名称及其图像。

filter_none
brightness_4
# models.py 
 class Hotel(models.Model): 
    name = models.CharField(max_length=50) 
    hotel_Main_Img = models.ImageField(upload_to='images/') 
//Here upload_to will specify, to which directory the images should reside, by default django creates the directory under media directory which will be automatically created when we upload an image. No need of explicit creation of media directory.

我们必须在 image_app 下创建一个 forms.py 文件,这里我们处理的是模型表单,以使内容更易于理解。

filter_none
brightness_4
# forms.py 
from django import forms 
from .models import *



class HotelForm(forms.ModelForm): 

    class Meta: 
        model = Hotel 
        fields = ['name', 'hotel_Main_Img'] 

Django 将隐式处理表单验证,而无需在脚本中显式声明,它会根据我们在 models.py 文件中指定的模型字段在页面中创建类似的表单字段。这就是模型形式的优势。

现在在 image_app 下创建一个模板目录,我们必须创建一个用于上传图像的 html 文件。HTML 文件应如下所示。

filter_none
edit
play_arrow

brightness_4
<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title>Hotel_image</title> 
</head> 
<body> 
    <form method = "post" enctype="multipart/form-data"> 
        {% csrf_token %} 
        {{ form.as_p }} 
        <button type="submit">Upload</button> 
    </form> 
</body> 
</html> 

在发出 POST 请求时,我们必须以某种方式对构成请求主体的数据进行编码。所以,我们必须在表单标签中指定编码格式。multipart/form-data 要复杂得多,但它允许将整个文件包含在数据中。

csrf_token 用于防止跨站点请求伪造。

form.as_p 只是将所有元素包装在 HTML 段落标签中。优点是不必在模板中编写循环来显式添加 HTML 来包围每个标题和字段。

在 image_app 下的 views.py 中,我们必须编写一个视图来接收用户的请求并返回一些 html 页面。

filter_none
brightness_4
from django.http import HttpResponse 
from django.shortcuts import render, redirect 
from .forms import *

# Create your views here. 
def hotel_image_view(request): 

    if request.method == 'POST': 
        form = HotelForm(request.POST, request.FILES) 

        if form.is_valid(): 
            form.save() 
            return redirect('success') 
    else: 
        form = HotelForm() 
    return render(request, 'hotel_image_form.html', {'form' : form}) 




def success(request): 
    return HttpResponse('successfully uploaded') 

每当 hotel_image_view 命中并且该请求是 POST 时,我们正在创建一个模型表单实例 form = HotelForm(request.POST, request.FILES) 图像将存储在 request.FILES 之一下。如果有效,则保存到数据库中并重定向到成功 url,表示图像上传成功。如果方法不是 POST,我们将使用创建的 html 模板进行渲染。

urls.py 看起来像这样——</p>

filter_none
brightness_4
from django.contrib import admin 
from django.urls import path 
from django.conf import settings 
from django.conf.urls.static import static 
from .views import *

urlpatterns = [ 
    path('image_upload', hotel_image_view, name = 'image_upload'), 
    path('success', success, name = 'success'), 
] 

if settings.DEBUG: 
        urlpatterns += static(settings.MEDIA_URL, 
                              document_root=settings.MEDIA_ROOT) `enter code here`

推荐阅读