I have been working through the following tutorial provided for Django Autocomplete Light:
https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html
I have successfully implemented autocompletion for one of the fields in my form, however I am unable to complete the following section:
The documentation states that I should be able to add in a feature which allows the user to create a new choice in the form if their required choice is unavailable. However the tutorial is not particularly clear in explaining how to do this.
I am trying to implement a form in which the user can create a new Feedback by:
- Selecting from an autocompleting list of Categories
- Selecting a Message corresponding to the chosen Category
- If the Category or Message they wish to choose is not available, they should be able to add to the existing choices
I have this partly implemented, but it does not appear to work correctly as if no Category is selected, the drop down for the Messages displays the list of Categories. However, if a Category is selected, the correct Messages are displayed as required.
models.py
class Feedback(models.Model):
feedback_id = models.IntegerField(primary_key=True,default=0)
pre_defined_message = models.ForeignKey('Message',on_delete=models.CASCADE,null=True,blank=True) # Selected from a pre defined list depending on selected category
points = models.IntegerField(default=0)
lecturer = models.ForeignKey('LecturerProfile', on_delete=models.CASCADE, null=True, blank=True)
student = models.ForeignKey('StudentProfile', on_delete=models.CASCADE, null=True, blank=True)
which_course = models.ForeignKey('Course', on_delete=models.CASCADE, null=True, blank=True)
datetime_given = models.DateTimeField(default=timezone.now, blank=False)
optional_message = models.CharField(max_length=200,default="")
category = models.ForeignKey('Category', on_delete=models.CASCADE, null=True, blank=True)
class Category(models.Model):
name = models.CharField(max_length=20, default="Empty",primary_key=True)
def __str__(self):
return self.name
class Message(models.Model):
category = models.ForeignKey('Category',on_delete=models.CASCADE,null=True,blank=True)
text = models.CharField(max_length=200,default="No message",primary_key=True)
def __str__(self):
return self.text
forms.py
class FeedbackForm(autocomplete.FutureModelForm):
optional_message = forms.CharField(max_length=200, required=False)
class Meta:
model = Feedback
fields = ('category', 'pre_defined_message','optional_message','points')
widgets = {
'pre_defined_message': autocomplete.ModelSelect2(url='category_autocomplete',forward=['category']),
'category': autocomplete.ModelSelect2(url='category_autocomplete')
}
help_texts = {
'pre_defined_message': "Select a Message",
'category': 'Category',
'optional_message': "Optional Message",
'points': "Points"
}
views.py
class CategoryAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
if not self.request.user.is_authenticated or not self.request.user.is_lecturer:
return Category.objects.none()
query_set = Category.objects.all()
category = self.forwarded.get('category', None)
if self.q:
query_set = query_set.filter(name__istartswith=self.q)
return query_set
if category:
query_set = Message.objects.filter(category=category)
return query_set
urls.py
re_path(r'^category-autocomplete/$', CategoryAutocomplete.as_view(create_field='name'), name='category_autocomplete'),
I have searched for an answer to this for a while and have struggled to find a solution.
I am also aware that my forms.py in particular may not have the most efficient/clean code and am open to suggestions to improve this. I have tried defining an init method however I was unable to do this successfully.
Thanks in advance