How to create a charfield with suggestions in django forms?

Viewed 75

I want to create a charfield input in a django form that has suggestions. Essentially I want a choice field that also allows you to write your own value if needed. In other words a hybrid between a charfield and choice field input. Any suggestions on how to achieve this ?

forms.py


class PDFClassificationForm(forms.ModelForm):  
    nature = forms.CharField(required=False)
    class Meta:  
        model = Documents
        fields = [,
                  'nature',]
        labels = {,,
                  'nature':'Nature/Concerne:',
                  }
        
    def __init__(self, uuid_pdf, *args, **kwargs):
        super(PDFClassificationForm, self).__init__(*args, **kwargs)
        
        nature_choices=  Archivagerecurrencelibelle.objects.filter(Q(id_emetteur=Documents.objects.get(uuid=uuid_pdf).id_emetteur) & Q(source="Nature")).values_list('concerne','concerne')
        
        self.fields['nature'].choices =  nature_choices
        

views.py

class DocumentsArchiveUpdateView(UpdateView): 
    model = Documents
    template_name = 'documents/documents_read_write.html'
    form_class = PDFClassificationForm
    success_url = lazy(reverse, str)("documents_archive_list")
    
    def get_context_data(self, *args, **kwargs):
    
        # Call the base implementation first to get a context
        context = super(DocumentsArchiveUpdateView, self).get_context_data(*args, **kwargs)
        
        id_customer = Documents.objects.get(uuid=self.kwargs['uuid_pdf']).id_customer
        context["document_owner"] = Entity.objects.get(id=id_customer)
        
        context["uuid_contrat"] = self.kwargs['uuid_contrat']
        context["uuid_group"] = self.kwargs['uuid_group']
        context["uuid_pdf"] = self.kwargs['uuid_pdf']

       
        return context
    
 

    def form_valid(self, form):
        obj = form.save(commit=False)
        obj.id_document_status = DocumentStatusLst.objects.get(id=3)
        obj.save()        
        return super().form_valid(form)
    
    def get_form_kwargs(self,) :
            
        uuid_pdf = self.kwargs['uuid_pdf']
        kwargs = super(DocumentsArchiveUpdateView, self).get_form_kwargs()
        kwargs["uuid_pdf"] = uuid_pdf

        return kwargs


documents_read_write.html

{% extends 'layout.html' %}

{% load crispy_forms_tags %} 


<form action = "{%url 'jnt_customer_create' uuid_contrat uuid_group pdfid%}" method="POST" enctype="multipart/form-data">
  <!-- Security token -->
  {% csrf_token %} 

  <!-- Using the formset -->
  {{ form |crispy}} 
  <button type="submit"  name="btnform1" class="btn btn-primary">Enregistrer</button>
</form> 

{% endblock %}

2 Answers

----------- models.py -------

from django.db import models


class EmployeeModel(models.Model):
    name = models.CharField(max_length=255)
    age = models.PositiveIntegerField()
    city = models.CharField(max_length=255)

    def __str__(self):
        return self.name

----------- form.py -------

class EmployeeFrom(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(EmployeeFrom, self).__init__(*args, **kwargs)
        self.fields['city'].widget = forms.Select(choices = CityModel.objects.values_list('name','name'))
        

    class Meta:
        model = EmployeeModel
        fields = "__all__"

        widgets = {

            'name':forms.TextInput(attrs={'class':'form-control'}),
            'age':forms.NumberInput(attrs={'class':'form-control'}),

        }

----------- Html code for form -----------

<div class="modal-body">
        <form action="" method="POST">
          {% csrf_token %}
          <div class="mb-3">
            <label class="form-label">{{form.name.label}}</label>
            {{form.name}}
          </div>

          <div class="mb-3">
            <label class="form-label">{{form.age.label}}</label>
            {{form.age}}
          </div>
          <div class="mb-3">
          <label class="form-label">{{form.city.label}}</label>
          <input class="form-select" placeholder="--- Select city ---" name="city" type="text" list="cities">
          <datalist id="cities">
            {% for i in form.city %}
            <option>{{i}}</option>
            
            {% endfor %}
          </datalist>
        </div>
            
          
          <button class="btn btn-primary" type="submit">Add Employee</button>
        </form>
      </div>

========= Ouput ===============

all cities

enter image description here

after entering keyword

enter image description here

==== last output ==============

enter image description here

You might try with this https://github.com/jazzband/django-taggit I used it in a similar use case, you can pass a whitelist of "tags" as suggestion or populate it with already used tags, while still allowing the creation of new values

Related