Django 动态文件字段 upload_to
Django dynamic FileField upload_to
我正在尝试为 FileField 模型创建动态上传路径。因此,当用户上传文件时,Django 将其存储到我的计算机 /media/(username)/(path_to_a_file)/(filename)。
例如/media/Michael/Homeworks/Math/Week_1/questions.pdf 或 /media/Ernie/Fishing/Atlantic_ocean/Good_fishing_spots.txt
VIEWS
@login_required
def add_file(request, **kwargs):
if request.method == 'POST':
form = AddFile(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.parent = Directory.objects.get(directory_path=str(kwargs['directory_path']))
post.file_path = str(kwargs['directory_path'])
post.file_content = request.FILES['file_content'] <-- need to pass dynamic file_path here
post.save()
return redirect('/home/' + str(post.author))
MODELS
class File(models.Model):
parent = models.ForeignKey(Directory, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
file_name = models.CharField(max_length=100)
file_path = models.CharField(max_length=900)
file_content = models.FileField(upload_to='e.g. /username/PATH/PATH/..../')
FORMS
class AddFile(forms.ModelForm):
class Meta:
model = File
fields = ['file_name', 'file_content']
我找到的是这个,但是经过反复试验我没有找到方法。所以 "upload/..." 将是 post.file_path,这是动态的。
def get_upload_to(instance, filename):
return 'upload/%d/%s' % (instance.profile, filename)
class Upload(models.Model):
file = models.FileField(upload_to=get_upload_to)
profile = models.ForeignKey(Profile, blank=True, null=True)
你可以使用这样的东西(我在我的项目中使用过):
import os
def get_upload_path(instance, filename):
return os.path.join(
"user_%d" % instance.owner.id, "car_%s" % instance.slug, filename)
现在:
photo = models.ImageField(upload_to=get_upload_path)
因为 file_path
是 File
模型的一个属性,你能不能构建完整的路径,像这样:
import os
def create_path(instance, filename):
return os.path.join(
instance.author.username,
instance.file_path,
filename
)
然后从您的 File
模型中引用它:
class File(models.Model):
...
file_content = models.FileField(upload_to=create_path)
其他答案完美无缺;但是,我想指出源代码中允许此类功能的那一行。可以在Django的源代码中查看函数,generate_filename
,here。
让奇迹发生的台词:
if callable(self.upload_to):
filename = self.upload_to(instance, filename)
当你传递一个callable
给upload_to
参数时,Django会调用callable
来生成路径。请注意,Django 期望您的 callable
处理两个参数:
instance
- 包含
FileField
/ImageField
的模型
filename
- 上传文件的名称,包括扩展名(.png、.pdf、...)
另请注意,Python 不会强制您的 callable
的参数完全是 'instance' 和 'filename',因为 Django 将它们作为位置参数传递。例如,我更喜欢重命名它们:
def get_file_path(obj, fname):
return os.path.join(
'products',
obj.slug,
fname,
)
然后像这样使用它:
image = models.ImageField(upload_to=get_file_path)
我正在尝试为 FileField 模型创建动态上传路径。因此,当用户上传文件时,Django 将其存储到我的计算机 /media/(username)/(path_to_a_file)/(filename)。
例如/media/Michael/Homeworks/Math/Week_1/questions.pdf 或 /media/Ernie/Fishing/Atlantic_ocean/Good_fishing_spots.txt
VIEWS
@login_required
def add_file(request, **kwargs):
if request.method == 'POST':
form = AddFile(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.parent = Directory.objects.get(directory_path=str(kwargs['directory_path']))
post.file_path = str(kwargs['directory_path'])
post.file_content = request.FILES['file_content'] <-- need to pass dynamic file_path here
post.save()
return redirect('/home/' + str(post.author))
MODELS
class File(models.Model):
parent = models.ForeignKey(Directory, on_delete=models.CASCADE)
author = models.ForeignKey(User, on_delete=models.CASCADE)
file_name = models.CharField(max_length=100)
file_path = models.CharField(max_length=900)
file_content = models.FileField(upload_to='e.g. /username/PATH/PATH/..../')
FORMS
class AddFile(forms.ModelForm):
class Meta:
model = File
fields = ['file_name', 'file_content']
我找到的是这个,但是经过反复试验我没有找到方法。所以 "upload/..." 将是 post.file_path,这是动态的。
def get_upload_to(instance, filename):
return 'upload/%d/%s' % (instance.profile, filename)
class Upload(models.Model):
file = models.FileField(upload_to=get_upload_to)
profile = models.ForeignKey(Profile, blank=True, null=True)
你可以使用这样的东西(我在我的项目中使用过):
import os
def get_upload_path(instance, filename):
return os.path.join(
"user_%d" % instance.owner.id, "car_%s" % instance.slug, filename)
现在:
photo = models.ImageField(upload_to=get_upload_path)
因为 file_path
是 File
模型的一个属性,你能不能构建完整的路径,像这样:
import os
def create_path(instance, filename):
return os.path.join(
instance.author.username,
instance.file_path,
filename
)
然后从您的 File
模型中引用它:
class File(models.Model):
...
file_content = models.FileField(upload_to=create_path)
其他答案完美无缺;但是,我想指出源代码中允许此类功能的那一行。可以在Django的源代码中查看函数,generate_filename
,here。
让奇迹发生的台词:
if callable(self.upload_to):
filename = self.upload_to(instance, filename)
当你传递一个callable
给upload_to
参数时,Django会调用callable
来生成路径。请注意,Django 期望您的 callable
处理两个参数:
instance
- 包含
FileField
/ImageField
的模型
- 包含
filename
- 上传文件的名称,包括扩展名(.png、.pdf、...)
另请注意,Python 不会强制您的 callable
的参数完全是 'instance' 和 'filename',因为 Django 将它们作为位置参数传递。例如,我更喜欢重命名它们:
def get_file_path(obj, fname):
return os.path.join(
'products',
obj.slug,
fname,
)
然后像这样使用它:
image = models.ImageField(upload_to=get_file_path)