Пример #1
0
def get_field_tuple(name, form_or_model):
    """Returns a tuple for the field, of given instance, identified by "name".
    
    Instance could be a model instance, a form instance or any arbitrary object.
    
    The returned tuple is in the form:
    
    (label, attrs, value)
    """
    name, sep, suffix = name.partition(':')

    label = ""
    value = ""
    td_attrs = {}
    field_list = get_fields(form_or_model)
    field = None

    if name in field_list:
        field = field_list[name]

    elif hasattr(form_or_model, name):
        field = getattr(form_or_model, name)
        if hasattr(field, 'short_description'):
            name = field.short_description

    if isinstance(field, models.Field):
        label = '%s:' % field.verbose_name
        value = '%s' % field_to_string(field, form_or_model)

    elif isinstance(field, forms.Field):
        bf = BoundField(form_or_model, field, name)
        label = '%s' % bf.label_tag()
        value = '%s' % bf
        if bf.help_text:
            value += '<br/><span title="%(help_text)s" class="helptext helppopup">%(help_text)s</span>' % {
                "help_text": '%s' % bf.help_text
            }
        errors = bf.errors
        if errors:
            value += '<br/>\n<ul class="errorlist">\n'
            for error in errors:
                value += '\t<li>%s</li>\n' % error
            value += '</ul>\n'
        css_classes = bf.css_classes()
        if css_classes:
            td_attrs['class'] = css_classes

    else:
        name = _(pretty_name(name).lower())
        label = '%s:' % name.capitalize()
        value = field() if callable(field) else field

    firstcap_label = label[:1].upper() + label[1:]
    if suffix:
        value += " " + suffix

    return mark_safe(firstcap_label), flatatt(td_attrs), mark_safe(value)
Пример #2
0
def form_input_text(form: forms.Form,
                    field: BoundField,
                    input_type: str = "text") -> str:
    """Form group with label, input, and errors when form is bound."""
    form_is_bound = form.is_bound
    errors = field.errors
    has_errors = form_is_bound and errors

    return format_html(
        """
    <div class="form-group">
        <label for="{input_id}">{label}</label>
        <input
            type="{input_type}"
            class="form-control {invalid_class}"
            id="{input_id}"
            name="{name}"
            value="{value}"
            aria-describedby="{input_id}-help {input_id}-feedback"
            required>
        <small id="{input_id}-help" class="form-text text-muted">{help_text}</small>
        <div id="{input_id}-feedback" class="invalid-feedback">{errors}</div>
    </div>
    """,
        input_id=field.id_for_label,
        label=field.label,
        input_type=input_type,
        invalid_class="is-invalid" if has_errors else "",
        has_errors=has_errors,
        name=field.html_name,
        value=field.value() or "",
        help_text=field.help_text,
        errors=" ".join(field.errors),
    )
 def as_widget(self, widget=None, attrs=None, only_initial=False):
     subfield_widgets = []
     for i, subfield in enumerate(self.field.fields):
         sub_bf = BoundField(self.form, subfield,
                             "{}_{}".format(self.name, i))
         subfield_widgets.append(self._subfield_as_widget(sub_bf))
     return render_to_string("dynamic_forms/widgets/formrender.html",
                             context={'subfields': subfield_widgets})
Пример #4
0
 def test_get_tuple_for_form_field(self):
     """Tests returning a tuple for a form instance's field.
     """
     from django.forms.boundfield import BoundField
     b = BoundField(self.f, self.f.fields['username'], 'username')
     self.assertEqual(get_field_tuple("username", self.f), (
         '<label class="required" for="id_username">Username:</label>',
         ' class="required"',
         '%s<br/><span title="Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters" class="helptext helppopup">Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters</span>'
         % (b, )))
     b = BoundField(self.f, self.f.fields['email'], 'email')
     self.assertEqual(
         get_field_tuple("email", self.f),
         ('<label class="required" for="id_email">Email:</label>',
          ' class="required"', '%s' % (b, )))
     b = BoundField(self.f, self.f.fields['password2'], 'password2')
     self.assertEqual(get_field_tuple("password2", self.f), (
         '<label for="id_password2">Password confirmation:</label>',
         ' class="errors"',
         '%s<br/><span title="%s" class="helptext helppopup">%s</span><br/>\n<ul class="errorlist">\n\t<li>This field is required.</li>\n</ul>\n'
         % (b, b.help_text, b.help_text)))
def test_crispy_field_and_class_converters():
    template = Template("""
        {% load crispy_forms_field %}
        {% crispy_field testField 'class' 'error' %}
    """)
    test_form = SampleForm()
    field_instance = test_form.fields["email"]
    bound_field = BoundField(test_form, field_instance, "email")

    c = Context({"testField": bound_field})
    html = template.render(c)
    assert "error" in html
    assert "inputtext" in html
Пример #6
0
def field_(self, name):
    """
    From https://github.com/halfnibble/django-underscore-filters

    Get a form field starting with _.
    Taken near directly from Django > forms.
    Returns a BoundField with the given name.
    """
    try:
        field = self.fields[name]
    except KeyError as e:
        raise KeyError("Key %r not found in '%s'" %
                       (name, self.__class__.__name__)) from e
    return BoundField(self, field, name)
Пример #7
0
def render_form_field(field: BoundField, switch: bool = False, add_choices: choice_list_type = None,
                      replace_choices: choice_list_type = None, empty_option: Optional[str] = None,
                      value: field_value = None):
    if value:
        field.initial = value
    return {
        'field': field,
        'switch': switch,
        'add_choices': add_choices,
        'replace_choices': replace_choices,
        'empty_option': empty_option,
        'value': value,
        # TODO: radio values?
    }
Пример #8
0
def test_crispy_addon(settings):
    test_form = SampleForm()
    field_instance = test_form.fields["email"]
    bound_field = BoundField(test_form, field_instance, "email")

    assert "input-group-text" in crispy_addon(bound_field,
                                              prepend="Work",
                                              append="Primary")
    assert "input-group-text" in crispy_addon(bound_field,
                                              prepend="Work",
                                              append="Secondary")

    # errors
    with pytest.raises(TypeError):
        crispy_addon()
    with pytest.raises(TypeError):
        crispy_addon(bound_field)
def uka_form_row_stacked(element, errors='', extra_classes=''):
    label = BoundField.label_tag(element, "", {'class': 'uk-form-label'}, label_suffix='')
    
    if errors:
        extra_classes = f'{extra_classes} uk-form-danger uk-clearfix'
    
    help_text = f'<div class="uk-text-muted uk-margin-small-top"><span uk-icon="icon: comment"></span> {element.help_text}</div>' \
        if element.help_text else ''
    
    original_classes = element.field.widget.attrs.get('class', '')
    
    applied_classes = 'uk-margin-small-top uk-margin-small-bottom'
    
    if element.field.widget.__class__.__name__ == "Select":
        applied_classes = f'{original_classes} uk-select'
    
    elif element.field.widget.__class__.__name__ == "RelatedFieldWidgetWrapper":
        applied_classes = f'{original_classes} uk-select'
        
    elif element.field.widget.__class__.__name__ in ["AdminTextareaWidget", "TextareaWidget"]:
        applied_classes = f'{original_classes} uk-textarea'
    else:
        applied_classes = original_classes
    
    
    # Trying some overrides
    '''
    if element.field.__class__.__name__ in ['SplitDateTimeField', 'ReadOnlyPasswordHashField', 'ModelMultipleChoiceField', 'QuillField']:
        element = element.as_widget()
    
    elif element.field.__class__.__name__ == 'TextareaWidget':
        element = element.as_widget(attrs={'class': f'{applied_classes}'})
   
    else:
    '''
    element = element.as_widget(attrs={'class': f'uk-input uk-form-width-large {applied_classes} {extra_classes}'})
    
    html_error = format_html(f'<div class="uk-text-danger uk-margin-top">{errors}</div>')

    html = format_html(f'<div class="uk-form-row">' \
                       f'    <div>{label} {html_error}</div>' \
                       f'    <div class="uk-form-controls" style="clear: both">{element}{help_text}</div>' \
                       f'</div>')
    return html
def test_crispy_addon(settings):
    test_form = SampleForm()
    field_instance = test_form.fields["email"]
    bound_field = BoundField(test_form, field_instance, "email")

    if settings.CRISPY_TEMPLATE_PACK == "bootstrap":
        # prepend tests
        assert "input-prepend" in crispy_addon(bound_field, prepend="Work")
        assert "input-append" not in crispy_addon(bound_field, prepend="Work")
        # append tests
        assert "input-prepend" not in crispy_addon(bound_field,
                                                   append="Primary")
        assert "input-append" in crispy_addon(bound_field, append="Secondary")
        # prepend and append tests
        assert "input-append" in crispy_addon(bound_field,
                                              prepend="Work",
                                              append="Primary")
        assert "input-prepend" in crispy_addon(bound_field,
                                               prepend="Work",
                                               append="Secondary")
    elif settings.CRISPY_TEMPLATE_PACK == "bootstrap3":
        assert "input-group-addon" in crispy_addon(bound_field,
                                                   prepend="Work",
                                                   append="Primary")
        assert "input-group-addon" in crispy_addon(bound_field,
                                                   prepend="Work",
                                                   append="Secondary")
    elif settings.CRISPY_TEMPLATE_PACK == "bootstrap4":
        assert "input-group-text" in crispy_addon(bound_field,
                                                  prepend="Work",
                                                  append="Primary")
        assert "input-group-text" in crispy_addon(bound_field,
                                                  prepend="Work",
                                                  append="Secondary")

    # errors
    with pytest.raises(TypeError):
        crispy_addon()
    with pytest.raises(TypeError):
        crispy_addon(bound_field)
Пример #11
0
def form_input_checkbox(
    form: forms.Form,
    field: BoundField,
    tooltip_src: str = "ui/svg/info-circle-fill.svg",
    placement: str = "right",
) -> str:
    """Form group with label, checkbox input, and tooltip."""
    form_is_bound = form.is_bound
    errors = field.errors
    has_errors = form_is_bound and errors

    return format_html(
        """
    <div class="form-group">
        <div class="form-check">
            <input
            type="checkbox"
            class="form-check-input {invalid_class}"
            id="{input_id}" {checked}/>
            <label class="form-check-label" for="{input_id}">{label}</label>
            <img
                id="{input_id}-tooltip"
                src="{static_url}{tooltip_src}"
                data-toggle="tooltip"
                data-placement="{placement}"
                title="{help_text}" />
        </div>
    </div>
    """,
        input_id=field.id_for_label,
        label=field.label,
        invalid_class="is-invalid" if has_errors else "",
        checked="checked" if form_is_bound and field.value() else "",
        static_url=settings.STATIC_URL,
        tooltip_src=tooltip_src,
        placement=placement,
        help_text=field.help_text,
    )
Пример #12
0
 def get_bound_field(self, form, field_name):
     """
     Return a BoundField instance that will be used when accessing the form
     field in a template.
     """
     return BoundField(form, self, field_name)
Пример #13
0
 def bound_field_dict(self):
     return OrderedDict(
         (field_name, BoundField(self.form, field, field_name))
         for (field_name, field) in self.form.fields.items()
     )
Пример #14
0
 def _bound_value(self, field_name):
     field = self.fields[field_name]
     return BoundField(self, field, field_name).value()
Пример #15
0
    def default(self, o, form=None, field_name=None):
        if issubclass(o.__class__, (forms.Form,forms.BaseForm)):
            flds = []

            for name, field in o.fields.items():
                if isinstance(field, dict):
                    field['title'] = name
                else:
                    field.name = name
                cfg = self.default(field, o, name)
                flds.append(cfg)

            return flds
        elif isinstance(o, dict):
            #Fieldset
            default_config = {
                'autoHeight': True,
                'collapsible': True,
                'items': [],
                'labelWidth': 200,
                'title': o['title'],
                'xtype':'fieldset',
            }
            del o['title']

            #Ensure fields are added sorted by position
            for name, field in sorted(o.items()):
                field.name = name
                default_config['items'].append(self.default(field))
            return default_config
        elif issubclass(o.__class__, fields.Field):
            #bf = form and form.is_bound and BoundField(form, o, field_name) or None
            bf = BoundField(form, o, field_name)
            #print field_name , o.__class__

            default_config = {}
            if o.__class__ in self.DJANGO_EXT_FIELD_TYPES:
                default_config.update(self.DJANGO_EXT_FIELD_TYPES[o.__class__][1])
            else:
                default_config.update(self.EXT_DEFAULT_CONFIG['editor'])
            config = deepcopy(default_config)
            if bf:
                config['invalidText']="".join(form[field_name].errors)

            if form and form.is_bound:
                data = bf.data
            else:
                if field_name:
                    data = form.initial.get(field_name, o.initial)
                    if callable(data):
                        data = data()
                else:
                    data = None
            config['value'] = data
            for dj, ext in self.DJANGO_EXT_FIELD_ATTRS.items():
                v = None
                if dj == 'size':
                    v = o.widget.attrs.get(dj, None)
                    if v is not None:
                        if o.__class__ in (fields.DateField, fields.DateTimeField,
                           fields.SplitDateTimeField, fields.TimeField):
                            v += 8
                        #Django's size attribute is the number of characters,
                        #so multiply by the pixel width of a character
                        v = v * self.CHAR_PIXEL_WIDTH
                elif dj == 'hidden':
                    v = o.widget.attrs.get(dj, default_config.get('fieldHidden', ext[1]))
                elif dj == 'name':
                    v = bf and bf.html_name or field_name
                elif dj == 'label':
                    v = bf and bf.label or getattr(o, dj, ext[1])
                elif getattr(o, dj, ext[1]) is None:
                    #print "dj:%s field name:%s"%(dj,field_name)
                    pass
                #elif dj == 'input_formats':
                    #alt_fmts = []
                    ##Strip out the '%'  placeholders
                    #for fmt in getattr(field, dj, ext[1]):
                        #alt_fmts.append(fmt.replace('%', ''))
                    #v = u'|'.join(alt_fmts)
                elif isinstance(ext[1], basestring):
                    v = getattr(o, dj, getattr(field, ext[1]))
                elif ext[0] == 'store':
                    v = {
                        'autoLoad': True,
                        'storeId': o.name,
                        'url': '/csds/ext/rdo/queryset/%s/' % (o.name.lower(),),
                        #'xtype': 'jsonstore',
                    }
                elif dj == 'required':
                    try:
                        v = not getattr(o, dj)
                    except AttributeError :
                        v = ext[1]
                else:
                    v = getattr(o, dj, ext[1])
                if v is not None:
                    if ext[0] == 'name':
                        config[ext[0]] = v
                        config['header'] = v
                    elif ext[0] not in ('name', 'dataIndex', 'fieldLabel', 'header', 'defaultValue'):
                    #elif ext[0] in ('allowBlank', 'listWidth', 'store', 'width'):
                            #if isinstance(v, QuerySetIterator):
                            #    config['editor'][ext[0]] = list(v)
                        config[ext[0]] = v
                        if ext[0] == 'store':
                            #config['url'] = v['url']
                            choices = [(c[0],c[1]) for c in o.choices]
                            config['store'] = choices
                            config['displayField'] = 'display'
                            config['editable'] = False
                            #config['editor']['forceSelection'] = True
                            config['hiddenName'] = o.name
                            #config['lastQuery'] = ''
                            config['mode'] = 'local'
                            config['triggerAction'] = 'all'
                            #config['valueField'] = 'id'

                    elif isinstance(v, unicode):
                        config[ext[0]] = v.encode('utf8')
                    else:
                        config[ext[0]] = v
            return config
        else:
            return super(ExtJSONEncoder, self).default(o)
Пример #16
0
 def __iter__(self):
     for name in self.fields:
         yield BoundField(self.form, self.form.fields[name], name)