Default value for a Dexterity Named Blob File Field?

Hi everyone,

is it possible to provide a default file for a Dexterity Named Blob File Field?

I tried the following with some partial success:

from plone.autoform import directives
from plone.formwidget.namedfile.widget import NamedFileFieldWidget
from plone.namedfile.field import NamedBlobFile as NamedBlobFileField
from zope.interface import provider
from zope.schema.interfaces import IContextAwareDefaultFactory

def defaultParameterFileFactory(filename):
    cwd = os.path.dirname(__file__)
    filepath = os.path.join(cwd, "..", "data", filename)
    data = open(filepath, "rb").read()
    blob = NamedBlobFile(data=data, filename=filename)

    @provider(IContextAwareDefaultFactory)
    def factory(context):
        return blob

    return factory

class IDataInterfaceSchema(model.Schema):
    directives.widget("parameters", NamedFileFieldWidget)
    parameters = NamedBlobFileField(
        title=_(u"Parameters"),
        description=_(u"Please upload the Parameters Excel"),
        required=False,
        defaultFactory=defaultParameterFileFactory(u"ld2328_twcvua_parameter.xlsx"),
    )

The file is referenced after creation, but with a size of 0 KB:

Also the downloaded file has a size of 0 and can not be opened.

Then I tried to provide it in the update of a custom Add-View:

import os

from plone.namedfile.file import NamedBlobFile
from plone.dexterity.browser.add import DefaultAddForm
from plone.dexterity.browser.add import DefaultAddView

def get_parameter_file(filename):
    cwd = os.path.dirname(__file__)
    filepath = os.path.join(cwd, "../../..", "data", filename)
    data = open(filepath, "rb").read()
    return NamedBlobFile(data=data, filename=filename)

class AddForm(DefaultAddForm):

    def get_widget(self, name, default=None):
        """Lookup a widget by name in the current form
        """
        if name in self.widgets.keys():
            return self.widgets[name]
        for group in self.groups:
            if name in group.widgets.keys():
                return group.widgets[name]
        return default

    def update(self):
        super(AddForm, self).update()

        parameters_file = get_parameter_file(u"ld2328_twcvua_parameter.xlsx")
        parameters_widget = self.get_widget("parameters")
        # Workaround to display the filename in the widget template
        parameters_widget.ignoreContext = False
        parameters_widget.value = parameters_file
        ...

Which seems to work nice in the add form, especially because the user can see the default file immediately:

However, no file is uploaded in this case:

Finally, I tried to provide the file directly as the default value in the schema and not the defaultFactory. But there I get again files with 0 KB of size in my content type.

Any further ideas?

Thanks and best regards
Ramon

Hi everyone,

I just wanted to share what we ended up with, in case anyone else has a similar requirement.

We injected the files now into the data dictionary in the createAndAdd method of the custom AddForm from above:


class AddForm(DefaultAddForm):

    def createAndAdd(self, data):
        # provide default parameter files
        if data.get("parameters") is None:
            data["parameters"] = get_parameter_file(
                u"ld2328_twcvua_parameter.xlsx")
        if data.get("procedures") is None:
            data["procedures"] = get_parameter_file(
                u"ld2328_twcvua_verfahren.xlsx")
        if data.get("dimensions") is None:
            data["dimensions"] = get_parameter_file(
                u"ld2328_twcvua_dimension.xlsx")

        obj = super(AddForm, self).createAndAdd(data)
        return obj

This seems to work for now, but has the downside, that the fields obviously can not be marked as required to allow to send the form w/o files uploaded.

Ramon

Off topic, probably, but I see that this is how I read a file (image) with plone.api, looks similar but I see that I add the image 'later'. ( I add several image, so in my code I actually use 'load_image('some:name') )

wf_image = plone.api.content.create(
                    type='Image',
                    container=some_folder,
                    id='my_id',
                    title=wf_name,
                    
                )
wf_image.image = load_image()


def load_image():
    filename = os.path.join(os.path.dirname(__file__), 'img', 'blank.png')
    with open(filename, 'rb') as image_file:
        return NamedBlobImage(
            data=image_file.read(),
            filename='dummy.png'
        )