Django Autocomplete Light create new choice












2














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:



https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#creation-of-new-choices-in-the-autocomplete-form



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:




  1. Selecting from an autocompleting list of Categories

  2. Selecting a Message corresponding to the chosen Category

  3. 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










share|improve this question





























    2














    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:



    https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#creation-of-new-choices-in-the-autocomplete-form



    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:




    1. Selecting from an autocompleting list of Categories

    2. Selecting a Message corresponding to the chosen Category

    3. 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










    share|improve this question



























      2












      2








      2







      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:



      https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#creation-of-new-choices-in-the-autocomplete-form



      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:




      1. Selecting from an autocompleting list of Categories

      2. Selecting a Message corresponding to the chosen Category

      3. 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










      share|improve this question















      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:



      https://django-autocomplete-light.readthedocs.io/en/master/tutorial.html#creation-of-new-choices-in-the-autocomplete-form



      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:




      1. Selecting from an autocompleting list of Categories

      2. Selecting a Message corresponding to the chosen Category

      3. 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







      python django django-forms django-autocomplete-light






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 17 '18 at 17:39

























      asked Nov 17 '18 at 16:29









      A. Maliampurakal

      114




      114
























          2 Answers
          2






          active

          oldest

          votes


















          0














          After searching through all the open source documentation of Django Autocomplete Light:



          https://github.com/yourlabs/django-autocomplete-light



          I believe I have found a solution to this and thought I should share it for others confused by the provided tutorial.



          After reaching the stage that I have above (i.e working autocompletion) you must include a get_create_option method to allow the view to understand what to do when it retrieves a create_field.



          So in urlpatterns list in urls.py ensure the following line is present:



          re_path(r'^category-autocomplete/$', CategoryAutocomplete.as_view(model=Category,create_field='name'), name='category_autocomplete')




          (Note: the create_field variable must be set to the primary key of the relevant model. In my case, the primary key of Category model is name)



          What is not made clear in the tutorial is the next step. After looking in the following file:



          https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/views.py



          I found a method get_create_option which handles the creation of the new option.



          def get_create_option(self, context, q):
          """Form the correct create_option to append to results."""
          create_option =
          display_create_option = False
          if self.create_field and q:
          page_obj = context.get('page_obj', None)
          if page_obj is None or page_obj.number == 1:
          display_create_option = True

          # Don't offer to create a new option if a
          # case-insensitive) identical one already exists
          existing_options = (self.get_result_label(result).lower()
          for result in context['object_list'])
          if q.lower() in existing_options:
          display_create_option = False

          if display_create_option and self.has_add_permission(self.request):
          create_option = [{
          'id': q,
          'text': _('Create "%(new_value)s"') % {'new_value': q},
          'create_id': True,
          }]
          return create_option




          After including this method in my CategoryAutocomplete class in my views.py, the ability to create a new Category within the search finally worked!



          I am now having difficulty creating a Message object with the previously selected Category as a foreign key as this is also not well documented. I will update this answer if I find a solution.



          Hopefully this is of some help to someone!



          UPDATE



          Although it is a bit of a hack, I have managed to set the foreign key of the Message model. I simply access the created Message and set its category field within the form validation itself:



          if request.method == 'POST':
          form = FeedbackForm(request.POST)
          if form.is_valid():
          new_fb = form.save(commit=False)
          # When a new message is made, the category it is associated with is not saved
          # To fix this, set the category field within this form and save the message object.
          new_fb.pre_defined_message.category = Category.objects.get(name=new_fb.category)
          new_fb.pre_defined_message.save()





          share|improve this answer































            0














            Maybe the problem is that the user doesn't have the add permission that get_create_option checks ?



            Does it work if you add this to your view ?




            def has_add_permission(self, request):
            return True






            share|improve this answer





















            • You're right, that was one of the issues. However the main problem was that I didn't realise I had to include the get_create_option method
              – A. Maliampurakal
              Nov 20 '18 at 17:38










            • I don't think so.
              – jpic
              Nov 21 '18 at 11:14











            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53353161%2fdjango-autocomplete-light-create-new-choice%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            After searching through all the open source documentation of Django Autocomplete Light:



            https://github.com/yourlabs/django-autocomplete-light



            I believe I have found a solution to this and thought I should share it for others confused by the provided tutorial.



            After reaching the stage that I have above (i.e working autocompletion) you must include a get_create_option method to allow the view to understand what to do when it retrieves a create_field.



            So in urlpatterns list in urls.py ensure the following line is present:



            re_path(r'^category-autocomplete/$', CategoryAutocomplete.as_view(model=Category,create_field='name'), name='category_autocomplete')




            (Note: the create_field variable must be set to the primary key of the relevant model. In my case, the primary key of Category model is name)



            What is not made clear in the tutorial is the next step. After looking in the following file:



            https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/views.py



            I found a method get_create_option which handles the creation of the new option.



            def get_create_option(self, context, q):
            """Form the correct create_option to append to results."""
            create_option =
            display_create_option = False
            if self.create_field and q:
            page_obj = context.get('page_obj', None)
            if page_obj is None or page_obj.number == 1:
            display_create_option = True

            # Don't offer to create a new option if a
            # case-insensitive) identical one already exists
            existing_options = (self.get_result_label(result).lower()
            for result in context['object_list'])
            if q.lower() in existing_options:
            display_create_option = False

            if display_create_option and self.has_add_permission(self.request):
            create_option = [{
            'id': q,
            'text': _('Create "%(new_value)s"') % {'new_value': q},
            'create_id': True,
            }]
            return create_option




            After including this method in my CategoryAutocomplete class in my views.py, the ability to create a new Category within the search finally worked!



            I am now having difficulty creating a Message object with the previously selected Category as a foreign key as this is also not well documented. I will update this answer if I find a solution.



            Hopefully this is of some help to someone!



            UPDATE



            Although it is a bit of a hack, I have managed to set the foreign key of the Message model. I simply access the created Message and set its category field within the form validation itself:



            if request.method == 'POST':
            form = FeedbackForm(request.POST)
            if form.is_valid():
            new_fb = form.save(commit=False)
            # When a new message is made, the category it is associated with is not saved
            # To fix this, set the category field within this form and save the message object.
            new_fb.pre_defined_message.category = Category.objects.get(name=new_fb.category)
            new_fb.pre_defined_message.save()





            share|improve this answer




























              0














              After searching through all the open source documentation of Django Autocomplete Light:



              https://github.com/yourlabs/django-autocomplete-light



              I believe I have found a solution to this and thought I should share it for others confused by the provided tutorial.



              After reaching the stage that I have above (i.e working autocompletion) you must include a get_create_option method to allow the view to understand what to do when it retrieves a create_field.



              So in urlpatterns list in urls.py ensure the following line is present:



              re_path(r'^category-autocomplete/$', CategoryAutocomplete.as_view(model=Category,create_field='name'), name='category_autocomplete')




              (Note: the create_field variable must be set to the primary key of the relevant model. In my case, the primary key of Category model is name)



              What is not made clear in the tutorial is the next step. After looking in the following file:



              https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/views.py



              I found a method get_create_option which handles the creation of the new option.



              def get_create_option(self, context, q):
              """Form the correct create_option to append to results."""
              create_option =
              display_create_option = False
              if self.create_field and q:
              page_obj = context.get('page_obj', None)
              if page_obj is None or page_obj.number == 1:
              display_create_option = True

              # Don't offer to create a new option if a
              # case-insensitive) identical one already exists
              existing_options = (self.get_result_label(result).lower()
              for result in context['object_list'])
              if q.lower() in existing_options:
              display_create_option = False

              if display_create_option and self.has_add_permission(self.request):
              create_option = [{
              'id': q,
              'text': _('Create "%(new_value)s"') % {'new_value': q},
              'create_id': True,
              }]
              return create_option




              After including this method in my CategoryAutocomplete class in my views.py, the ability to create a new Category within the search finally worked!



              I am now having difficulty creating a Message object with the previously selected Category as a foreign key as this is also not well documented. I will update this answer if I find a solution.



              Hopefully this is of some help to someone!



              UPDATE



              Although it is a bit of a hack, I have managed to set the foreign key of the Message model. I simply access the created Message and set its category field within the form validation itself:



              if request.method == 'POST':
              form = FeedbackForm(request.POST)
              if form.is_valid():
              new_fb = form.save(commit=False)
              # When a new message is made, the category it is associated with is not saved
              # To fix this, set the category field within this form and save the message object.
              new_fb.pre_defined_message.category = Category.objects.get(name=new_fb.category)
              new_fb.pre_defined_message.save()





              share|improve this answer


























                0












                0








                0






                After searching through all the open source documentation of Django Autocomplete Light:



                https://github.com/yourlabs/django-autocomplete-light



                I believe I have found a solution to this and thought I should share it for others confused by the provided tutorial.



                After reaching the stage that I have above (i.e working autocompletion) you must include a get_create_option method to allow the view to understand what to do when it retrieves a create_field.



                So in urlpatterns list in urls.py ensure the following line is present:



                re_path(r'^category-autocomplete/$', CategoryAutocomplete.as_view(model=Category,create_field='name'), name='category_autocomplete')




                (Note: the create_field variable must be set to the primary key of the relevant model. In my case, the primary key of Category model is name)



                What is not made clear in the tutorial is the next step. After looking in the following file:



                https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/views.py



                I found a method get_create_option which handles the creation of the new option.



                def get_create_option(self, context, q):
                """Form the correct create_option to append to results."""
                create_option =
                display_create_option = False
                if self.create_field and q:
                page_obj = context.get('page_obj', None)
                if page_obj is None or page_obj.number == 1:
                display_create_option = True

                # Don't offer to create a new option if a
                # case-insensitive) identical one already exists
                existing_options = (self.get_result_label(result).lower()
                for result in context['object_list'])
                if q.lower() in existing_options:
                display_create_option = False

                if display_create_option and self.has_add_permission(self.request):
                create_option = [{
                'id': q,
                'text': _('Create "%(new_value)s"') % {'new_value': q},
                'create_id': True,
                }]
                return create_option




                After including this method in my CategoryAutocomplete class in my views.py, the ability to create a new Category within the search finally worked!



                I am now having difficulty creating a Message object with the previously selected Category as a foreign key as this is also not well documented. I will update this answer if I find a solution.



                Hopefully this is of some help to someone!



                UPDATE



                Although it is a bit of a hack, I have managed to set the foreign key of the Message model. I simply access the created Message and set its category field within the form validation itself:



                if request.method == 'POST':
                form = FeedbackForm(request.POST)
                if form.is_valid():
                new_fb = form.save(commit=False)
                # When a new message is made, the category it is associated with is not saved
                # To fix this, set the category field within this form and save the message object.
                new_fb.pre_defined_message.category = Category.objects.get(name=new_fb.category)
                new_fb.pre_defined_message.save()





                share|improve this answer














                After searching through all the open source documentation of Django Autocomplete Light:



                https://github.com/yourlabs/django-autocomplete-light



                I believe I have found a solution to this and thought I should share it for others confused by the provided tutorial.



                After reaching the stage that I have above (i.e working autocompletion) you must include a get_create_option method to allow the view to understand what to do when it retrieves a create_field.



                So in urlpatterns list in urls.py ensure the following line is present:



                re_path(r'^category-autocomplete/$', CategoryAutocomplete.as_view(model=Category,create_field='name'), name='category_autocomplete')




                (Note: the create_field variable must be set to the primary key of the relevant model. In my case, the primary key of Category model is name)



                What is not made clear in the tutorial is the next step. After looking in the following file:



                https://github.com/yourlabs/django-autocomplete-light/blob/master/src/dal_select2/views.py



                I found a method get_create_option which handles the creation of the new option.



                def get_create_option(self, context, q):
                """Form the correct create_option to append to results."""
                create_option =
                display_create_option = False
                if self.create_field and q:
                page_obj = context.get('page_obj', None)
                if page_obj is None or page_obj.number == 1:
                display_create_option = True

                # Don't offer to create a new option if a
                # case-insensitive) identical one already exists
                existing_options = (self.get_result_label(result).lower()
                for result in context['object_list'])
                if q.lower() in existing_options:
                display_create_option = False

                if display_create_option and self.has_add_permission(self.request):
                create_option = [{
                'id': q,
                'text': _('Create "%(new_value)s"') % {'new_value': q},
                'create_id': True,
                }]
                return create_option




                After including this method in my CategoryAutocomplete class in my views.py, the ability to create a new Category within the search finally worked!



                I am now having difficulty creating a Message object with the previously selected Category as a foreign key as this is also not well documented. I will update this answer if I find a solution.



                Hopefully this is of some help to someone!



                UPDATE



                Although it is a bit of a hack, I have managed to set the foreign key of the Message model. I simply access the created Message and set its category field within the form validation itself:



                if request.method == 'POST':
                form = FeedbackForm(request.POST)
                if form.is_valid():
                new_fb = form.save(commit=False)
                # When a new message is made, the category it is associated with is not saved
                # To fix this, set the category field within this form and save the message object.
                new_fb.pre_defined_message.category = Category.objects.get(name=new_fb.category)
                new_fb.pre_defined_message.save()






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 18 '18 at 22:52

























                answered Nov 18 '18 at 14:04









                A. Maliampurakal

                114




                114

























                    0














                    Maybe the problem is that the user doesn't have the add permission that get_create_option checks ?



                    Does it work if you add this to your view ?




                    def has_add_permission(self, request):
                    return True






                    share|improve this answer





















                    • You're right, that was one of the issues. However the main problem was that I didn't realise I had to include the get_create_option method
                      – A. Maliampurakal
                      Nov 20 '18 at 17:38










                    • I don't think so.
                      – jpic
                      Nov 21 '18 at 11:14
















                    0














                    Maybe the problem is that the user doesn't have the add permission that get_create_option checks ?



                    Does it work if you add this to your view ?




                    def has_add_permission(self, request):
                    return True






                    share|improve this answer





















                    • You're right, that was one of the issues. However the main problem was that I didn't realise I had to include the get_create_option method
                      – A. Maliampurakal
                      Nov 20 '18 at 17:38










                    • I don't think so.
                      – jpic
                      Nov 21 '18 at 11:14














                    0












                    0








                    0






                    Maybe the problem is that the user doesn't have the add permission that get_create_option checks ?



                    Does it work if you add this to your view ?




                    def has_add_permission(self, request):
                    return True






                    share|improve this answer












                    Maybe the problem is that the user doesn't have the add permission that get_create_option checks ?



                    Does it work if you add this to your view ?




                    def has_add_permission(self, request):
                    return True







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 20 '18 at 16:35









                    jpic

                    26.8k38793




                    26.8k38793












                    • You're right, that was one of the issues. However the main problem was that I didn't realise I had to include the get_create_option method
                      – A. Maliampurakal
                      Nov 20 '18 at 17:38










                    • I don't think so.
                      – jpic
                      Nov 21 '18 at 11:14


















                    • You're right, that was one of the issues. However the main problem was that I didn't realise I had to include the get_create_option method
                      – A. Maliampurakal
                      Nov 20 '18 at 17:38










                    • I don't think so.
                      – jpic
                      Nov 21 '18 at 11:14
















                    You're right, that was one of the issues. However the main problem was that I didn't realise I had to include the get_create_option method
                    – A. Maliampurakal
                    Nov 20 '18 at 17:38




                    You're right, that was one of the issues. However the main problem was that I didn't realise I had to include the get_create_option method
                    – A. Maliampurakal
                    Nov 20 '18 at 17:38












                    I don't think so.
                    – jpic
                    Nov 21 '18 at 11:14




                    I don't think so.
                    – jpic
                    Nov 21 '18 at 11:14


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53353161%2fdjango-autocomplete-light-create-new-choice%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Biblatex bibliography style without URLs when DOI exists (in Overleaf with Zotero bibliography)

                    ComboBox Display Member on multiple fields

                    Is it possible to collect Nectar points via Trainline?