【问题标题】:It is possible for Django to upload file without FORMS?Django可以在没有FORMS的情况下上传文件吗?
【发布时间】:2017-01-16 00:02:15
【问题描述】:

我目前正在使用自定义 HTML 模板,而不是在我的 Django 应用上使用表单来上传特定路径中的图像。

应用结构

src/
    media/
        app/
            img/
    app_name/
        templates/
            app_name/
                app_template.html
        __init__.py
        admin.py
        apps.py
        models.py
        tests.py
        urls.py
        views.py
    proj_name/
        __init__.py
        settings.py
        urls.py
        wsgi.py
    manage.py

settings.py

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

models.py

class Document(models.Model):
    doc_file = models.FileField(upload_to='app/img')

views.py

def app_save(request):
    if request.method == 'POST':
        newdoc = Document(doc_file=request.FILES.get('myfile'))
        newdoc.save()

app_template.html

<form id="myform" method="POST" action="{% url 'my_app:save' %}" 
      enctype="multipart/form-data">

    <input type="file" name="myfile">
    <input type="submit"> 
</form>

#结果 提交表单后,我没有任何内部服务器错误,也没有 python 回溯。但是app/img 路径中没有上传图片,在我的数据库中,由于newdoc.save() 查询,我插入了一条空白记录。

可以在没有表单的情况下进行文件管理吗?


#更新

我在forms.py添加了这个

class UploadFileForm(forms.Form):
    file = forms.FileField()

并将我的 app_template.html 更新为:

<form id="myform" method="POST" action="{% url 'my_app:save' %}" 
      enctype="multipart/form-data">

    {{ form.file }}
    <input type="submit"> 
</form>

那么我想在views.py中加入加载app_template.html的功能:

def index(request):
    form = UploadFileForm()
    return render(request, 'app_name/app_template.html', { 'form': form })

并且还将app_save()函数更新为:

 def app_save(request):
    form = UploadFileForm(request.POST, request.FILES)
    if request.method == 'POST':
        if form.is_valid():
            newdoc = Document(doc_file=request.FILES.get('file')) # note 'file' is the name of input file of a form.
            newdoc.save()

现在的问题是

在应用程序中没有发现错误,但没有使用上传的图像文件创建media/app/img 路径。什么地方出了错?我想我在这里漏掉了一些东西。

【问题讨论】:

  • 您在寻找&lt;MEDIA_ROOT&gt;/app/img中的文件吗?
  • 哦,是的,先生,这是media/app/img,我更新了应用程序结构
  • upload_to 始终相对于MEDIA_ROOT。至少如果你使用FileSystemStorage
  • 重要说明:您在表单提交时不使用 javascript 处理程序吗?
  • @SergeyGornostaev 哦,我使用 jquery onsubmit 先生并使用 $.ajax 将数据传递到服务器

标签: python django file django-models


【解决方案1】:

您的后端代码很好。问题出在前端。您不能像其他字段一样使用 jQuery.ajax 提交文件输入。使用FormData:

$('#myform').submit(function(event) {
    if(window.FormData !== undefined) {
        event.preventDefault();

        var formData = new FormData(this);
        var xhr = new XMLHttpRequest();
        xhr.open('POST', $(this).attr('action'), true);
        xhr.setRequestHeader('X-REQUESTED-WITH', 'XMLHttpRequest')            
        xhr.onreadystatechange = function() {
            if(xhr.readyState == 4) {
                if(xhr.status == 200) {
                    result = JSON.parse(xhr.responseText);
                    // Code for success upload
                }
                else {
                    // Code for error
                }
            }
        };
        xhr.send(formData);
    }
});

【讨论】:

  • 感谢您的帮助,但在您的回答中,我收到了此错误 AttributeError: 'NoneType' object has no attribute 'read',它指出了 file_data = uploaded_file.read()。我的 django 版本是 1.10
  • 表示request.FILES.get('myfile')返回None
  • 但我确定它有价值。
  • print request.FILES.keys() 的输出是什么?
  • 它打印 dict_keys([]) 也许这就是它没有返回的原因,但我已经在表单中包含了 enctype="multipart/form-data"
【解决方案2】:

我不明白你为什么不想使用模型表单;它会让事情变得更容易。

但是,如果您真的想在没有人的情况下执行此操作,则需要自己处理实际的上传操作。 documentation 有一个很好的例子来说明你需要做什么;基本上你只需从request.FILES 获取文件并将其保存到你想要的位置。

【讨论】:

  • 我更新了我的帖子,先生,但它似乎不起作用。我想我错过了什么
  • 是的,你做到了。正如我所说,要么使用负责保存的 ModelForm,要么编写一个函数来处理上传。
  • 我在您的链接中找到了带有 FileField 的表单和模型
  • 为什么这个答案会被接受?这不是一个解决方案,也不是对“Django 可以在没有 FORMS 的情况下上传文件吗?”问题的答案
【解决方案3】:

django.core.files 中有ContentFile,使用它来将文件保存为模型字段非常方便。 假设您将一个字段声明为FileField,并且您可能需要创建一个文件并将其保存到该字段的附件中。然后你可以这样做。

from django.core.files.base import ContentFile
from django.db import models

class YourModel(models.Model):
    content = models.FileField(upload_to="any_path_or_callable")
    ...
    def save_file(self, content: str):
        temp_file = ContentFile(content)
        self.content.save(f'{self.pk}.txt', temp_file)

希望对你有帮助。

谢谢

【讨论】:

    猜你喜欢
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    相关资源
    最近更新 更多