我正在尝试创建一个 Django 应用程序,允许用户从下拉菜单中选择文件名并上传文件。无论用户如何命名他们的文件,我都会收到该文件,保存为他们在下拉菜单中选择的任何内容加上日期。我似乎无法显示我的下拉菜单。数小时的阅读文档、多个堆栈溢出帖子以及反复试验都无济于事。*有谁知道如何将用户选择的下拉值从 views.py 插入到 models.py 以插入到上传文件的路径中? *
另一方面,我确信我的代码还有其他问题,作为一个 Django 新手,所以如果你看到它们,请指出它们。
models.py
from django.db import models
from datetime import datetime
import os
def update_filename(instance, filename):
path = "documents/"
format = '{0}_{1}.csv'.format(vc, datetime.today().strftime('%Y%m%d'))
#note that vc is defined in views.py but I am not sure how to transfer this to models.py
#*************************************************************
return os.path.join(path, format)
class Document(models.Model):
docfile = models.FileField(upload_to= update_filename) #/%Y/%m/%d')
#value_chains = (('coffee', 'coffee'),('tea', 'tea'),)
dropdown = models.CharField(max_length=20, choices=(('coffee', 'coffee'),('tea', 'tea'),))
forms.py
from django import forms
from .models import Document
def validate_file_extension(value):
if not value.name.endswith('.csv'):
raise forms.ValidationError("Only CSV file is accepted")
class DocumentForm(forms.ModelForm):
docfile = forms.FileField(label='Select a file', validators=[validate_file_extension])
value_chains = (('coffee', 'coffee'),('tea', 'tea'),)
dropdown = forms.ChoiceField(choices=value_chains, required=True)
class Meta:
model = Document
fields = ['dropdown']
views.py
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views.generic.edit import CreateView
from .models import Document
from .forms import DocumentForm
def list(request):
# Handle file upload
if request.method == 'POST':
#bind the data to the form
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
#**** vc is defined here ************************************
vc = form.cleaned_data['dropdown']
newdoc = Document(docfile = request.FILES['docfile'])
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('file_upload_app.views.list'))
# if a GET (or any other method) we'll create a blank form:
else:
form = DocumentForm() # A empty, unbound form. This is what we can expect to happen the first time we visit the URL.
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render_to_response(
'file_upload_app/list.html',
{'documents': documents, 'form': form},
context_instance=RequestContext(request)
)
列表.html
<form action="{% url "list" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.dropdown }}
<p>
<h6>
Note: the uploaded file must be in
<b>.CSV</b>
format and contain a column labeled "A" which contains
<em>only</em>
numbers.
</h6>
</p>
<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>
<!-- List of uploaded documents -->
<p>
{% if documents %}
<div class="col-sm-12" align="center" >
<ul>
<p>Files on server:</p>
{% for document in documents %}
<li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
{% endfor %}
</ul>
</div>
{% else %}
<div class="col-sm-12" align="center" >
<p>No documents.</p>
</div>
我建议你使用Djano的CreateView作为你的视图。在您的情况下,您将拥有
Class UploadDocumentView(CreateView):
model = Document
当您在表单上单击"提交"并且操作指向正确的视图时,它将使用您提供的字段创建一个新文档。
您的模板中应该包含此内容,url 应该是您为 url 指定的名称。 我建议不要使用"list"作为你的网址,因为这是python中的一个特殊名称,Django有自己的ListView概念。
<form id="upload_document" method="POST" action="{% url 'document:upload' %}">
{{ form }}
<input class="btn btn-primary" id="upload_document_button" type="submit" value="Upload Document"/>
</form>
有时看到一个工作示例是有用的。下面的一个使用Django的UpdateView。 UpdateView 将使用 get_object 方法来确定要修改数据库中的哪个对象。 它知道要查看哪个模型,因为它设置为模型 = UserProfile,并且它知道要保存哪些值,因为您在表单中设置了这些值。
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
primary_key=True)
company_identifier = models.CharField(max_length=5, blank=False)
employee_id = models.CharField(max_length=20, null=True, blank=False)
forms.py
def get_company_choices():
company_list = [('','-------')]
companies = models.Company.objects.values_list('id', 'name').order_by('name')
company_list = list(chain(company_list, companies))
return company_list
class EmployerForm(forms.ModelForm):
employee_id_confirm = forms.CharField(label="Confirm Employee ID", required=True)
company_identifier = forms.ChoiceField(choices=get_company_choices, label="Company")
class Meta:
model = models.UserProfile
fields = ('company_identifier', 'employee_id')
labels = {
'employee_id': "Employee ID",
}
views.py
@method_decorator(login_required, name='dispatch')
class EmploymentUpdate(SuccessMessageMixin, UpdateView):
model = UserProfile
template_name = 'employee/update_employment.html'
form_class = forms.EmployerForm
success_url = reverse_lazy('employee:home')
success_message = "Employment Updated."
def get_object(self):
return self.model.objects.get(pk=self.request.user.userprofile.pk)
我找到了解决方案,由下面的****表示:
models.py:
from django.db import models
from datetime import datetime
import os
value_chains = (
('coffee', 'coffee'),
('tea', 'tea'),
)
def update_filename(instance, filename):
path = "documents/"
#*************************************************************
#use instance to access the instance of Document's CharField function, which is defined below
format = '{0}_{1}.csv'.format(instance.dropdown, datetime.today().strftime('%Y%m%d'))
#*************************************************************
return os.path.join(path, format)
class Document(models.Model):
docfile = models.FileField(upload_to= update_filename)
dropdown = models.CharField(max_length=20, choices=value_chains)
class Meta:
permissions = (("access_file_upload_app", "Access file upload tool."),)
views.py:
from django.shortcuts import render_to_response, redirect
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
from django.conf import settings
from .models import Document
from .forms import DocumentForm
@login_required
def doc_upload_view(request):
if request.user.has_perm('file_upload_app.access_file_upload_app') and settings.VC_ENABLED == 'Y':
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
#********************************************************
# make sure to pass the dropdown value to the Document call:
newdoc = Document(docfile = request.FILES['docfile'], dropdown = form.cleaned_data['dropdown'])
#********************************************************
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('file_upload_app.views.doc_upload_view'))
else:
form = DocumentForm() # An 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(
'file_upload_app/doc_upload_view.html',
{'documents': documents, 'form': form},
context_instance=RequestContext(request)
)
else:
return redirect('/home/')
forms.py:
from django import forms
from .models import Document
def validate_file_extension(value):
if not value.name.endswith('.csv'):
raise forms.ValidationError("Only CSV file is accepted")
class DocumentForm(forms.ModelForm):
value_chains = (('coffee', 'coffee'),('tea', 'tea'),)
docfile = forms.FileField(label='Select a file', validators=[validate_file_extension])
dropdown = forms.ChoiceField(choices=value_chains, required=True )
class Meta:
model = Document
fields = ('dropdown',)
doc_upload_view.html:
<!-- Upload form. Note enctype attribute! -->
<form action="{% url "doc_upload_view" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.dropdown }}
<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>
<!-- List of uploaded documents -->
<p class="top-space">
{% if documents %}
<div class="col-sm-12" align="center" >
<ul>
<p>Files on server:</p>
{% for document in documents %}
<li><a href="{{ document.docfile.url }}">{{ document.docfile.name }}</a></li>
{% endfor %}
</ul>
</div>
{% else %}
<div class="col-sm-12" align="center" >
<p>No documents.</p>
</div>
{% endif %}
</p>