1

pyramid_simpleformは、 bind(model)を使用して、フォームの値をモデルの値に簡単に変換できることを示しています。

(以下、pyramid_simpleform のドキュメントから)

def add(self):
  form = Form(request,
              defaults={"name" : "..."},
              schema=MyModelSchema)

  if form.validate():
    obj = form.bind(MyModel())
    # persist model somewhere...
    return HTTPFound(location="/")

  return dict(renderer=FormRenderer(form))

変形ドキュメントのどこにも同等の方法が見つかりません...または変形でこれを行う方法はありますか?

4

2 に答える 2

4

Deform はスキーマをモデルに直接バインドすることをサポートしていませんが、sqlalchemy を使用する場合、ColanderAlchemyはまさにそれを行います。これは、sqlalchemy モデルから水切りスキーマ (変形によって使用される) を生成し、フォームをモデルにバインドします。

于 2012-11-21T08:31:16.330 に答える
0

これは、閲覧専用フォームと編集フォームの両方を含む、150 行の回答です。最も単純なユースケースでは不必要に複雑かもしれませんが、それが機能するようになるまでには時間がかかりました.

class FormView:
    """A base class for views which utilize ColanderAlchemy to view/edit SQLAlchemy model instances."""

    #: If the child class is not overriding the rendering loop, point this to a template which provides the page frame and ``crud_content`` block.
    base_template = None

    #: List of SQLAlchemy and JSONProperty field names automatically mapped to a form
    includes = ["id",]

    def __init__(self, context, request):
        self.context = context
        self.request = request

    def create_form(self, buttons=()):
        """Automatically create a read-only collander schema + deform form based on the underlying SQLALchemy model.

        :param buttons: Passed to Deform as form buttons
        """
        obj = self.get_object()
        includes = self.includes
        schema = PropertyAwareSQLAlchemySchemaNode(obj.__class__, includes=includes)
        self.customize_schema(schema)
        schema = self.bind_schema(schema)
        form = deform.Form(schema, buttons=buttons)
        return form

    def bind_schema(self, schema):
        """Initialize Colander field dynamic default values. By default, don't do anything."""
        return schema

    def get_crud(self):
        """Get CRUD manager object for this view."""
        return self.context.__parent__

    def get_object(self):
        """Get underlying SQLAlchemy model instance from current Pyramid traversing context."""
        return self.context.get_object()

    def get_title(self):
        """Get human-readable title for for template page title."""
        return "#{}".format(self.get_object().id)

    def customize_schema(self, schema):
        """After Colander schema is automatically generated from the SQLAlchemy model, edit it in-place for fine-tuning.

        Override this in your view subclass for schema customizations.
        """
        return



class Show(FormView):
    """Read-only view to SQLAlchemy model instance using Deform form generated by ColanderAlchemy.
    """

    def get_title(self):
        return "#{}".format(self.get_object().id)

    @view_config(context=sqlalchemy.Resource, name="show", renderer="crud/show.html", permission='view')
    def show(self):
        """View for showing an individual object."""

        obj = self.context.get_object()
        base_template = self.base_template

        form = self.create_form()
        appstruct = form.schema.dictify(obj)
        rendered_form = form.render(appstruct, readonly=True)

        crud = self.get_crud()

        resource_buttons = dict(edit=self.request.resource_url(self.context, "edit"), delete=False)

        title = current_view_name = self.get_title()

        return dict(form=rendered_form, context=self.context, obj=obj, title=title, crud=crud, base_template=base_template, resource_buttons=resource_buttons)


class Edit(FormView):
    """Edit SQLAlchemy model instance using Deform form generated by ColanderAlchemy.
    """

    # We display id field on the edit form and it needs special handling, because it is read-only
    # See http://deformdemo.repoze.org/readonly_value_nonvalidation/
    includes = [
        colander.SchemaNode(colander.String(),
            name="id",
            missing=lambda node, kw: kw["obj"].id,
            widget=deform.widget.TextInputWidget(readonly=True),
        )
    ]

    def get_title(self):
        return "Editing #{}".format(self.get_object().id)

    def create_form(self):
        return super(Edit, self).create_form(buttons=("save", "cancel",))

    def bind_schema(self, schema):
        return schema.bind(obj=self.context.get_object())

    @view_config(context=sqlalchemy.Resource, name="edit", renderer="crud/edit.html", permission='edit')
    def edit(self):
        """View for showing an individual object."""

        # SQLAlchemy model instance
        obj = self.context.get_object()
        base_template = self.base_template

        # Create form, convert instance to Colander structure for Deform
        form = self.create_form()

        crud = self.get_crud()

        resource_buttons = dict(show=self.request.resource_url(self.context, "show"), delete=False)

        title = current_view_name = self.get_title()

        if "save" in self.request.POST:

            controls = self.request.POST.items()

            try:
                appstruct = form.validate(controls)

                # Cannot update id, as it is read-only
                del appstruct["id"]

                form.schema.objectify(appstruct, obj)

                # We do not need to explicitly call save() or commit() as we are using Zope transaction manager

                messages.add(self.request, kind="success", msg="Changes saved.")

                # Redirect back to view page after edit page has succeeded
                return HTTPFound(self.request.resource_url(self.context, "show"))

            except deform.ValidationFailure as e:
                # Whoops, bad things happened, render form with validation errors
                rendered_form = e.render()

        elif "cancel" in self.request.POST:
            # User pressed cancel
            return HTTPFound(self.request.resource_url(self.context, "show"))
        else:
            # Render initial form view with populated values
            appstruct = form.schema.dictify(obj)
            rendered_form = form.render(appstruct)

        return dict(form=rendered_form, context=self.context, obj=obj, title=title, crud=crud, base_template=base_template, resource_buttons=resource_buttons)
于 2015-05-04T17:58:42.670 に答える