2

I'm looking for a crispy forms version of this: Django form with choices but also with freetext option?

Models.py

class Animals(models.Model):
     animal_id = models.AutoField(primary_key=True)
     animal_name = models.CharField(max_length=100, verbose_name='Animal Name')

forms.py

from django import forms
from django.forms import ModelForm
from .models import Animals

class CustomSelection(Field):
template = 'custom_selectbox.html'

class AnimalsForm(ModelForm):
class Meta:
    model = Animals
    fields = [
        'animal_name',
    ]

def __init__(self, *args, **kwargs):
    super(AnimalsForm, self).__init__(*args, **kwargs)
    self.helper = FormHelper()
    self.helper.form_tag = True
    self.helper.layout = Layout(
        Div(
            Fieldset(CustomSelection('animal_name'))
            FormActions(
                  Button('submit','Submit')
            )
        )
     )

So if I have:

custom_selectbox.html

{% load crispy_forms_field %}
<div class="form-group">
{{ field.label_tag }}
{% crispy_field field 'class' 'custom-select' %}
</div>

this renders a box OK, which is the first thing I want.

Next, I would like to know if it's possible to somehow inject all of the existing animal_names, something like this:

  {% load crispy_forms_field %}
  <input list="options" name="test-field"  required="" class="form-control" id="test-field-add">
  <datalist id="options">
    {% for option in field.subwidgets %}
      <option value="{{ option.choice_label }}"/>
    {% endfor %}
  </datalist>

but with support for crispy-forms. Essentially I want the user to be presented with a list of existing CharField entries - but if the thing they're looking for isn't around, then I want them to be able to add it. Note: it doesn't need to be a charfield - I could do an independent model and use a Foreign Key but if I do that I'm not sure if that means I need to make a separate form to add new entries to every model (the example is animal_name - in reality the form I need to build has lots of equivalent fields). I would accept the reduced control of a charfield over a foreignkey if it is easier for users to add new entries.

I think the datalist approach would work if I'm making the form directly (forgive me, I'm very new to django) but it feels like I'm (hopefully) missing a more django-esque solution. Ideally one that is compatible with my existing crispy-forms. These forms are very large, so I'm using the Layout() helper heavily, so I would really like to avoid re-creating all of this manually.

I have seen this: Django crispy forms work with custom widgets? but it's very old and I don't understand django well enough to know if the answer still applies.

I have also seen: https://leaverou.github.io/awesomplete/ - this looks equivalent to the datalist approach.

Then finally, https://pypi.org/project/django-awesomplete/ - the only example is for the admin panel so I'm not sure if I can do the same thing with crispy-forms.

neil thompson
  • 57
  • 1
  • 7

1 Answers1

0

I did it using django-floppyforms. I found the solution here: Django form with choices but also with freetext option?

My code:

forms.py

class UserProfileForm(forms.ModelForm):
class Meta:
    model = UserProfile
    fields = ('sexo', 'data_nascimento', 'foto', 'sobre_mim', 'telefone', 'paroquia','cidade','estado', 'cep', 'possui_filhos', 'facebook', 'instagram')
    

    widgets = {
        'cidade': floppyforms.widgets.Input(datalist=CIDADES, attrs={'autocomplete': 'off'}),
    }

Note:

CIDADES is my list containing cities.

atrrs is optional.