【问题标题】:How do I store the uploaded file inside a folder having the name from the model field in django?如何将上传的文件存储在具有 django 模型字段名称的文件夹中?
【发布时间】:2019-07-19 01:29:41
【问题描述】:

使用FileFieldupload_to参数我想将用户上传的文件存储在一个名为TestName的文件夹中,即用户输入的测试名称。我编写了以下代码,但它创建了一个名为“models.CharField(max_length=255)”的文件夹。我该如何解决这个问题?

from django.core.validators import FileExtensionValidator
from django.db import models
from django.contrib.auth.models import User


class TestInfo(models.Model):
    TestName = models.CharField(max_length=255)
    MaxMarks = models.IntegerField()
    TimeDuration = models.IntegerField()
    PosMarks = models.IntegerField()
    NegMarks = models.IntegerField()
    InputTextFile = models.FileField(upload_to='Tests/{}/'.format(TestName),\
    validators[FileExtensionValidator(allowed_extensions['txt'])],blank=False)

    def __str__(self):
        return self.TestName

【问题讨论】:

标签: django python-3.x django-models


【解决方案1】:

我认为您只是错过了一个可以帮助您的附加功能。我现在没有时间特别测试这个,但你正在寻找这样的东西:

from django.core.validators import FileExtensionValidator
from django.db import models
from django.contrib.auth.models import User

def content_file_name(instance, filename):
    return "Tests/{folder}/{file}".format(folder=instance.TestName, file=filename)

class TestInfo(models.Model):
    TestName = models.CharField(max_length=255)
    MaxMarks = models.IntegerField()
    TimeDuration = models.IntegerField()
    PosMarks = models.IntegerField()
    NegMarks = models.IntegerField()
    InputTextFile = models.FileField(upload_to=content_file_name)
    validators[FileExtensionValidator(allowed_extensions['txt'])],blank=False)

    def __str__(self):
        return self.TestName

更新 - 关于使用用户名作为文件夹名来保存上传的文件

如果您想将 用户名 添加为将保存用户上传内容的子文件夹名称,按用户名添加到不同的子文件夹中。同时,您将上传者的用户名也保留在您的模型中,然后您应该将您的模型表述得更像下面这样。我在您的模型中添加了一个额外字段,即 Uploader_info。它只是在上传时获取用户名,因此上传者用户无法对其进行编辑,它只是在通过请求数据从您的用户表上传时始终给出。

在 models.py 中:

from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError

def content_file_name(instance, filename):
    return "Tests/{subfolder}/{folder}/{file}".format(subfolder=instance.Uploader_info, folder=instance.TestName, file=filename)

def validate_file_extension(value):
    if value.file.content_type != 'text/plain':
        raise ValidationError('The uploaded file must be a text file')

class TestInfo(models.Model):
    Uploader_info = models.CharField(max_length=100, editable=False, null = True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='testinfos', on_delete=models.CASCADE, null=True)
    TestName = models.CharField(max_length=255)
    MaxMarks = models.IntegerField()
    TimeDuration = models.IntegerField()
    PosMarks = models.IntegerField()
    NegMarks = models.IntegerField()
    InputTextFile = models.FileField(upload_to=content_file_name, blank=False, validators=[validate_file_extension])        

    def __str__(self):
        template = '{0.TestName} {0.Uploader_info}'
        return template.format(self)

别忘了迁移。

重要!在 admin.py 中注册模型,添加一个简短的功能,将上传者的用户名提供给记录:

在 admin.py 中:

from .models import TestInfo

class TestInfoAdmin(admin.ModelAdmin):

    def save_model(self, request, obj, form, change):
        if not change:
            obj.Uploader_info = request.user.username
        obj.save()

admin.site.register(TestInfo, TestInfoAdmin)

对于表单提交,您当前的视图名称是 post,必须重新表述如下:

视图中,py

@login_required
def post(request):
    if request.method == 'POST':
        # create a form instance and populate it with data from the request:
        form = TestForm(request.POST, request.FILES)
        # check whether it's valid:
        if form.is_valid():
            fulltest = form.save(commit=False)
            fulltest.user = request.user
            fulltest.Uploader_info = request.user
            TestName = form.cleaned_data.get('TestName')
            File = form.cleaned_data.get('InputTextFile')
            fulltest.save()
            messages.success(request, 'Test {} Posted successfully'.format(TestName))
            return redirect('Test-Making')
        else:
            parameters = {
              'form': form,                   
              'error': form.errors.as_ul()
            }
            return render(request, 'Test/post.html', parameters)

    # if a GET (or any other method) we'll create a blank form
    else:
        form = TestForm()
        return render(request, 'Test/post.html', {'form': form})

forms.py 中的表单很简单:

class TestForm(forms.ModelForm):
    class Meta:
        model = TestInfo
        fields = ('TestName', 'MaxMarks', 'TimeDuration', 'PosMarks', 'NegMarks', 'InputTextFile')

就是这样。如果您的表格没问题,那么上面的内容将在我成功测试时起作用。

【讨论】:

  • 谢谢!它就像一个魅力!如果我想要当前用户登录的用户名代替“测试”怎么办?即路径:用户名/TestName/文件名
  • @Kiran - 只是有点棘手。只有稍后或明天,如果您不解决该问题,我将有时间对此进行更新。解决这个问题的方法很少。
  • @Kiran,我用代码的用户名子文件夹版本更新了我的答案。我希望它也对你有用,因为它对我有用。保重,我的朋友!
  • 我已尝试实施您的解决方案。由于某种原因,Uploader_info 的值始终等于 None。可能是什么原因?
  • @Kiran - 我更新了我的答案。我在模型中添加了一个用户字段,并重新构造了您的视图以获取提交表单的用户信息和用户 ID。所以请使用更新的模型和视图并给我一些反馈。我再次对此进行了测试,现在它也可以从前端提交中使用。
猜你喜欢
  • 2020-02-05
  • 1970-01-01
  • 2020-10-27
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-22
  • 2022-08-21
相关资源
最近更新 更多