Сегодня встала проблема создания поля со списком директорий. К сожалению стандартные поля не позволяют решать данную задачу, или позволяют, но я этого не нашел. Пришлось писать самому. К счастью изобретение велосипедов не является моим хобби. Поэтому за основу взял код класса FilePathField(models.Field).
Задача: передаем классу параметр path при инициализации и на выходе получаем рекурсивный список директорий, находящихся в path.
Всё делается предельно просто: создаю пакет cff (custom forms and fields) и заливаем туда два модуля
- formfields.py
- dbfields.py
Форма, для отображения данных (в нашем случае списка директорий):
# formfields.py
from mysite import settings
import os
from django import forms
class ImagesDirField(forms.ChoiceField):
def __init__(self, path, match=None, recursive=False, required=True,
widget=None, label=None, initial=None, help_text=None,
*args, **kwargs):
self.path, self.match, self.recursive = path, match, recursive
super(ImagesDirField, self).__init__(choices=(), required=required,
widget=widget, label=label, initial=initial, help_text=help_text,
*args, **kwargs)
self.choices.append(("", ""),)
for root, dirs, files in os.walk(self.path):
for f in dirs:
if self.match is None or self.match_re.search(f):
f = os.path.join(root, f)
self.choices.append((f, f.replace(path, "", 1).replace("\\", "/"))) # Delete path and replace winbackslashes
self.widget.choices = self.choices
Поле для модели :-)
# dbfields.py
from django.db import models
from mysite.cff import formfields
class ImagesPathField(models.Field):
description = "Field Gets Paths List for Images"
def __init__(self, verbose_name=None, name=None, path="", match=None, recursive=False, **kwargs):
self.path, self.match, self.recursive = path, match, recursive
kwargs["max_length"] = kwargs.get("max_length", 100)
models.Field.__init__(self, verbose_name, name, **kwargs)
def formfield(self, **kwargs):
defaults = {
"path": self.path,
"match": self.match,
"recursive": self.recursive,
"form_class": formfields.ImagesDirField,
}
defaults.update(kwargs)
return super(ImagesPathField, self).formfield(**defaults)
def get_internal_type(self):
return "ImagesPathField"
Использование:
from mysite.cff import dbfields
class Directories(models.Model):
directory = dbfields.ImagesPathField(path = ("%s/img/" % (settings.MEDIA_ROOT)))