【问题标题】:Django - how to transfer user input from views.py to models.py?Django - 如何将用户输入从views.py传输到models.py?
【发布时间】:2018-01-29 10:50:08
【问题描述】:

我正在尝试创建一个允许用户从下拉菜单中选择文件名并上传文件的 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)
)

list.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>

【问题讨论】:

    标签: django django-models django-forms


    【解决方案1】:

    我建议您使用 Djano 的 CreateView 作为您的视图。在你的情况下,你会有

    Class UploadDocumentView(CreateView):
        model = Document
    

    当您在表单上单击提交,并且您的操作指向正确的视图时,它将使用您提供的字段创建一个新文档。

    你的模板应该有这个,url应该是你给你的url的名字。我建议不要使用“list”作为你的 url,因为这是 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 方法来确定要修改数据库中的哪个对象。它知道要查看什么模型,因为它设置为 model = 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)
    

    【讨论】:

    • 感谢您的回答。我已经广泛检查了您的代码,但无法实施更改;我不确定我是否理解。您可以编辑我的代码吗?我的理解是我正在使用基于函数的视图,因为我正在做一些基于类的视图(Django 的UpdateView)无法做的自定义事情。谢谢!
    【解决方案2】:

    我找到了解决方案,用下面的****表示:

    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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-11-02
      • 2021-04-17
      • 1970-01-01
      • 2014-02-08
      • 2011-08-25
      • 2021-12-31
      • 1970-01-01
      相关资源
      最近更新 更多