Haikson

[ Everything is possible. Everything takes time. ]

Расширенный Django DirectoryPathField

В прошлый раз я выкладывал пример создания класса, который рекурсивно выводил список директорий. Конечно же там были ограничения. Вот здесь новые классы, которые помогут полностью реализовать функционал старого FilePathField применительно к директориям. Не знаю, почему в django до сих пор не добавят ?
from django.forms import fields
from django.db import models
import os, re

class DirectoryPathField(models.FilePathField):
    def __init__(self, *args, **kwargs):
        super(DirectoryPathField, self).__init__(*args, **kwargs)

    def formfield(self, **kwargs):
        defaults = {
            "path": self.path,
            "match": self.match,
            "recursive": self.recursive,
            "form_class": DirectoryPathFieldWidget,
        }
        defaults.update(kwargs)
        return super(DirectoryPathField, self).formfield(**defaults)
        kwargs["widget"] = DirectoryPathFieldWidget()

        return super(DirectoryPathField, self).formfield(**kwargs)

    def get_internal_type(self):
        return "DirectoryPathField"

class DirectoryPathFieldWidget(fields.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(DirectoryPathFieldWidget, self).__init__(choices=(), required=required,
            widget=widget, label=label, initial=initial, help_text=help_text,
            *args, **kwargs)

        if self.required:
            self.choices = []
        else:
            self.choices = [("", "---------")]

        if self.match is not None:
            self.match_re = re.compile(self.match)

        if recursive:
            for root, dirs, files in sorted(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("\\", "/")))
        else:
            try:
                for f in sorted(os.listdir(self.path)):
                    full_file = os.path.join(self.path, f)
                    if os.path.isdir(full_file) and (self.match is None or self.match_re.search(f)):
                        self.choices.append((full_file, f))
            except OSError:
                pass

        self.widget.choices = sorted(self.choices, key=lambda title: title[1])