Django Image无法保存

krcsximq  于 2023-06-25  发布在  Go
关注(0)|答案(1)|浏览(121)

我在一个网站上工作,在那里你可以上传一个项目。每个项目都包含一个名称,描述,图像和截止日期,您可以设置。
当我试图通过按下“保存项目”按钮上传项目时,我会按预期重定向到我的主页,但图像不会被保存,其他所有内容都会保存。我没有收到任何错误信息。
models.py:

from django.db import models

class Project(models.Model):
    project_name = models.CharField(max_length=100)
    project_description = models.CharField(max_length=2000)
    created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True,)
    deadline = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return self.project_name

class Image(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='project_images')
    image = models.ImageField(null=True, blank=True, upload_to="images/")

    def __str__(self):
        return self.image.name

forms.py:

from django import forms
from django.forms import inlineformset_factory
from .models import Project, Image

class ProjectForm(forms.ModelForm):
    class Meta:
        model = Project
        fields = ['project_name', 'project_description', 'deadline']
        widgets = {
            'deadline': forms.DateTimeInput(attrs={'type': 'date'}),
        }

ImageFormSet = inlineformset_factory(Project, Image, fields=('image',), extra=5, can_delete=True,)

views.py:

from django.shortcuts import render, redirect, get_object_or_404
from .models import Project
from .forms import ProjectForm, ImageFormSet

def homepage(request):
    projects = Project.objects.all()
    context = {
        'projects': projects,
    }
    return render(request, 'project.html', context)

def create_project(request):
    if request.method == 'POST':
        project_form = ProjectForm(request.POST)
        if project_form.is_valid():
            project = project_form.save()
            formset = ImageFormSet(request.POST, request.FILES, instance=project)
            if formset.is_valid():
                formset.save()
                return redirect('http://127.0.0.1:8000')
    else:
        project_form = ProjectForm()
        formset = ImageFormSet()

    context = {
        'project_form': project_form,
        'formset': formset,
    }
    return render(request, 'create_project.html', context)

create_project.html:

<!DOCTYPE html>
<html>

<head>
    <title>Create Project</title>
</head>

<body>
    <h1>Create Project</h1>

    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        <label for="{{ project_form.project_name.id_for_label }}">Project name:</label>
        {{ project_form.project_name }}
        <br>
        <label for="{{ project_form.project_description.id_for_label }}">Project description:</label>
        {{ project_form.project_description }}
        <br>
        {{ formset.management_form }}
        <div id="image-container"></div>
        <br>
        <label for="{{ project_form.deadline.id_for_label }}">Deadline:</label>
        {{ project_form.deadline }}
        <br>
        <button type="button" id="add-image-btn">Add Image</button>
        <button type="submit">Save Project</button>
    </form>

    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const addImageBtn = document.getElementById('add-image-btn');
            const imageContainer = document.getElementById('image-container');
    
            let imageCount = 0;
    
            addImageBtn.addEventListener('click', () => {
                // Checks if imagefield is empty
                const previousImageInput = document.querySelector(`[name="form-${imageCount-1}-image"]`);
                if (previousImageInput && previousImageInput.value === '') {
                    alert('Add a image to the existing field, before creating a new one.');
                    return;
                }
    
                if (imageCount < 5) {
                    const newImageRow = document.createElement('div');
                    newImageRow.className = 'image-row';
                    const label = document.createElement('label');
                    label.textContent = 'Image:';
                    const imageInput = document.createElement('input');
                    imageInput.type = 'file';
                    imageInput.name = `form-${imageCount}-image`;
                    const deleteBtn = document.createElement('button');
                    deleteBtn.type = 'button';
                    deleteBtn.className = 'delete-image-btn';
                    deleteBtn.textContent = 'Delete Image';
                    newImageRow.appendChild(label);
                    newImageRow.appendChild(imageInput);
                    newImageRow.appendChild(deleteBtn);
                    imageContainer.appendChild(newImageRow);
                    imageCount++;
                }
            });
    
            imageContainer.addEventListener('click', (event) => {
                if (event.target.className === 'delete-image-btn') {
                    const imageRow = event.target.parentNode;
                    imageRow.remove();
                    imageCount--;
                }
            });
        });
    </script>
    

</body>

</html>

project.html:

<!DOCTYPE html>
<html>

<head>
    <title>Create Projects</title>
</head>

<body>
    <a href="/create_project"><h2>Create a new project</h2></a>

    <h1>Projects</h1>

    {% for project in projects|dictsortreversed:"created_at" %}
        <div>
            <hr>
            <h2>{{ project.project_name }}</h2>
            <p>{{ project.project_description }}</p>
            <p>Created at: {{ project.created_at }}</p>
            {% if project.deadline %}
                <p>Deadline: {{ project.deadline }}</p>
            {% endif %}
            {% for image in project.project_images.all %}
                {% if image.image %}
                    <img src="{{ image.image.url }}" alt="Project Picture could not be loaded" style="max-width: 500px;">
                {% else %}
                    <p>No image available for this project.</p>
                {% endif %}
            {% empty %}
                <p>No images available for this project.</p>
            {% endfor %}
            <a href="{% url 'edit_project' project.id %}">Bearbeiten</a>
            <br>
        </div>
    {% empty %}
        <p>Keine Projekte vorhanden.</p>
    {% endfor %}
</body>

</html>

settings.py:

STATIC_URL = 'static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
    )

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('', include('projekte.urls')),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.homepage, name='index'),
    path('delete_picture/<int:project_id>/', views.delete_picture, name='delete_picture'),
    path('edit_project/<int:project_id>/', views.edit_project, name='edit_project'),
    path('delete_project/<int:project_id>/', views.delete_project, name='delete_project'),
    path('create_project', views.create_project, name='create_project'),

]

在模型中,我定义了两个模型,Project和Image。“项目”处理项目名称,描述,创建日期和截止日期。“Image”包含一个Imagefield,并且与Project有外键关系。
Forms有一个使用Modelform的名为Projectform的类。我把它和模型项目联系起来了。之后,我使用inlineformset_factory为Project和Image模型创建了一个内联表单集工厂,因此它可以为一个项目处理许多图像。
有两个功能。其中之一是homepage,它从数据库中检索所有项目,并将其传递给project.html。它会显示所有信息,比如名字,图像...第二个函数“create_project”处理用于创建新项目的GET和POST请求。当发出POST请求时,它验证ProjectForm和关联的ImageFormSet。如果这两个表单都有效,它应该保存项目和相关的图像,然后重定向到主页。当发出GET请求时,它将创建ProjectForm和ImageFormSet的示例,以显示用于创建新项目的空表单。表单作为上下文数据传递给create_project.html模板进行呈现。
Create_project. html是用于创建项目的基本HTML模板。它包括一个表单,其中包含项目名称、描述、截止日期等字段,以及添加多个图像的选项。表单使用POST方法和enctype multipart/form-data来处理文件上传。
底部的脚本部分包含代码,当单击“添加图像”按钮时,该代码检查前一个图像输入字段是否为空。如果是,则显示警告,并且不创建新的图像字段。这样可以确保用户在添加新图像字段之前先填写上一个图像字段。

  • 如果前一图像输入字段不为空并且总图像计数小于5,则创建新图像字段。每个图像字段由一个标签、一个“文件”类型的输入字段和一个删除按钮组成。“添加图像”按钮还创建了一个“删除图像”按钮。它从DOM中删除相应的图像字段并减少图像计数。

这至少是我尝试过的,但它不会保存图像,也不会保存到数据库中。只是一个猜测,但我认为问题可能在于create_project.html文件,因为它已经能够保存多个图像,但经过一些变化,并添加一个它打破了,我无法修复它。我的目标是当我按下“保存项目”,也图像得到保存不仅名称,描述,截止日期,创建日期。
输入表单截图:

保存项目后主页截图:

感谢您的关注:)

du7egjpx

du7egjpx1#

通过引用.save方法中的项目

formset.save(project=project)

当fileForm作为modelForm使用时,它可以工作,无论如何,为什么你不把imagefield放在项目模型上?

相关问题