Warning

Starting from CubicWeb version 4.0 all code related to generating html views has been moved to the Cube cubicweb_web.

If you want to migrate a project from 3.38 to 4.* while still using all the html views you need to both install the cubicweb_web cube AND add it to your dependencies and run add_cube('web').

cubicweb_web can be installed from pypi this way:

pip install cubicweb_web

We don’t plan to maintain the features in cubicweb_web in the long run; we are moving to a full javascript frontend using both cubicweb_api (which exposes a HTTP API) and @cubicweb/client as a frontend javascript toolkit.

In the long run cubicweb_api will be merged inside of CubicWeb.

HTML form construction#

CubicWeb provides the somewhat usual form / field / widget / renderer abstraction to provide generic building blocks which will greatly help you in building forms properly integrated with CubicWeb (coherent display, error handling, etc…), while keeping things as flexible as possible.

A form basically only holds a set of fields, and has te be bound to a renderer which is responsible to layout them. Each field is bound to a widget that will be used to fill in value(s) for that field (at form generation time) and ‘decode’ (fetch and give a proper Python type to) values sent back by the browser.

The field should be used according to the type of what you want to edit. E.g. if you want to edit some date, you’ll have to use the cubicweb_web.formfields.DateField. Then you can choose among multiple widgets to edit it, for instance cubicweb_web.formwidgets.TextInput (a bare text field), DateTimePicker (a simple calendar) or even JQueryDatePicker (the JQuery calendar). You can of course also write your own widget.

Exploring the available forms#

A small excursion into a CubicWeb shell is the quickest way to discover available forms (or application objects in general).

>>> from pprint import pprint
>>> pprint( session.vreg['forms'] )
{'base': [<class 'cubicweb_web.views.forms.FieldsForm'>,
          <class 'cubicweb_web.views.forms.EntityFieldsForm'>],
 'changestate': [<class 'cubicweb_web.views.workflow.ChangeStateForm'>,
                 <class 'cubicweb_tracker.views.forms.VersionChangeStateForm'>],
 'composite': [<class 'cubicweb_web.views.forms.CompositeForm'>,
               <class 'cubicweb_web.views.forms.CompositeEntityForm'>],
 'deleteconf': [<class 'cubicweb_web.views.editforms.DeleteConfForm'>],
 'edition': [<class 'cubicweb_web.views.autoform.AutomaticEntityForm'>,
             <class 'cubicweb_web.views.workflow.TransitionEditionForm'>,
             <class 'cubicweb_web.views.workflow.StateEditionForm'>],
 'logform': [<class 'cubicweb_web.views.basetemplates.LogForm'>],
 'massmailing': [<class 'cubicweb_web.views.massmailing.MassMailingForm'>],
 'muledit': [<class 'cubicweb_web.views.editforms.TableEditForm'>]}

The two most important form families here (for all practical purposes) are base and edition. Most of the time one wants alterations of the AutomaticEntityForm to generate custom forms to handle edition of an entity.

The Automatic Entity Form#

class cubicweb_web.views.autoform.AutomaticEntityForm(*args, **kwargs)[source]#

AutomaticEntityForm is an automagic form to edit any entity. It is designed to be fully generated from schema but highly configurable through uicfg.

Of course, as for other forms, you can also customise it by specifying various standard form parameters on selection, overriding, or adding/removing fields in selected instances.

Configuration through uicfg#

It is possible to manage which and how an entity’s attributes and relations will be edited in the various contexts where the automatic entity form is used by using proper uicfg tags.

The details of the uicfg syntax can be found in the The uicfg module chapter.

Possible relation tags that apply to entity forms are detailled below. They are all in the cubicweb_web.uicfg module.

Attributes/relations display location#

autoform_section specifies where to display a relation in form for a given form type. tag_attribute(), tag_subject_of() and tag_object_of() methods for this relation tag expect two arguments additionally to the relation key: a formtype and a section.

formtype may be one of:

  • ‘main’, the main entity form (e.g. the one you get when creating or editing an entity)

  • ‘inlined’, the form for an entity inlined into another form

  • ‘muledit’, the table form when editing multiple entities of the same type

section may be one of:

  • ‘hidden’, don’t display (not even in a hidden input)

  • ‘attributes’, display in the attributes section

  • ‘relations’, display in the relations section, using the generic relation selector combobox (available in main form only, and not usable for attributes)

  • ‘inlined’, display target entity of the relation into an inlined form (available in main form only, and not for attributes)

By default, mandatory relations are displayed in the ‘attributes’ section, others in ‘relations’ section.

Change default fields#

Use autoform_field to replace the default field class to use for a relation or attribute. You can put either a field class or instance as value (put a class whenether it’s possible).

Warning

autoform_field_kwargs should usually be used instead of autoform_field. If you put a field instance into autoform_field, autoform_field_kwargs values for this relation will be ignored.

Customize field options#

In order to customize field options (see Field for a detailed list of options), use autoform_field_kwargs. This rtag takes a dictionary as arguments, that will be given to the field’s contructor.

You can then put in that dictionary any arguments supported by the field class. For instance:

# Change the content of the combobox. Here `ticket_done_in_choices` is a
# function which returns a list of elements to populate the combobox
autoform_field_kwargs.tag_subject_of(('Ticket', 'done_in', '*'),
                                     {'sort': False,
                                      'choices': ticket_done_in_choices})

# Force usage of a TextInput widget for the expression attribute of
# RQLExpression entities
autoform_field_kwargs.tag_attribute(('RQLExpression', 'expression'),
                                    {'widget': fw.TextInput})

Note

the widget argument can be either a class or an instance (the later case being convenient to pass the Widget specific initialisation options)

Overriding permissions#

The autoform_permissions_overrides rtag provides a way to by-pass security checking for dark-corner case where it can’t be verified properly.

Anatomy of a choices function#

Let’s have a look at the ticket_done_in_choices function given to the choices parameter of the relation tag that is applied to the (‘Ticket’, ‘done_in’, ‘*’) relation definition, as it is both typical and sophisticated enough. This is a code snippet from the tracker cube.

The Ticket entity type can be related to a Project and a Version, respectively through the concerns and done_in relations. When a user is about to edit a ticket, we want to fill the combo box for the done_in relation with values pertinent with respect to the context. The important context here is:

  • creation or modification (we cannot fetch values the same way in either case)

  • __linkto url parameter given in a creation context

from cubicweb_web import formfields

def ticket_done_in_choices(form, field):
    entity = form.edited_entity
    # first see if its specified by __linkto form parameters
    linkedto = form.linked_to[('done_in', 'subject')]
    if linkedto:
        return linkedto
    # it isn't, get initial values
    vocab = field.relvoc_init(form)
    veid = None
    # try to fetch the (already or pending) related version and project
    if not entity.has_eid():
        peids = form.linked_to[('concerns', 'subject')]
        peid = peids and peids[0]
    else:
        peid = entity.project.eid
        veid = entity.done_in and entity.done_in[0].eid
    if peid:
        # we can complete the vocabulary with relevant values
        rschema = form._cw.vreg.schema['done_in'].rdef('Ticket', 'Version')
        rset = form._cw.execute(
            'Any V, VN ORDERBY version_sort_value(VN) '
            'WHERE V version_of P, P eid %(p)s, V num VN, '
            'V in_state ST, NOT ST name "published"', {'p': peid}, 'p')
        vocab += [(v.view('combobox'), v.eid) for v in rset.entities()
                  if rschema.has_perm(form._cw, 'add', toeid=v.eid)
                  and v.eid != veid]
    return vocab

The first thing we have to do is fetch potential values from the __linkto url parameter that is often found in entity creation contexts (the creation action provides such a parameter with a predetermined value; for instance in this case, ticket creation could occur in the context of a Version entity). The RelationField field class provides a relvoc_linkedto() method that gets a list suitably filled with vocabulary values.

linkedto = field.relvoc_linkedto(form)
if linkedto:
    return linkedto

Then, if no __linkto argument was given, we must prepare the vocabulary with an initial empty value (because done_in is not mandatory, we must allow the user to not select a verson) and already linked values. This is done with the relvoc_init() method.

vocab = field.relvoc_init(form)

But then, we have to give more: if the ticket is related to a project, we should provide all the non published versions of this project (Version and Project can be related through the version_of relation). Conversely, if we do not know yet the project, it would not make sense to propose all existing versions as it could potentially lead to incoherences. Even if these will be caught by some RQLConstraint, it is wise not to tempt the user with error-inducing candidate values.

The “ticket is related to a project” part must be decomposed as:

  • this is a new ticket which is created is the context of a project

  • this is an already existing ticket, linked to a project (through the concerns relation)

  • there is no related project (quite unlikely given the cardinality of the concerns relation, so it can only mean that we are creating a new ticket, and a project is about to be selected but there is no __linkto argument)

Note

the last situation could happen in several ways, but of course in a polished application, the paths to ticket creation should be controlled so as to avoid a suboptimal end-user experience

Hence, we try to fetch the related project.

veid = None
if not entity.has_eid():
    peids = form.linked_to[('concerns', 'subject')]
    peid = peids and peids[0]
else:
    peid = entity.project.eid
    veid = entity.done_in and entity.done_in[0].eid

We distinguish between entity creation and entity modification using the Entity.has_eid() method, which returns False on creation. At creation time the only way to get a project is through the __linkto parameter. Notice that we fetch the version in which the ticket is done_in if any, for later.

Note

the implementation above assumes that if there is a __linkto parameter, it is only about a project. While it makes sense most of the time, it is not an absolute. Depending on how an entity creation action action url is built, several outcomes could be possible there

If the ticket is already linked to a project, fetching it is trivial. Then we add the relevant version to the initial vocabulary.

if peid:
    rschema = form._cw.vreg.schema['done_in'].rdef('Ticket', 'Version')
    rset = form._cw.execute(
        'Any V, VN ORDERBY version_sort_value(VN) '
        'WHERE V version_of P, P eid %(p)s, V num VN, '
        'V in_state ST, NOT ST name "published"', {'p': peid})
    vocab += [(v.view('combobox'), v.eid) for v in rset.entities()
              if rschema.has_perm(form._cw, 'add', toeid=v.eid)
              and v.eid != veid]

Warning

we have to defend ourselves against lack of a project eid. Given the cardinality of the concerns relation, there must be a project, but this rule can only be enforced at validation time, which will happen of course only after form subsmission

Here, given a project eid, we complete the vocabulary with all unpublished versions defined in the project (sorted by number) for which the current user is allowed to establish the relation.

Building self-posted form with custom fields/widgets#

Sometimes you want a form that is not related to entity edition. For those, you’ll have to handle form posting by yourself. Here is a complete example on how to achieve this (and more).

Imagine you want a form that selects a month period. There are no proper field/widget to handle this in CubicWeb, so let’s start by defining them:

# let's have the whole import list at the beginning, even those necessary for
# subsequent snippets
from logilab.common import date
from logilab.mtconverter import xml_escape
from cubicweb.predicates import match_kwargs
from cubicweb_web.view import View
from cubicweb_web import RequestError, ProcessFormError
from cubicweb_web import formfields as fields, formwidgets as wdgs
from cubicweb_web.views import forms, calendar

class MonthSelect(wdgs.Select):
    """Custom widget to display month and year. Expect value to be given as a
    date instance.
    """

    def format_value(self, form, field, value):
        return u'%s/%s' % (value.year, value.month)

    def process_field_data(self, form, field):
        val = super(MonthSelect, self).process_field_data(form, field)
        try:
            year, month = val.split('/')
            year = int(year)
            month = int(month)
            return date.date(year, month, 1)
        except ValueError:
            raise ProcessFormError(
                form._cw._('badly formated date string %s') % val)


class MonthPeriodField(fields.CompoundField):
    """custom field composed of two subfields, 'begin_month' and 'end_month'.

    It expects to be used on form that has 'mindate' and 'maxdate' in its
    extra arguments, telling the range of month to display.
    """

    def __init__(self, *args, **kwargs):
        kwargs.setdefault('widget', wdgs.IntervalWidget())
        super(MonthPeriodField, self).__init__(
            [fields.StringField(name='begin_month',
                                choices=self.get_range, sort=False,
                                value=self.get_mindate,
                                widget=MonthSelect()),
             fields.StringField(name='end_month',
                                choices=self.get_range, sort=False,
                                value=self.get_maxdate,
                                widget=MonthSelect())], *args, **kwargs)

    @staticmethod
    def get_range(form, field):
        mindate = date.todate(form.cw_extra_kwargs['mindate'])
        maxdate = date.todate(form.cw_extra_kwargs['maxdate'])
        assert mindate <= maxdate
        _ = form._cw._
        months = []
        while mindate <= maxdate:
            label = '%s %s' % (_(calendar.MONTHNAMES[mindate.month - 1]),
                               mindate.year)
            value = field.widget.format_value(form, field, mindate)
            months.append( (label, value) )
            mindate = date.next_month(mindate)
        return months

    @staticmethod
    def get_mindate(form, field):
        return form.cw_extra_kwargs['mindate']

    @staticmethod
    def get_maxdate(form, field):
        return form.cw_extra_kwargs['maxdate']

    def process_posted(self, form):
        for field, value in super(MonthPeriodField, self).process_posted(form):
            if field.name == 'end_month':
                value = date.last_day(value)
            yield field, value

Here we first define a widget that will be used to select the beginning and the end of the period, displaying months like ‘<month> YYYY’ but using ‘YYYY/mm’ as actual value.

We then define a field that will actually hold two fields, one for the beginning and another for the end of the period. Each subfield uses the widget we defined earlier, and the outer field itself uses the standard IntervalWidget. The field adds some logic:

  • a vocabulary generation function get_range, used to populate each sub-field

  • two ‘value’ functions get_mindate and get_maxdate, used to tell to subfields which value they should consider on form initialization

  • overriding of process_posted, called when the form is being posted, so that the end of the period is properly set to the last day of the month.

Now, we can define a very simple form:

class MonthPeriodSelectorForm(forms.FieldsForm):
    __regid__ = 'myform'
    __select__ = match_kwargs('mindate', 'maxdate')

    form_buttons = [wdgs.SubmitButton()]
    form_renderer_id = 'onerowtable'
    period = MonthPeriodField()

where we simply add our field, set a submit button and use a very simple renderer (try others!). Also we specify a selector that ensures form will have arguments necessary to our field.

Now, we need a view that will wrap the form and handle post when it occurs, simply displaying posted values in the page:

class SelfPostingForm(View):
    __regid__ = 'myformview'

    def call(self):
        mindate, maxdate = date.date(2010, 1, 1), date.date(2012, 1, 1)
        form = self._cw.vreg['forms'].select(
            'myform', self._cw, mindate=mindate, maxdate=maxdate, action='')
        try:
            posted = form.process_posted()
            self.w(u'<p>posted values %s</p>' % xml_escape(repr(posted)))
        except RequestError: # no specified period asked
            pass
        form.render(w=self.w, formvalues=self._cw.form)

Notice usage of the process_posted() method, that will return a dictionary of typed values (because they have been processed by the field). In our case, when the form is posted you should see a dictionary with ‘begin_month’ and ‘end_month’ as keys with the selected dates as value (as a python date object).

APIs#

The Field class and basic fields#

Note

Fields are used to control what’s edited in forms. They makes the link between something to edit and its display in the form. Actual display is handled by a widget associated to the field.

Let first see the base class for fields:

class cubicweb_web.formfields.Field(name=None, label=<nullobject>, widget=None, **kwargs)[source]#

This class is the abstract base class for all fields. It hold a bunch of attributes which may be used for fine control of the behaviour of a concrete field.

Attributes

All the attributes described below have sensible default value which may be overriden by named arguments given to field’s constructor.

name

base name of the field (basestring). The actual input name is returned by the input_name() method and may differ from that name (for instance if eidparam is true).

id

DOM identifier (default to the same value as name), should be unique in a form.

label

label of the field (default to the same value as name).

help

help message about this field.

widget

widget associated to the field. Each field class has a default widget class which may be overriden per instance.

value

field value. May be an actual value or a callable which should take the form and the field as argument and return a value.

choices

static vocabulary for this field. May be a list of values, a list of (label, value) tuples or a callable which should take the form and field as arguments and return a list of values or a list of (label, value).

required

bool flag telling if the field is required or not.

sort

bool flag telling if the vocabulary (either static vocabulary specified in choices or dynamic vocabulary fetched from the form) should be sorted on label.

internationalizable

bool flag telling if the vocabulary labels should be translated using the current request language.

eidparam

bool flag telling if this field is linked to a specific entity

role

when the field is linked to an entity attribute or relation, tells the role of the entity in the relation (eg ‘subject’ or ‘object’). If this is not an attribute or relation of the edited entity, role should be None.

fieldset

optional fieldset to which this field belongs to

order

key used by automatic forms to sort fields

ignore_req_params

when true, this field won’t consider value potentially specified using request’s form parameters (eg you won’t be able to specify a value using for instance url like http://mywebsite.com/form?field=value)

Generic methods

input_name(form, suffix=None)[source]#

Return the ‘qualified name’ for this field, e.g. something suitable to use as HTML input name. You can specify a suffix that will be included in the name when widget needs several inputs.

dom_id(form, suffix=None)[source]#

Return the HTML DOM identifier for this field, e.g. something suitable to use as HTML input id. You can specify a suffix that will be included in the name when widget needs several inputs.

actual_fields(form)[source]#

Fields may be composed of other fields. For instance the RichTextField is containing a format field to define the text format. This method returns actual fields that should be considered for display / edition. It usually simply return self.

Form generation methods

form_init(form)[source]#

Method called at form initialization to trigger potential field initialization requiring the form instance. Do nothing by default.

typed_value(form, load_bytes=False)[source]#

Return the correctly typed value for this field in the form context.

Post handling methods

process_posted(form)[source]#

Return an iterator on (field, value) that has been posted for field returned by actual_fields().

process_form_value(form)[source]#

Return the correctly typed value posted for this field.

Now, you usually don’t use that class but one of the concrete field classes described below, according to what you want to edit.

Basic fields#

class cubicweb_web.formfields.StringField[source]#

Use this field to edit unicode string (String yams type). This field additionally support a max_length attribute that specify a maximum size for the string (None meaning no limit).

Unless explicitly specified, the widget for this field will be:

  • Select if some vocabulary is specified using choices attribute

  • TextInput if maximum size is specified using max_length attribute and this length is inferior to 257.

  • TextArea in all other cases

class cubicweb_web.formfields.PasswordField[source]#

Use this field to edit password (Password yams type, encoded python string).

Unless explicitly specified, the widget for this field will be a PasswordInput.

class cubicweb_web.formfields.IntField[source]#

Use this field to edit integers (Int yams type). Similar to BigIntField but set max length when text input widget is used (the default).

class cubicweb_web.formfields.BigIntField[source]#

Use this field to edit big integers (BigInt yams type). This field additionally support min and max attributes that specify a minimum and/or maximum value for the integer (None meaning no boundary).

Unless explicitly specified, the widget for this field will be a TextInput.

class cubicweb_web.formfields.FloatField[source]#

Use this field to edit floats (Float yams type). This field additionally support min and max attributes as the IntField.

Unless explicitly specified, the widget for this field will be a TextInput.

class cubicweb_web.formfields.BooleanField[source]#

Use this field to edit booleans (Boolean yams type).

Unless explicitly specified, the widget for this field will be a Radio with yes/no values. You can change that values by specifing choices.

class cubicweb_web.formfields.DateField[source]#

Use this field to edit date (Date yams type).

Unless explicitly specified, the widget for this field will be a JQueryDatePicker.

class cubicweb_web.formfields.DateTimeField[source]#

Use this field to edit datetime (Datetime yams type).

Unless explicitly specified, the widget for this field will be a JQueryDateTimePicker.

class cubicweb_web.formfields.TZDatetimeField[source]#

Use this field to edit a timezone-aware datetime (TZDatetime yams type). Note the posted values are interpreted as UTC, so you may need to convert them client-side, using some javascript in the corresponding widget.

class cubicweb_web.formfields.TimeField[source]#

Use this field to edit time (Time yams type).

Unless explicitly specified, the widget for this field will be a JQueryTimePicker.

class cubicweb_web.formfields.TimeIntervalField[source]#

Use this field to edit time interval (Interval yams type).

Unless explicitly specified, the widget for this field will be a TextInput.

Compound fields#

class cubicweb_web.formfields.RichTextField[source]#

This compound field allow edition of text (unicode string) in a particular format. It has an inner field holding the text format, that can be specified using format_field argument. If not specified one will be automaticall generated.

Unless explicitly specified, the widget for this field will be a FCKEditor or a TextArea. according to the field’s format and to user’s preferences.

class cubicweb_web.formfields.FileField[source]#

This compound field allow edition of binary stream (Bytes yams type). Three inner fields may be specified:

  • format_field, holding the file’s format.

  • encoding_field, holding the file’s content encoding.

  • name_field, holding the file’s name.

Unless explicitly specified, the widget for this field will be a FileInput. Inner fields, if any, will be added to a drop down menu at the right of the file input.

class cubicweb_web.formfields.CompoundField[source]#

This field shouldn’t be used directly, it’s designed to hold inner fields that should be conceptually groupped together.

Entity specific fields and function#

class cubicweb_web.formfields.RelationField[source]#

Use this field to edit a relation of an entity.

Unless explicitly specified, the widget for this field will be a Select.

cubicweb_web.formfields.guess_field(eschema, rschema, role='subject', req=None, **kwargs)[source]#

This function return the most adapted field to edit the given relation (rschema) where the given entity type (eschema) is the subject or object (role).

The field is initialized according to information found in the schema, though any value can be explicitly specified using kwargs.

Widgets#

Note

A widget is responsible for the display of a field. It may use more than one HTML input tags. When the form is posted, a widget is also reponsible to give back to the field something it can understand.

Of course you can not use any widget with any field…

class cubicweb_web.formwidgets.FieldWidget(attrs=None, setdomid=None, suffix=None)[source]#

The abstract base class for widgets.

Attributes

Here are standard attributes of a widget, that may be set on concrete class to override default behaviours:

needs_js

list of javascript files needed by the widget.

needs_css

list of css files needed by the widget.

setdomid

flag telling if HTML DOM identifier should be set on input.

suffix

string to use a suffix when generating input, to ease usage as a sub-widgets (eg widget used by another widget)

vocabulary_widget

flag telling if this widget expect a vocabulary

Also, widget instances takes as first argument a attrs dictionary which will be stored in the attribute of the same name. It contains HTML attributes that should be set in the widget’s input tag (though concrete classes may ignore it).

Form generation methods

render(form, field, renderer=None)[source]#

Called to render the widget for the given field in the given form. Return a unicode string containing the HTML snippet.

You will usually prefer to override the _render() method so you don’t have to handle addition of needed javascript / css files.

_render(form, field, renderer)[source]#

This is the method you have to implement in concrete widget classes.

values(form, field)[source]#

Return the current string values (i.e. for display in an HTML string) for the given field. This method returns a list of values since it’s suitable for all kind of widgets, some of them taking multiple values, but you’ll get a single value in the list in most cases.

Those values are searched in:

  1. previously submitted form values if any (on validation error)

  2. req.form (specified using request parameters)

  3. extra form values given to form.render call (specified the code generating the form)

  4. field’s typed value (returned by its typed_value() method)

Values found in 1. and 2. are expected te be already some ‘display value’ (eg a string) while those found in 3. and 4. are expected to be correctly typed value.

3 and 4 are handle by the typed_value() method to ease reuse in concrete classes.

attributes(form, field)[source]#

Return HTML attributes for the widget, automatically setting DOM identifier when desired (see setdomid attribute)

Post handling methods

process_field_data(form, field)[source]#

Return process posted value(s) for widget and return something understandable by the associated field. That value may be correctly typed or a string that the field may parse.

HTML <input> based widgets#

class cubicweb_web.formwidgets.HiddenInput(attrs=None, setdomid=None, suffix=None)[source]#

Simple <input type=’hidden’> for hidden value, will return a unicode string.

class cubicweb_web.formwidgets.TextInput(attrs=None, setdomid=None, suffix=None)[source]#

Simple <input type=’text’>, will return a unicode string.

class cubicweb_web.formwidgets.EmailInput(attrs=None, setdomid=None, suffix=None)[source]#

Simple <input type=’email’>, will return a unicode string.

class cubicweb_web.formwidgets.PasswordSingleInput(attrs=None, setdomid=None, suffix=None)[source]#

Simple <input type=’password’>, will return a utf-8 encoded string.

You may prefer using the PasswordInput widget which handles password confirmation.

class cubicweb_web.formwidgets.FileInput(attrs=None, setdomid=None, suffix=None)[source]#

Simple <input type=’file’>, will return a tuple (name, stream) where name is the posted file name and stream a file like object containing the posted file data.

class cubicweb_web.formwidgets.ButtonInput(attrs=None, setdomid=None, suffix=None)[source]#

Simple <input type=’button’>, will return a unicode string.

If you want a global form button, look at the Button, SubmitButton, ResetButton and ImgButton below.

Other standard HTML widgets#

class cubicweb_web.formwidgets.TextArea(attrs=None, setdomid=None, suffix=None)[source]#

Simple <textarea>, will return a unicode string.

class cubicweb_web.formwidgets.Select(attrs=None, multiple=False, **kwargs)[source]#

Simple <select>, for field having a specific vocabulary. Will return a unicode string, or a list of unicode strings.

class cubicweb_web.formwidgets.CheckBox(attrs=None, separator=None, **kwargs)[source]#

Simple <input type=’checkbox’>, for field having a specific vocabulary. One input will be generated for each possible value.

You can specify separator using the separator constructor argument, by default <br/> is used.

class cubicweb_web.formwidgets.Radio(attrs=None, separator=None, **kwargs)[source]#

Simle <input type=’radio’>, for field having a specific vocabulary. One input will be generated for each possible value.

You can specify separator using the separator constructor argument, by default <br/> is used.

Date and time widgets#

class cubicweb_web.formwidgets.DateTimePicker(attrs=None, setdomid=None, suffix=None)[source]#

<input type=’text’> + javascript date/time picker for date or datetime fields. Will return the date or datetime as a unicode string.

class cubicweb_web.formwidgets.JQueryDateTimePicker(initialtime=None, timesteps=15, separator=':', **kwargs)[source]#

Compound widget using JQueryDatePicker and JQueryTimePicker widgets to define a date and time picker. Will return the date and time as python datetime instance.

class cubicweb_web.formwidgets.JQueryDatePicker(datestr=None, min_of=None, max_of=None, **kwargs)[source]#

Use jquery.ui.datepicker to define a date picker. Will return the date as a unicode string.

You can couple DatePickers by using the min_of and/or max_of parameters. The DatePicker identified by the value of min_of(/max_of) will force the user to choose a date anterior(/posterior) to this DatePicker.

example:

start and end are two JQueryDatePicker and start must always be before end:

affk.set_field_kwargs(etype, 'start_date', widget=JQueryDatePicker(min_of='end_date'))
affk.set_field_kwargs(etype, 'end_date', widget=JQueryDatePicker(max_of='start_date'))

That way, on change of end(/start) value a new max(/min) will be set for start(/end) The invalid dates will be gray colored in the datepicker

class cubicweb_web.formwidgets.JQueryTimePicker(timestr=None, timesteps=30, separator=':', **kwargs)[source]#

Use jquery.timePicker to define a time picker. Will return the time as a unicode string.

Ajax / javascript widgets#

class cubicweb_web.formwidgets.FCKEditor(*args, **kwargs)[source]#

FCKEditor enabled <textarea>, will return a unicode string containing HTML formated text.

class cubicweb_web.formwidgets.AjaxWidget(wdgtype, inputid=None, **kwargs)[source]#

Simple <div> based ajax widget, requiring a wdgtype argument telling which javascript widget should be used.

class cubicweb_web.formwidgets.AutoCompletionWidget(*args, **kwargs)[source]#

<input type=’text’> based ajax widget, taking a autocomplete_initfunc argument which should specify the name of a method of the json controller. This method is expected to return allowed values for the input, that the widget will use to propose matching values as you type.

class cubicweb_web.formwidgets.InOutWidget(*args, **kwargs)[source]#

Other widgets#

class cubicweb_web.formwidgets.PasswordInput(attrs=None, setdomid=None, suffix=None)[source]#

<input type=’password’> and a confirmation input. Form processing will fail if password and confirmation differs, else it will return the password as a utf-8 encoded string.

class cubicweb_web.formwidgets.IntervalWidget(attrs=None, setdomid=None, suffix=None)[source]#

Custom widget to display an interval composed by 2 fields. This widget is expected to be used with a CompoundField containing the two actual fields.

Exemple usage:

class MyForm(FieldsForm):
   price = CompoundField(fields=(IntField(name='minprice'),
                                 IntField(name='maxprice')),
                         label=_('price'),
                         widget=IntervalWidget())
class cubicweb_web.formwidgets.BitSelect(attrs=None, multiple=True, **kwargs)[source]#

Select widget for IntField using a vocabulary with bit masks as values.

See also BitFieldFacet.

class cubicweb_web.formwidgets.HorizontalLayoutWidget(attrs=None, setdomid=None, suffix=None)[source]#

Custom widget to display a set of fields grouped together horizontally in a form. See IntervalWidget for example usage.

class cubicweb_web.formwidgets.EditableURLWidget(attrs=None, setdomid=None, suffix=None)[source]#

Custom widget to edit separatly a URL path / query string (used by default for the path attribute of Bookmark entities).

It deals with url quoting nicely so that the user edit the unquoted value.

Form controls#

Those classes are not proper widget (they are not associated to field) but are used as form controls. Their API is similar to widgets except that field argument given to render() will be None.

class cubicweb_web.formwidgets.Button(label=('button_ok', 'OK_ICON'), attrs=None, setdomid=None, name='', value='', onclick=None, cwaction=None)[source]#

Simple <input type=’button’>, base class for global form buttons.

Note that label is a msgid which will be translated at form generation time, you should not give an already translated string.

class cubicweb_web.formwidgets.SubmitButton(label=('button_ok', 'OK_ICON'), attrs=None, setdomid=None, name='', value='', onclick=None, cwaction=None)[source]#

Simple <input type=’submit’>, main button to submit a form

class cubicweb_web.formwidgets.ResetButton(label=('button_ok', 'OK_ICON'), attrs=None, setdomid=None, name='', value='', onclick=None, cwaction=None)[source]#

Simple <input type=’reset’>, main button to reset a form. You usually don’t want to use this.

class cubicweb_web.formwidgets.ImgButton(domid, href, label, imgressource)[source]#

Simple <img> wrapped into a <a> tag with href triggering something (usually a javascript call).

Base form classes#

Besides the automagic form we’ll see later, there are roughly two main form classes in CubicWeb:

class cubicweb_web.views.forms.FieldsForm(req, rset=None, row=None, col=None, submitmsg=None, mainform=True, **kwargs)[source]#

This is the base class for fields based forms.

Attributes

The following attributes may be either set on subclasses or given on form selection to customize the generated form:

needs_js

sequence of javascript files that should be added to handle this form (through add_js())

needs_css

sequence of css files that should be added to handle this form (through add_css())

domid

value for the “id” attribute of the <form> tag

action

value for the “action” attribute of the <form> tag

onsubmit

value for the “onsubmit” attribute of the <form> tag

cssclass

value for the “class” attribute of the <form> tag

cssstyle

value for the “style” attribute of the <form> tag

cwtarget

value for the “target” attribute of the <form> tag

redirect_path

relative to redirect to after submitting the form

copy_nav_params

flag telling if navigation parameters should be copied back in hidden inputs

form_buttons

sequence of form control (Button widgets instances)

form_renderer_id

identifier of the form renderer to use to render the form

fieldsets_in_order

sequence of fieldset names , to control order

autocomplete

set to False to add ‘autocomplete=off’ in the form open tag

Generic methods

Form.field_by_name(name, role=None)#

Return field with the given name and role.

Raise FieldNotFound if the field can’t be found.

Form.fields_by_name(name, role=None)#

Return a list of fields with the given name and role.

Form construction methods

Form.remove_field(field)#

Remove the given field.

Form.append_field(field)#

Append the given field.

Form.insert_field_before(field, name, role=None)#

Insert the given field before the field of given name and role.

Form.insert_field_after(field, name, role=None)#

Insert the given field after the field of given name and role.

Form.add_hidden(name, value=None, **kwargs)#

Append an hidden field to the form. name, value and extra keyword arguments will be given to the field constructor. The inserted field is returned.

Form rendering methods

render(formvalues=None, renderer=None, **kwargs)[source]#

Render this form, using the renderer given as argument or the default according to form_renderer_id. The rendered form is returned as a unicode string.

formvalues is an optional dictionary containing values that will be considered as field’s value.

Extra keyword arguments will be given to renderer’s render() method.

Form posting methods

Once a form is posted, you can retrieve the form on the controller side and use the following methods to ease processing. For “simple” forms, this should looks like :

form = self._cw.vreg['forms'].select('myformid', self._cw)
posted = form.process_posted()
# do something with the returned dictionary

Notice that form related to entity edition should usually use the edit controller which will handle all the logic for you.

process_posted()[source]#

use this method to process the content posted by a simple form. it will return a dictionary with field names as key and typed value as associated value.

iter_modified_fields(editedfields=None, entity=None)[source]#

return a generator on field that has been modified by the posted form.

class cubicweb_web.views.forms.EntityFieldsForm(_cw, rset=None, row=None, col=None, **kwargs)[source]#

This class is designed for forms used to edit some entities. It should handle for you all the underlying stuff necessary to properly work with the generic EditController.

As you have probably guessed, choosing between them is easy. Simply ask you the question ‘I am editing an entity or not?’. If the answer is yes, use EntityFieldsForm, else use FieldsForm.

Actually there exists a third form class:

class cubicweb_web.views.forms.CompositeForm(*args, **kwargs)[source]#

Form composed of sub-forms. Typical usage is edition of multiple entities at once.

but you’ll use this one rarely.

Renderers#

Note

Form renderers are responsible to layout a form to HTML.

Here are the base renderers available:

class cubicweb_web.views.formrenderers.FormRenderer(req=None, rset=None, row=None, col=None, **kwargs)[source]#

This is the ‘default’ renderer, displaying fields in a two columns table:

field1 label

field1 input

field2 label

field2 input

buttons

class cubicweb_web.views.formrenderers.HTableFormRenderer(req=None, rset=None, row=None, col=None, **kwargs)[source]#

The ‘htable’ form renderer display fields horizontally in a table:

field1 label

field2 label

field1 input

field2 input

buttons

class cubicweb_web.views.formrenderers.EntityCompositeFormRenderer(req=None, rset=None, row=None, col=None, **kwargs)[source]#

This is a specific renderer for the multiple entities edition form (‘muledit’).

Each entity form will be displayed in row off a table, with a check box for each entities to indicate which ones are edited. Those checkboxes should be automatically updated when something is edited.

class cubicweb_web.views.formrenderers.EntityFormRenderer(req=None, rset=None, row=None, col=None, **kwargs)[source]#

This is the ‘default’ renderer for entity’s form.

You can still use form_renderer_id = ‘base’ if you want base FormRenderer layout even when selected for an entity.

class cubicweb_web.views.formrenderers.EntityInlinedFormRenderer(req=None, rset=None, row=None, col=None, **kwargs)[source]#

This is a specific renderer for entity’s form inlined into another entity’s form.