Ответы:
Уф, документация Django действительно не имеет хорошего примера по этому поводу. Я потратил более 2 часов, чтобы выкопать все кусочки, чтобы понять, как это работает. С этим знанием я реализовал проект, который позволяет загружать файлы и показывать их в виде списка. Чтобы загрузить исходный код проекта, посетите https://github.com/axelpale/minimal-django-file-upload-example или клонируйте его:
> git clone https://github.com/axelpale/minimal-django-file-upload-example.git
Обновление 2013-01-30: Источник на GitHub также имеет реализацию для Django 1.4 в дополнение к 1.3. Несмотря на небольшое количество изменений, следующий урок также полезен для 1.4.
Обновление 2013-05-10: реализация для Django 1.5 на GitHub. Небольшие изменения в перенаправлении в urls.py и использование тега шаблона URL в list.html. Спасибо hubert3 за усилия.
Обновление 2013-12-07: Django 1.6 поддерживается на GitHub. Один импорт изменен в myapp / urls.py. Спасибо идет в Arthedian .
Обновление 2015-03-17: Django 1.7 поддерживается на GitHub, благодаря aronysidoro .
Обновление 2015-09-04: Django 1.8 поддерживается на GitHub, благодаря nerogit .
Обновление 2016-07-03: Django 1.9 поддерживается на GitHub, благодаря daavve и nerogit
Базовый проект Django 1.3 с одним приложением и медиа / каталогом для загрузки.
minimal-django-file-upload-example/
src/
myproject/
database/
sqlite.db
media/
myapp/
templates/
myapp/
list.html
forms.py
models.py
urls.py
views.py
__init__.py
manage.py
settings.py
urls.py
Чтобы загружать и обслуживать файлы, вам нужно указать, где Django хранит загруженные файлы и с какого URL Django их обслуживает. MEDIA_ROOT и MEDIA_URL по умолчанию находятся в settings.py, но они пусты. Подробности смотрите в первых строках Django Managing Files . Не забудьте также установить базу данных и добавить myapp в INSTALLED_APPS
...
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'database.sqlite3'),
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
...
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
...
INSTALLED_APPS = (
...
'myapp',
)
Далее вам нужна модель с FileField. В этом конкретном поле хранятся файлы, например, в media / documents / 2011/12/24 / на основе текущей даты и MEDIA_ROOT. Смотрите ссылку на FileField .
# -*- coding: utf-8 -*-
from django.db import models
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
Для удобной загрузки вам нужна форма. Эта форма имеет только одно поле, но этого достаточно. См. Ссылку FileField формы для деталей.
# -*- coding: utf-8 -*-
from django import forms
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file',
help_text='max. 42 megabytes'
)
Вид, где происходит вся магия. Обратите внимание, как request.FILES
обрабатываются. Для меня было действительно трудно определить факт, который request.FILES['docfile']
можно сохранить в моделях. FileField просто так. Модель save () автоматически обрабатывает сохранение файла в файловой системе.
# -*- coding: utf-8 -*-
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from myproject.myapp.models import Document
from myproject.myapp.forms import DocumentForm
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile = request.FILES['docfile'])
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('myapp.views.list'))
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render_to_response(
'myapp/list.html',
{'documents': documents, 'form': form},
context_instance=RequestContext(request)
)
Django не обслуживает MEDIA_ROOT по умолчанию. Это было бы опасно в производственной среде. Но на стадии разработки мы могли бы прервать. Обратите внимание на последнюю строчку. Эта строка позволяет Django обслуживать файлы из MEDIA_URL. Это работает только в стадии разработки.
Подробности смотрите в django.conf.urls.static.static . Смотрите также это обсуждение об обслуживании медиа-файлов .
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
(r'^', include('myapp.urls')),
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Чтобы сделать представление доступным, вы должны указать для него URL-адреса. Здесь нет ничего особенного.
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
urlpatterns = patterns('myapp.views',
url(r'^list/$', 'list', name='list'),
)
Последняя часть: шаблон для списка и форма загрузки под ним. Форма должна иметь атрибут enctype, установленный в «multipart / form-data», и метод, установленный в «post», чтобы сделать возможной загрузку в Django. Подробнее смотрите в документации по загрузке файлов .
FileField имеет много атрибутов, которые можно использовать в шаблонах. Например, {{document.docfile.url}} и {{document.docfile.name}} как в шаблоне. Подробнее об этом см. В статье « Использование файлов в моделях» и документации по объекту «Файл» .
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Minimal Django File Upload Example</title>
</head>
<body>
<!-- List of uploaded documents -->
{% if documents %}
<ul>
{% for document in documents %}
<li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No documents.</p>
{% endif %}
<!-- Upload form. Note enctype attribute! -->
<form action="{% url 'list' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload" /></p>
</form>
</body>
</html>
Просто запустите syncdb и runserver.
> cd myproject
> python manage.py syncdb
> python manage.py runserver
Наконец-то все готово. По умолчанию в среде разработки Django список загруженных документов можно посмотреть по адресу localhost:8000/list/
. Сегодня файлы загружены в / path / to / myproject / media / documents / 2011/12/17 / и могут быть открыты из списка.
Я надеюсь, что этот ответ поможет кому-то так же, как и мне.
{% url list %}
делается {% url "list" %}
.
Вообще говоря, когда вы пытаетесь «просто получить рабочий пример», лучше всего «просто начать писать код». Здесь нет кода, который мог бы вам помочь, поэтому он делает ответ на этот вопрос намного более полезным для нас.
Если вы хотите получить файл, вам нужно что-то вроде этого в html-файле:
<form method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" name="submit" value="Upload" />
</form>
Это даст вам кнопку обзора, кнопку загрузки, чтобы начать действие (отправить форму) и отметить энктип, чтобы Django знал, чтобы дать вам request.FILES
В представлении где-то вы можете получить доступ к файлу с
def myview(request):
request.FILES['myfile'] # this is my file
В документах для загрузки файлов содержится огромное количество информации.
Я рекомендую вам внимательно прочитать страницу и просто начать писать код, а затем возвращаться с примерами и трассировкой стека, когда он не работает.
enctype="multipart/form-data"
, Что мне нужно , чтобы сделать эту работу, спасибо!
Смотрите репозиторий github , работает с Django 3
Запустите startproject ::
$ django-admin.py startproject sample
Теперь папка ( образец ) создана.
Создать приложение ::
$ cd sample
$ python manage.py startapp uploader
Теперь папка ( uploader
) с этими файлами создана:
uploader/
__init__.py
admin.py
app.py
models.py
tests.py
views.py
migrations/
__init__.py
На sample/settings.py
оных 'uploader'
к INSTALLED_APPS
и добавить MEDIA_ROOT
и MEDIA_URL
, то есть ::
INSTALLED_APPS = [
'uploader',
...<other apps>...
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
в sample/urls.py
добавлении ::
...<other imports>...
from django.conf import settings
from django.conf.urls.static import static
from uploader import views as uploader_views
urlpatterns = [
...<other url patterns>...
path('', uploader_views.UploadView.as_view(), name='fileupload'),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
обновление uploader/models.py
::
from django.db import models
class Upload(models.Model):
upload_file = models.FileField()
upload_date = models.DateTimeField(auto_now_add =True)
обновление uploader/views.py
::
from django.views.generic.edit import CreateView
from django.urls import reverse_lazy
from .models import Upload
class UploadView(CreateView):
model = Upload
fields = ['upload_file', ]
success_url = reverse_lazy('fileupload')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['documents'] = Upload.objects.all()
return context
Создайте папку sample / uploader / templates / uploader
Создайте файл upload_form.html т.е. sample/uploader/templates/uploader/upload_form.html
::
<div style="padding:40px;margin:40px;border:1px solid #ccc">
<h1>Django File Upload</h1>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form><hr>
<ul>
{% for document in documents %}
<li>
<a href="{{ document.upload_file.url }}">{{ document.upload_file.name }}</a>
<small>({{ document.upload_file.size|filesizeformat }}) - {{document.upload_date}}</small>
</li>
{% endfor %}
</ul>
</div>
Синхронизировать базу данных и сервер запуска ::
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
посетите http: // localhost: 8000 /
FileField
то время, а Сухаил использовал ImageField
, может кто-нибудь объяснить, пожалуйста, выбор?
FileField
. ImageField
необходимо только для загрузки изображения. обновление будет работать с Django 1.11.
Я должен сказать, что нахожу документацию в Django запутанной. Также для простейшего примера, почему упоминаются формы? Пример, который я получил для работы в views.py:
for key, file in request.FILES.items():
path = file.name
dest = open(path, 'w')
if file.multiple_chunks:
for c in file.chunks():
dest.write(c)
else:
dest.write(file.read())
dest.close()
HTML-файл выглядит как приведенный ниже код, хотя в этом примере загружается только один файл, а код для сохранения файлов обрабатывает множество: -
<form action="/upload_file/" method="post" enctype="multipart/form-data">{% csrf_token %}
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
Эти примеры не являются моим кодом, они были получены из двух других примеров, которые я нашел. Я относительный новичок в Django, поэтому очень вероятно, что я упустил какой-то ключевой момент.
FileField
и а model.Form
. Для начинающих (и для тривиальных задач) ручная обработка загруженных файлов, как показано выше, менее запутанна.
У меня тоже было подобное требование. Большинство примеров в сети просят создать модели и формы, которые я не хотел использовать. Вот мой окончательный код.
if request.method == 'POST':
file1 = request.FILES['file']
contentOfFile = file1.read()
if file1:
return render(request, 'blogapp/Statistics.html', {'file': file1, 'contentOfFile': contentOfFile})
И в HTML для загрузки я написал:
{% block content %}
<h1>File content</h1>
<form action="{% url 'blogapp:uploadComplete'%}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input id="uploadbutton" type="file" value="Browse" name="file" accept="text/csv" />
<input type="submit" value="Upload" />
</form>
{% endblock %}
Ниже приводится HTML, который отображает содержимое файла:
{% block content %}
<h3>File uploaded successfully</h3>
{{file.name}}
</br>content = {{contentOfFile}}
{% endblock %}
Продолжая на примере Генри :
import tempfile
import shutil
FILE_UPLOAD_DIR = '/home/imran/uploads'
def handle_uploaded_file(source):
fd, filepath = tempfile.mkstemp(prefix=source.name, dir=FILE_UPLOAD_DIR)
with open(filepath, 'wb') as dest:
shutil.copyfileobj(source, dest)
return filepath
Вы можете вызвать эту handle_uploaded_file
функцию из своего поля зрения с загруженным файловым объектом. Это сохранит файл с уникальным именем (с префиксом имени исходного загруженного файла) в файловой системе и вернет полный путь сохраненного файла. Вы можете сохранить путь в базе данных и что-то сделать с файлом позже.
request.FILES['myfile']
) handle_uploaded_file
, а не request
самому себе.
prefix=source.name
его использовании добавляются дополнительные символы в конце файла, что портит расширение файла. Например, upload.csv
изменился на upload.csv5334
. Меняя это, чтобы suffix=source.name
исправить это для меня.
Здесь это может помочь вам: создайте поле файла в вашем models.py
Для загрузки файла (в вашем admin.py):
def save_model(self, request, obj, form, change):
url = "http://img.youtube.com/vi/%s/hqdefault.jpg" %(obj.video)
url = str(url)
if url:
temp_img = NamedTemporaryFile(delete=True)
temp_img.write(urllib2.urlopen(url).read())
temp_img.flush()
filename_img = urlparse(url).path.split('/')[-1]
obj.image.save(filename_img,File(temp_img)
и используйте это поле в вашем шаблоне.
Вы можете обратиться к примерам сервера в Fine Uploader, который имеет версию django. https://github.com/FineUploader/server-examples/tree/master/python/django-fine-uploader
Это очень элегантный и самый важный из всех, он предоставляет JS lib. Шаблон не включен в примеры серверов, но вы можете найти демо на его сайте. Fine Uploader: http://fineuploader.com/demos.html
views.py
UploadView отправляет запрос на публикацию и удаление соответствующим обработчикам.
class UploadView(View):
@csrf_exempt
def dispatch(self, *args, **kwargs):
return super(UploadView, self).dispatch(*args, **kwargs)
def post(self, request, *args, **kwargs):
"""A POST request. Validate the form and then handle the upload
based ont the POSTed data. Does not handle extra parameters yet.
"""
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_upload(request.FILES['qqfile'], form.cleaned_data)
return make_response(content=json.dumps({ 'success': True }))
else:
return make_response(status=400,
content=json.dumps({
'success': False,
'error': '%s' % repr(form.errors)
}))
def delete(self, request, *args, **kwargs):
"""A DELETE request. If found, deletes a file with the corresponding
UUID from the server's filesystem.
"""
qquuid = kwargs.get('qquuid', '')
if qquuid:
try:
handle_deleted_file(qquuid)
return make_response(content=json.dumps({ 'success': True }))
except Exception, e:
return make_response(status=400,
content=json.dumps({
'success': False,
'error': '%s' % repr(e)
}))
return make_response(status=404,
content=json.dumps({
'success': False,
'error': 'File not present'
}))
forms.py
class UploadFileForm(forms.Form):
""" This form represents a basic request from Fine Uploader.
The required fields will **always** be sent, the other fields are optional
based on your setup.
Edit this if you want to add custom parameters in the body of the POST
request.
"""
qqfile = forms.FileField()
qquuid = forms.CharField()
qqfilename = forms.CharField()
qqpartindex = forms.IntegerField(required=False)
qqchunksize = forms.IntegerField(required=False)
qqpartbyteoffset = forms.IntegerField(required=False)
qqtotalfilesize = forms.IntegerField(required=False)
qqtotalparts = forms.IntegerField(required=False)
Я столкнулся с подобной проблемой и решил администратор сайта django.
# models
class Document(models.Model):
docfile = models.FileField(upload_to='documents/Temp/%Y/%m/%d')
def doc_name(self):
return self.docfile.name.split('/')[-1] # only the name, not full path
# admin
from myapp.models import Document
class DocumentAdmin(admin.ModelAdmin):
list_display = ('doc_name',)
admin.site.register(Document, DocumentAdmin)