Как загрузить начальное значение для ClearableFileInput / FileField (до привязки формы) - PullRequest
2 голосов
/ 30 мая 2020

Как мне установить начальное значение для FileField, которое будет отображаться в виджете ClearableFileInput при создании нового объекта (несвязанная форма)?

Я пробовал следующее, но widget.value не возвращает FeildFile экземпляр, если это первый раз, когда пользователь создает объект:

models.py

class MyModel(models.Model):
    myfile=models.FileField()

forms.py

class MyForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['myfile'].initial= 'myfile.pdf'

    class Meta:
        model = Issuer
        fields = ['myfile']

Это приводит к:

enter image description here

Точно так же установка значения по умолчанию в поле модели не работает:

class MyModel(models.Model):
    myfile=models.FileField(default='myfile.pdf')

Исходное значение виджета все еще None, но если оставить его пустым и сохранить, будет создан файловый объект myfile.pdf . settings.MEDIA_URL и urls.py определенно верны, и файл находится в системе, потому что он загружается после сохранения формы.

Чего мне не хватает, так это показа его в качестве начального значения перед сохранением формы и созданием объекта.

Этот ответ предполагает, что вы не можете предоставить начальные данные, но вы можете указать начальное значение с атрибутом url, чтобы имитировать внешний вид файла. Однако неясно, как вы это сделаете.

Попытка создать начальный файловый объект в форме также возвращает widget.value = None

class MyForm(forms.ModelForm):

    f_path = os.path.join(settings.BASE_DIR + settings.MEDIA_URL, 'myfile.pdf')

    f = open(f_path)
    myfile = File(f)

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['privacy_policy'].initial = self.myfile

Ответы [ 3 ]

0 голосов
/ 08 июня 2020

Из Django Документация

FileField.upload_to

Этот атрибут позволяет настроить загрузку каталог и имя файла , и можно установить двумя способами. В обоих случаях значение передается методу Storage.save ().

Если вы указываете строковое значение или путь, оно может содержать форматирование strftime (), которое будет заменено датой / временем загрузки файла (чтобы загруженные файлы не заполняли заданный каталог). Например:

class MyModel(models.Model):
    # file will be uploaded to MEDIA_ROOT/uploads
    upload = models.FileField(upload_to='uploads/')
    # or...
    # file will be saved to MEDIA_ROOT/uploads/2015/01/30
    upload = models.FileField(upload_to='uploads/%Y/%m/%d/')

Например, ваш MEDIA_ ROOT установлен на '/ home / media', а upload_to установлен на 'photos /% Y /% m /% d'. Часть "% Y /% m /% d" в upload_to - это форматирование strftime (); «% Y» - это год с четырьмя ди git, «% m» - с двумя ди git месяц, а «% d» - это день с двумя ди git. Если вы загрузите файл 15 января 2007 г., он будет сохранен в каталоге /home/media/photos/2007/01/15.

0 голосов
/ 08 июня 2020

Вы не можете. Единственный способ установить значение входного файла - это выбрать его пользователем. Это сделано из соображений безопасности. В противном случае вы сможете создать файл Javascript, который автоматически загружает указанный файл c с клиентского компьютера. он не имеет ничего общего с Django (модель, форма), это функция браузера, мы делаем вещи с формой Django, только если это возможно в Html и javascript.

вашей форме:

class MyForm(forms.ModelForm):

f_path = os.path.join(settings.BASE_DIR + settings.MEDIA_URL, 'myfile.pdf')

f = open(f_path)
myfile = File(f)

def __init__(self, *args, **kwargs):
    super(MyForm, self).__init__(*args, **kwargs)
    self.fields['privacy_policy'].value = self.myfile

шаблон ClearableFileField по умолчанию:

{% if widget.is_initial %}{{ widget.initial_text }}: <a href="{{ widget.value.url }}">{{ widget.value }}</a>{% if not widget.required %}
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}">
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>{% endif %}<br>
{{ widget.input_text }}:{% endif %}
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>

Виджет is_initial должен быть истинным, чтобы увидеть ссылку.

class ClearableFileInput(FileInput):
    ...

    def is_initial(self, value):
        """
        Return whether value is considered to be initial value.
        """
        return bool(value and getattr(value, 'url', False))

     ....
0 голосов
/ 02 июня 2020

Ваш последний блок кода довольно близок.

Фактически вы говорите пользователю через виджет ClearableFileInput, что, если пользователь ничего не вводит во ввод файла, начальным значением будет ваш pdf

Но , это только для отображения, вы должны фактически поместить logi c при сохранении экземпляра! (FileField не сделает этого за вас). Итак, правильнее всего переопределить метод save() вашей формы, а в случае создания поместить фактический файл в качестве значения. Как это:

class MyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        path = os.path.join(settings.MEDIA_ROOT, 'myfile.pdf')

        self.default_file = open(path)

        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['privacy_policy'].initial = File(self.default_file)
        self.fields['privacy_policy'].initial.url = default_storage.url('myfile.pdf')

    def save(self, commit=True):
        # Actually put the default file as a value if no input for creation
        if not self.instance.pk and not self.cleaned_data.get('privacy_policy'):
            self.instance.privacy_policy = self.default_file
            self.instance.privacy_policy._committed = True
        super().save(commit)
...