Câu trả lời:
Phew, tài liệu Django thực sự không có ví dụ hay về điều này. Tôi đã dành hơn 2 giờ để đào tất cả các mảnh để hiểu cách thức hoạt động của nó. Với kiến thức đó, tôi đã thực hiện một dự án có thể tải lên các tệp và hiển thị chúng dưới dạng danh sách. Để tải xuống nguồn cho dự án, hãy truy cập https://github.com/axelpale/minimal-django-file-upload-example hoặc sao chép nó:
> git clone https://github.com/axelpale/minimal-django-file-upload-example.git
Cập nhật 2013-01-30: Nguồn tại GitHub cũng đã triển khai cho Django 1.4 ngoài 1.3. Mặc dù có một vài thay đổi, hướng dẫn sau đây cũng hữu ích cho 1.4.
Cập nhật 2013-05-10: Triển khai Django 1.5 tại GitHub. Những thay đổi nhỏ trong chuyển hướng trong url url và việc sử dụng thẻ mẫu url trong list.html. Cảm ơn hubert3 cho những nỗ lực.
Cập nhật 2013-12-07: Django 1.6 được hỗ trợ tại GitHub. Một lần nhập đã thay đổi trong myapp / urls.py. Cảm ơn đến Arthedian .
Cập nhật 2015/03/17: Django 1.7 được hỗ trợ tại GitHub, nhờ aronysidoro .
Cập nhật 2015-09-04: Django 1.8 được hỗ trợ tại GitHub, nhờ vào nerogit .
Cập nhật 2016/07/03: Django 1.9 được hỗ trợ tại GitHub, nhờ daavve và nerogit
Một dự án Django 1.3 cơ bản với ứng dụng duy nhất và phương tiện / thư mục để tải lên.
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
Để tải lên và phục vụ các tệp, bạn cần chỉ định nơi Django lưu trữ các tệp đã tải lên và từ URL nào Django phục vụ chúng. MEDIA_ROOT và MEDIA_URL theo mặc định trong settings.txt nhưng chúng trống. Xem các dòng đầu tiên trong Django Manage Files để biết chi tiết. Nhớ cũng đặt cơ sở dữ liệu và thêm myapp vào 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',
)
Tiếp theo bạn cần một mô hình với FileField. Trường cụ thể này lưu trữ các tệp, ví dụ như phương tiện / tài liệu / 2011/12/24 / dựa trên ngày hiện tại và MEDIA_ROOT. Xem tài liệu tham khảo FileField .
# -*- coding: utf-8 -*-
from django.db import models
class Document(models.Model):
docfile = models.FileField(upload_to='documents/%Y/%m/%d')
Để xử lý tải lên độc đáo, bạn cần một hình thức. Hình thức này chỉ có một lĩnh vực nhưng thế là đủ. Xem tài liệu tham khảo Form FileField để biết chi tiết.
# -*- coding: utf-8 -*-
from django import forms
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file',
help_text='max. 42 megabytes'
)
Một cái nhìn nơi tất cả các phép thuật xảy ra. Hãy chú ý cách request.FILES
xử lý. Đối với tôi, thật khó để phát hiện ra thực tế request.FILES['docfile']
có thể được lưu vào các mô hình.FileField giống như vậy. Save () của mô hình tự động xử lý việc lưu trữ tệp vào hệ thống tệp.
# -*- 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 không phục vụ MEDIA_ROOT theo mặc định. Điều đó sẽ nguy hiểm trong môi trường sản xuất. Nhưng trong giai đoạn phát triển, chúng ta có thể cắt ngắn. Hãy chú ý đến dòng cuối cùng. Dòng đó cho phép Django phục vụ các tệp từ MEDIA_URL. Điều này chỉ hoạt động trong giai đoạn phát triển.
Xem tài liệu tham khảo django.conf.urls.static.static để biết chi tiết. Xem thêm cuộc thảo luận này về việc phục vụ các tập tin phương tiện truyền thông .
# -*- 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)
Để làm cho chế độ xem có thể truy cập, bạn phải chỉ định các url cho nó. Không có gì đặc biệt ở đây.
# -*- coding: utf-8 -*-
from django.conf.urls import patterns, url
urlpatterns = patterns('myapp.views',
url(r'^list/$', 'list', name='list'),
)
Phần cuối cùng: mẫu cho danh sách và hình thức tải lên bên dưới nó. Biểu mẫu phải có thuộc tính enctype được đặt thành "nhiều dữ liệu / biểu mẫu dữ liệu" và phương thức được đặt thành "bài đăng" để có thể tải lên Django. Xem tài liệu Tải lên tệp để biết chi tiết.
FileField có nhiều thuộc tính có thể được sử dụng trong các mẫu. Ví dụ: {{document.docfile.url}} và {{document.docfile.name}} như trong mẫu. Xem thêm về những điều này trong Sử dụng tệp trong bài viết mô hình và Tài liệu đối tượng Tệp .
<!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>
Chỉ cần chạy syncdb và máy chủ.
> cd myproject
> python manage.py syncdb
> python manage.py runserver
Cuối cùng, mọi thứ đã sẵn sàng. Trên môi trường phát triển Django mặc định, có thể xem danh sách các tài liệu được tải lên tạilocalhost:8000/list/
. Hôm nay các tệp được tải lên / path / to / myproject / media / Documents / 2011/12/17 / và có thể được mở từ danh sách.
Tôi hy vọng câu trả lời này sẽ giúp được ai đó nhiều như nó sẽ giúp tôi.
{% url list %}
trở thành {% url "list" %}
.
Nói chung, khi bạn đang cố gắng 'chỉ lấy một ví dụ hoạt động', tốt nhất là 'chỉ bắt đầu viết mã'. Không có mã ở đây để giúp bạn, vì vậy nó giúp trả lời câu hỏi nhiều hơn cho chúng tôi.
Nếu bạn muốn lấy một tập tin, bạn cần một cái gì đó như thế này trong một tập tin html ở đâu đó:
<form method="post" enctype="multipart/form-data">
<input type="file" name="myfile" />
<input type="submit" name="submit" value="Upload" />
</form>
Điều đó sẽ cung cấp cho bạn nút duyệt, nút tải lên để bắt đầu hành động (gửi biểu mẫu) và lưu ý mã hóa để Django biết để cung cấp cho bạn request.FILES
Trong chế độ xem ở đâu đó, bạn có thể truy cập tệp với
def myview(request):
request.FILES['myfile'] # this is my file
Có một lượng lớn thông tin trong các tài liệu tải lên tập tin
Tôi khuyên bạn nên đọc kỹ trang và chỉ bắt đầu viết mã - sau đó quay lại với các ví dụ và ngăn xếp dấu vết khi nó không hoạt động.
enctype="multipart/form-data"
gì tôi cần để làm cho công việc này, cảm ơn!
Xem repo github , hoạt động với Django 3
Chạy startproject ::
$ django-admin.py startproject sample
bây giờ một thư mục ( mẫu ) được tạo ra.
Tạo một ứng dụng ::
$ cd sample
$ python manage.py startapp uploader
Bây giờ một thư mục ( uploader
) với các tệp này được tạo ::
uploader/
__init__.py
admin.py
app.py
models.py
tests.py
views.py
migrations/
__init__.py
Mở sample/settings.py
add 'uploader'
để INSTALLED_APPS
và thêm MEDIA_ROOT
và MEDIA_URL
, tức ::
INSTALLED_APPS = [
'uploader',
...<other apps>...
]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
trong sample/urls.py
thêm ::
...<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)
cập nhật uploader/models.py
::
from django.db import models
class Upload(models.Model):
upload_file = models.FileField()
upload_date = models.DateTimeField(auto_now_add =True)
cập nhật 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
Tạo một mẫu thư mục / trình tải lên / mẫu / trình tải lên
Tạo một tệp upload_form.html tức là 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>
Đồng bộ hóa cơ sở dữ liệu và máy chủ ::
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
truy cập http: // localhost: 8000 /
FileField
thời gian suhail sử dụng một ImageField
, ai đó có thể vui lòng giải thích các lựa chọn?
FileField
. ImageField
phải cho hình ảnh chỉ tải lên. Bản cập nhật sẽ hoạt động với Django 1.11.
Tôi phải nói rằng tôi tìm thấy các tài liệu tại django khó hiểu. Ngoài ra đối với ví dụ đơn giản nhất tại sao các hình thức được đề cập? Ví dụ tôi có để làm việc trong lượt xem là: -
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()
Tệp html trông giống như mã bên dưới, mặc dù ví dụ này chỉ tải lên một tệp và mã để lưu các tệp xử lý nhiều: -
<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>
Những ví dụ này không phải là mã của tôi, chúng đã được lấy từ hai ví dụ khác mà tôi tìm thấy. Tôi là người mới bắt đầu với django nên rất có khả năng tôi đang thiếu một số điểm chính.
FileField
và a model.Form
. Đối với người mới bắt đầu (và đối với các tác vụ tầm thường), xử lý thủ công các tệp được tải lên như hiển thị ở trên ít gây nhầm lẫn.
Tôi cũng có yêu cầu tương tự. Hầu hết các ví dụ trên mạng đang yêu cầu tạo mô hình và tạo các biểu mẫu mà tôi không muốn sử dụng. Đây là mã cuối cùng của tôi.
if request.method == 'POST':
file1 = request.FILES['file']
contentOfFile = file1.read()
if file1:
return render(request, 'blogapp/Statistics.html', {'file': file1, 'contentOfFile': contentOfFile})
Và trong HTML để tải lên, tôi đã viết:
{% 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 %}
Sau đây là HTML hiển thị nội dung của tệp:
{% block content %}
<h3>File uploaded successfully</h3>
{{file.name}}
</br>content = {{contentOfFile}}
{% endblock %}
Mở rộng trên ví dụ của Henry :
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
Bạn có thể gọi handle_uploaded_file
chức năng này từ chế độ xem của bạn với đối tượng tệp được tải lên. Điều này sẽ lưu tệp với một tên duy nhất (tiền tố với tên tệp của tệp được tải lên ban đầu) trong hệ thống tệp và trả về đường dẫn đầy đủ của tệp đã lưu. Bạn có thể lưu đường dẫn trong cơ sở dữ liệu và làm một cái gì đó với tệp sau này.
request.FILES['myfile']
Truyền đối tượng tệp đã tải lên ( ) cho handle_uploaded_file
, không phải request
chính nó.
prefix=source.name
nó đã thêm các ký tự phụ ở cuối tệp, làm rối tung phần mở rộng tệp. Ví dụ: upload.csv
đã đổi thành upload.csv5334
. Thay đổi nó để suffix=source.name
sửa nó cho tôi.
Ở đây nó có thể giúp bạn: tạo một trường tệp trong mô hình của bạn
Để tải lên tệp (trong admin.txt của bạn):
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)
và sử dụng trường đó trong mẫu của bạn cũng.
Bạn có thể tham khảo các ví dụ về máy chủ trong Fine Uploader, có phiên bản django. https://github.com/FineUploader/server-examples/tree/master/python/django-fine-uploader
Nó rất thanh lịch và quan trọng nhất, nó cung cấp lib js đặc trưng. Mẫu không được bao gồm trong các ví dụ máy chủ, nhưng bạn có thể tìm thấy bản demo trên trang web của nó. Trình tải lên tốt: http://fineuploader.com/demos.html
lượt xem
UploadView gửi bài và xóa yêu cầu đến xử lý tương ứng.
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'
}))
biểu mẫu
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)
Tôi đã đối mặt với vấn đề tương tự, và giải quyết bằng trang web quản trị 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)