Django Autocomplete Light create new choice
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:
- 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
python django django-forms django-autocomplete-light
add a comment |
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:
- 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
python django django-forms django-autocomplete-light
add a comment |
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:
- 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
python django django-forms django-autocomplete-light
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:
- 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
python django django-forms django-autocomplete-light
python django django-forms django-autocomplete-light
edited Nov 17 '18 at 17:39
asked Nov 17 '18 at 16:29
A. Maliampurakal
114
114
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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()
add a comment |
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
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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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()
add a comment |
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()
add a comment |
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()
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()
edited Nov 18 '18 at 22:52
answered Nov 18 '18 at 14:04
A. Maliampurakal
114
114
add a comment |
add a comment |
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
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
add a comment |
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
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
add a comment |
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
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
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
add a comment |
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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