Django:将用户上传保存在单独的文件夹中

时间:2015-12-12 12:33:34

标签: python django upload models

我希望个人用户能够将他们的文件上传到一个文件夹中(因此每个用户都有自己的根文件夹,他们可以上传自己的文件),但我不确定实施的最佳方式此

我最初计划将用户电子邮件用作其文件夹名称,并且所有上传内容都将保存在此文件夹中。但是,根据我收集的内容,检索此信息的唯一方法是通过请求函数,我无法设法将一个请求实例添加到models.py文件中,因此无法将其添加到我的'upload_to'目录中。 / p>

如何分离用户文件或如何在模型文件中获取请求实例的任何其他想法将非常感谢!!

这是我目前的模特:

def user_directory_path(instance, filename):
    return 'user_{0}/{1}'.format(instance.user.id, filename)

class UploadModel(models.Model):
    user = models.OneToOneField(User)
    file = models.FileField(upload_to=user_directory_path)

这是相关的错误:

Exception Value: UploadModel has no user.

6 个答案:

答案 0 :(得分:6)

  1. 我建议您不要使用用户电子邮件或任何其他可以更新为文件夹名称的信息,因为每次更改电子邮件或用户名时您都不会更改文件夹名称。因此,请使用唯一且不可更改的用户ID。

  2. 以下是Django文档的完整示例,用于访问模型中的实例信息以构建具有用户ID的路​​径:

  3. def user_directory_path(instance, filename):
        # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
        return 'user_{0}/{1}'.format(instance.user.id, filename)
    
    class MyModel(models.Model):
        upload = models.FileField(upload_to=user_directory_path)
    

    在这种情况下,它使用文件夹名称中的用户ID。当然,您可以将FileField替换为ImageField

    django docs中的更多信息:FileFields.upload_to

答案 1 :(得分:3)

你可以用他们的用户名分隔文件夹吗?您可以使用用户用户名创建一个创建文件夹的功能,如下所示:

def get_user_image_folder(instance, filename):
    return "%s/%s" %(instance.user.username, filename)

在您的模型中,您可以轻松使用upload_to并将刚刚创建的函数添加到其中:

class Images(models.Model):
   user = models.ForeignKey(User)
   image = models.ImageField(upload_to=get_user_image_folder,
                                  verbose_name='Image', )

您不必在模型中使用request,而是使用instance

答案 2 :(得分:0)

在views.py中,您必须像这样传递实例参数:

def post(self, request, *args, **kwargs):
    if 'uploadFile' in request.POST:
        f = UploadFileForm(request.POST, request.FILES, instance=request.user.uploadmodel)
        if f.is_valid():
            f.save()
            return HttpResponseRedirect('/sucess_url')

你的forms.py

from django import forms

from .models import UploadForm


class UploadFileForm(forms.ModelForm):
    class Meta:
        model = UploadForm
        fields = ('file',)

答案 3 :(得分:0)

为了实现这一点,我根据Louis Barranqueiro建议的文档实施了解决方案,模型看起来像:

# models.py
def user_directory_path(instance, filename):
    return 'user_{0}/{1}'.format(instance.user.id, filename)

class Document(models.Model):
    file = models.FileField(upload_to=user_directory_path)
    uploaded_at = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='documents')

但至关重要的是,我还更改了我的DocumentUploadView类以包含一个保存步骤,以便使用user属性保存文档(另请注意初始commit = False save步骤,这一点至关重要):

# views.py
class DocumentUploadView(View):

    def get(self, request):
        documents_list = Document.objects.all()
        return render(self.request, 'file_upload.html', {'documents': documents_list})

    def post(self, request):
        form = DocumentForm(self.request.POST, self.request.FILES)
        if form.is_valid():
            document = form.save(commit=False)
            document.user = request.user
            document.save()
            data = {'is_valid': True, 'name': document.file.name, 'url': document.file.url}
        else:
            data = {'is_valid': False}
        return JsonResponse(data)

最后我的forms.py看起来像这样:

# forms.py
class DocumentForm(forms.ModelForm):
    class Meta:
        model = Document
    fields = ('file',)

答案 4 :(得分:0)

我也面临着同样的问题。这是我解决的方法。我们必须在视图中创建用户引用。

下面是 models.py

的代码
def user_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    return 'user_{0}/{1}'.format(instance.user.id, filename)

class Document(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
    docfile = models.FileField(upload_to=user_directory_path)
    date = models.DateTimeField(auto_now_add=True, blank=True)

还按如下所示更新views.py中的代码:

def upload(request):
    # Handle file upload
    if request.method == 'POST':
        form = DocumentForm(request.POST, request.FILES)
        if form.is_valid():
            newdoc = Document(docfile=request.FILES['docfile'],user=request.user)
            newdoc.save()
            latest_documents = Document.objects.all().order_by('-id')[0]

            # Redirect to the document list after POST
            return HttpResponseRedirect(reverse('list'))
    else:
        form = DocumentForm()  # A empty, unbound form

    # Load documents for the list page
    documents = Document.objects.filter(user=request.user)

最重要的是一行

newdoc = Document(docfile=request.FILES['docfile'],user=request.user)

以某种方式,我无法获得模型实例来读取用户。这种方法对我有用。

答案 5 :(得分:0)

对于以后遇到此问题的其他任何人,我都可以通过将用户对象添加到视图中的模型中来访问当前用户的ID。

views.py

from .models import Document

if request.method == 'POST':
    form = DocumentForm(request.POST, request.FILES)
    if form.is_valid():
        newdoc = Document(docfile=request.FILES['docfile'])
        newdoc.owner = request.user
        newdoc.save()

然后,您可以在models.py中从先前在视图中创建的所有者中检索ID。

def user_directory_path(instance, filename):
    return 'Users/user_{0}/{1}'.format(instance.owner.id, filename)


class Document(models.Model):
    docfile = models.FileField(upload_to=user_directory_path)