简体   繁体   中英

Pre-tick specific checkbox in z3c.form list

I have a z3c.form that's used during registration. One of the fields is a list of emails users may wish to sign up for.

from zope import schema
from zope.schema.vocabulary import SimpleVocabulary

emailVocab = SimpleVocabulary.fromItems((
    ('sysn', u'System notifications (strongly recommended)'),
    ('mark', u'Marketing emails'),
    ('offe', u'Special offers')))

...

email_optin = schema.List(
    title = u'',
    description = u'',
    required = False,
    value_type = schema.Choice(source=emailVocab))

I'd like to have the first of these to be selected by default, while the others should not be. I can't see a way in the spec to do this. Any ideas?

Simplest case is as documented in Modelling using zope.schema, default value section , which z3c.form picks up ( relevant documentation ). However, this is complicated by the fact that the default values should not be mutable as the instance is shared across everything, so for safety sake a defaultFactory argument is implemented for handling this. Putting all that together, you should have something like this:

import zope.schema
import zope.interface
from zope.schema.vocabulary import SimpleVocabulary

emailVocab = SimpleVocabulary.fromItems((
    ('sysn', u'System notifications (strongly recommended)'),
    ('mark', u'Marketing emails'),
    ('offe', u'Special offers')))

def default_email():
    return [u'Special offers']  # example


class IEmailPreference(zope.interface.Interface):

    # ...

    email_optin = zope.schema.List(
        title=u'',
        description=u'',
        required=False,
        value_type=zope.schema.Choice(source=emailVocab),
        defaultFactory=default_email,
    )

Do note that the actual value used for the default is not the token part but the value part, hence the string 'Special offers' is returned instead of 'offe' . It is documented in the documentation about Vocabularies . If the human readable part is intended to be the title and you wish the actual value to be the same as the token you will need to adjust your code accordingly. Otherwise, to select the first one you simply have default_email return [u'System notifications (strongly recommended)'] .

For completeness, your form module might look something like this:

from z3c.form.browser.checkbox import CheckBoxFieldWidget
from z3c.form.form import Form

class EmailPreferenceForm(Form):

    fields = z3c.form.field.Fields(IEmailPreference)
    fields['email_optin'].widgetFactory = CheckBoxFieldWidget

Alternatively, you can use value discriminators to approach this issue if you don't wish to populate the interface with a default value or factory for that, but this is a lot more effort to set up so I generally avoid dealing with that when this is good enough.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM