Динамический вопрос FilePathField
У меня есть модель, в которой местоположение каталога pdf, на которое я указываю с помощью моего FilePathField, основано на полях "client" и "job_number".
class CCEntry(models.Model):
client = models.CharField(default="C_Comm", max_length=64)
job_number = models.CharField(max_length=30, unique=False, blank=False, null=False)
filename = models.CharField(max_length=64, unique=False, blank=True, null=True)
pdf = models.FilePathField(path="site_media/jobs/%s %s", match=".*\.pdf$", recursive=True
@property
def pdf(self):
return "site_media/jobs/%s %s" % (self.client, self.job_number)
def __unicode__ (self):
return u'%s %s' % (self.client, self.filename)
class Admin:
pass
Я попытался передать данные client и job_number в поле pdf динамически, используя метод @property в классе модели, но мой подход или мой синтаксис неверны, поскольку все поле pdf исчезает в админке. Есть указания на то, что я делаю не так?
4 ответа
Попробуйте установить значение пути как вызываемую функцию
def get_path(instance, filename):
return "site_media/jobs/%s_%s/%s" % (instance.client, instance.job_number, filename)
class CCEntry(models.Model):
....
pdf = models.FilePathField(path=get_path, match=".*\.pdf$", recursive=True)
но я не уверен, что это работает, я не проверял это.
Исходя из вашего последующего поста о схожей функциональности в FileField (см. Последнюю ссылку ниже) и моей неспособности заставить что-либо из перечисленного работать, я рискну предположить, что это пока невозможно FilePathField
тип поля.
Я знаю, что передача вызываемого объекта работает для большинства параметров по умолчанию для полей... https://docs.djangoproject.com/en/dev/ref/models/fields/... так как это работает для upload_to
параметр FieldField
(eg https://stackru.com/questions/10643889/dynamic-upload-field-arguments/ ) and
ImageField` (например, Django - передача дополнительных аргументов в вызываемую функцию upload_to)
Тот, кто заинтересован в расширении FilePathField
включить эту функцию?
Кто-нибудь заинтересован в расширении FilePathField для включения этой функции?
Я хотел бы видеть это расширение!
Просто для справки, это решение, которое работало для меня (django 1.3):
# models.py
class Analysis(models.Model):
run = models.ForeignKey(SampleRun)
# Directory name depends on the foreign key
# (directory was created outside Django and gets filled by a script)
bam_file = models.FilePathField(max_length=500, blank=True, null=True)
# admin.py
class CustomAnalysisModelForm(forms.ModelForm):
class Meta:
model = Analysis
def __init__(self, *args, **kwargs):
super(CustomAnalysisModelForm, self).__init__(*args, **kwargs)
# This is an update
if self.instance.id:
# set dynamic path
mypath = settings.DATA_PATH + self.instance.run.sample.name
self.fields['bam_file'] = forms.FilePathField(path=mypath, match=".*bam$", recursive=True)
class AnalysisAdmin(admin.ModelAdmin):
form = CustomAnalysisModelForm
Надеюсь, это поможет кому-то там.
Добавлена реализация этого на основе реализации FilePathField в Django v1.9:
from django.db.models import FilePathField
class DynamicFilePathField(FilePathField):
def __init__(self, verbose_name=None, name=None, path='', match=None,
recursive=False, allow_files=True, allow_folders=False, **kwargs):
self.path, self.match, self.recursive = path, match, recursive
if callable(self.path):
self.pathfunc, self.path = self.path, self.path()
self.allow_files, self.allow_folders = allow_files, allow_folders
kwargs['max_length'] = kwargs.get('max_length', 100)
super(FilePathField, self).__init__(verbose_name, name, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(FilePathField, self).deconstruct()
if hasattr(self, "pathfunc"):
kwargs['path'] = self.pathfunc
return name, path, args, kwargs
И пример использования:
import os
from django.db import models
def get_data_path():
return os.path.abspath(os.path.join(os.path.dirname(__file__), 'data'))
class GenomeAssembly(models.Model):
name = models.CharField(
unique=True,
max_length=32)
chromosome_size_file = DynamicFilePathField(
unique=True,
max_length=128,
path=get_data_path,
recursive=False)