Search code examples
pythondjangodjango-filterdjango-crispy-forms

Include search/filtering in my choicefield django


I have a CrispyForm where I have a ChoiceField called "act_cuenta" with choices that I load from a query. I want that in this field the user has the option to type and search for one of the options within the list.

form.py

class MayoresForm(Form):
    act_cuenta = ()

    act_fechaini = DateField(
        widget=DatePickerInput(
            format=Form_CSS.fields_date_format,
            options=Form_CSS.fields_date_opts,
            attrs={'value': Form_CSS.fields_current_date}
        ),
        label="Fecha desde: ",
        required=True,
    )
    act_fechafin = DateField(
        widget=DatePickerInput(
            format=Form_CSS.fields_date_format,
            options=Form_CSS.fields_date_opts,
            attrs={'value': Form_CSS.fields_current_date}
        ),
        label="Fecha hasta: ",
        required=True,
    )

    def __init__(self, *args, **kwargs):
        self.AIGN_OPCIONES = kwargs.pop("AIGN_OPCIONES")
        self.PERMISOS = []  # para recuperar los permisos de la tabla
        __json_values = json.loads(json.dumps(self.AIGN_OPCIONES))
        self.PERMISOS = recuperarPermisos(__json_values, 'con.transaccioncab')
        self.AIGN_PER_ID = kwargs.pop("AIGN_PER_ID")

        super(MayoresForm, self).__init__(*args, **kwargs)

        self.fields['act_cuenta'] = ChoiceField(label='Cuenta: ', choices=self.get_choices(), required=True)

        for form in self.visible_fields():
            form.field.widget.attrs['autocomplete'] = Form_CSS.fields_autocomplete
            form.field.widget.attrs['class'] = Form_CSS.fields_attr_class
        self.helper = FormHelper(self)
        self.helper.form_method = 'post'
        self.helper.form_id = Form_CSS.getFormID(self)
        self.helper.attrs = Form_CSS.form_attrs
        self.helper.form_tag = True
        self.helper.label_class = 'col-sm-3 text-right form-control-sm'
        self.helper.field_class = 'col-sm-6'
        self.helper.layout = Layout(
            Div(
                DivHeaderWithButtons(instance_pk=None, remove_create=False, remove_delete=True, remove_print=True,
                                     remove_cancel=False,
                                     permisos=self.PERMISOS,
                                     save_name=' Consultar'),
                Div(
                    Div(
                        Div(
                            Div(
                                Div(
                                    HTML("<h3 class='card-title'>Buscar por:</h3>"),
                                    css_class='card-header'
                                ),
                                Div(
                                    Div(
                                        'act_cuenta',
                                        css_class='card-body'
                                    ),
                                    Div(
                                        'act_fechaini',
                                        'act_fechafin',
                                        css_class='card-body'
                                    ),
                                    css_class="row"
                                ),
                                css_class='card card-secondary'
                            ),
                            css_class='col-sm',
                        ),
                        css_class='row',
                    ),
                    css_class='card-body'
                ),
                css_class='card'
            ),
        )

    def get_choices(self):
        all_tipoaux = Con_Cuenta.objects.filter(cue_grupo='M', cue_estado=1, per_id=self.AIGN_PER_ID).order_by(
            'cue_codigov').values()
        DOC = [(d['cue_codigov'], d['cue_codigov'] + ' - ' + d['cue_nombre']) for d in all_tipoaux]
        return DOC

How can I do this? I have seen that django-filter exists, but I don't know how to implement it together with crispy-forms.


Solution

  • SOLUTION:

    I was able to solve the problem using the Select2 library.

    self.fields['act_cuenta'] = ModelChoiceField(label=u'Cuenta: ', queryset=self.get_choices(),
                                                         widget=ModelSelect2Widget(
                                                             search_fields=['cue_nombre__icontains',
                                                                            'cue_codigov__icontains'],
                                                             dependent_fields={'cue_codigov': 'cue_codigov'},
                                                             attrs={"data-placeholder": '-- Cuenta --',
                                                                    'data-minimum-input-length': 0,
                                                                    'style': 'width: 120%;'},
                                                             # to_field_name="cue_codigov"
                                                         ), required=True)