Search code examples
djangodjango-autocomplete-lightdjango-smart-selects

Django AutoComplete Light Filter Foreign Key Values


I am using the Django AutoComplete Light library to filter Form values based on a Primary key. I have two models as below:

class Skill(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
    return self.name



  class SubSkill(models.Model):
        name = models.CharField(max_length=50)
        skill = models.ForeignKey(Skill, on_delete=models.CASCADE, null=True)
        def __str__(self):
        return self.name.

However, these two field are used in another Employee model as I want to query base on this model. I had used Django Smart Selects to chain the models in the Employee model which works fine. However, I am trying to filter my subskills based on the skills using the Autocomplete library but getting all the subskills instead. My Django Autocomplete light view looks like this

class SubskillsAutocomplete(autocomplete.Select2QuerySetView):

def get_queryset(self):
    # Don't forget to filter out results depending on the visitor !
    # if not self.request.user.is_authenticated():
    #     return Country.objects.none()

    qs = SubSkill.objects.all()

    if self.q:
        qs = qs.filter(name__istartswith=self.q)

    return qs

and my model form looks like this:

class EmployeeSkillForm(forms.ModelForm):

class Meta:
    model = Employee
    fields = ('skills','sub_skills', 'experience','resume','certificates')
    widgets = {
        'sub_skills': autocomplete.ModelSelect2Multiple(url='skills-autocomplete')
    }

I cannot figure out why my subskills will not filter based on the skill instead of showing everything.


Solution

  • Use the newest version of django-autocomplete-light doc. To filter results based on the value of other fields in the form you have to use forward argument.

    The form:

    class EmployeeSkillForm(forms.ModelForm):
    
        class Meta:
            model = Employee
            fields = ('skills','sub_skills', 'experience','resume','certificates')
            widgets = {
               'sub_skills': autocomplete.ModelSelect2Multiple(url='skills-autocomplete', 
                                                                forward=['skills'])
                      }
    

    Django Autocomplete light view:

    class SubskillsAutocomplete(autocomplete.Select2QuerySetView):
    
        def get_queryset(self):
    
            qs = SubSkill.objects.all()
            skills = self.forwarded.get('skills', None)
    
            if skills:
                qs = qs.filter(skill__in=skills)
    
            if self.q:
                qs = qs.filter(name__istartswith=self.q)
    
    
            return qs