I am sorry if it question might turn to be little broad, but since I am just learning django (and I am just hobbyist developer) I need some guidance which, I hope, will help someone like me in the future since I could not find any clear and easily comprehensible guide on using this widget. With your answers and help I will try to make this question thread at least guide-ish.
Material I found somewhat helpful for this topic:
Django: Replacement for the default ManyToMany Widget of Forms
Django's FilteredSelectMultiple widget only works when logged in
Django FilteredSelectMultiple not rendering on page
Use the Django admin app's FilteredSelectMultiple widget in form
Get the chosen values from FilteredSelectMultiple widget in Django
Django FilteredSelectMultiple Right Half Does Not Render
There were few others links, but they did not made anything clearer or added new information so I won't mention them.
Here is what I managed to understand (please correct me if I am wrong or add anything that I missed):
To create FilteredSelectMultiple
widget firs I need to amend forms.py
(as in any other widget creation process). Amended forms.py
should have from django.contrib.admin.widgets import FilteredSelectMultiple
import and Media
class. forms.py
code should look like this (please correct me, because probably it is wrong somewhere):
from django import forms
from catalog.models import DrgCode
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.conf import settings #without it I get an error that settings not defined
class CalculatorForm(forms.Form):
drg_choice = forms.ModelMultipleChoiceField(queryset=DrgCode.objects.all(), widget=FilteredSelectMultiple("Somethings", is_stacked=False), required=True)
class Media:
css = {
'all': (os.path.join(settings.BASE_DIR, '/static/admin/css/widgets.css'),),
}
js = ('/admin/jsi18n',)
Questions about this part:
- Am I right about
django.conf
import? Since I did not see it imported in any material I found. Answer: during my test I determined thatdjango.conf
import is necessary if usingsettings.BASE_DIR
part. In various sources there was two ways of writingcss
path, this one worked for me. - Do I need to create
widgets.css
and corresponding directory? Or django will find it itself? Since there is no such file or directory generated after I created skeleton-website usingdjango-admin startproject
cmd? Answer: No. There is no need to createwidgets.css
or any of the files since django finds them itself. - Same question as previous for
jsi18n
part. Also what is this? I assume its javascript file, but it has no extension for some reason. Also I cannot find it anywhere? Should I create it? How to do that? Or I can copy it from somewhere? Partial answer: no need to create it. Just point at it inurls.py
. Still do not know exactly that kind of file it is (or where it is)
After amending forms.py
I should ammend urls.py
by adding url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', name='jsi18n')
So urls.py
now look like this:
from django.urls import path
from . import views
from django.conf.urls import url
urlpatterns = [
path('', views.index, name='index'),
'django.views.i18n.javascript_catalog',
name='jsi18n'),
]
Questions:
- Am I doing it wright or should I just add it below
urlpatterns
? Answer: This method if fine.
Now I need to set HTML
template file for form to render (like in any other case). Code for it (file named DrgCalculator.html
):
{% extends "base_generic.html" %}
<script type="text/javascript" src="{% url 'jsi18n' %}" > </script>
{{ form.media }}
<form enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Submit</button>
</form>
- This part seems more or less clear. But maybe I should amend something or know about? Answer: Should be changed. Will write full code below.
Lastly I need to adjust views.py
to set where this form and everything related with it happens.
From what I understand code in this part is more or less is not directly related with widget, but to complete everything and make working example I will use code I leaned/got in this (very good) django tutorial:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
from catalog.models import DrgCode
from catalog.forms import CalculatorForm
def DrgCalculator(request):
if request.method == 'POST':
form = CalculatorForm(request.POST)
if form.is_valid():
return render(request, 'DrgCalculator.html')
context = {
'form': form,
}
return render(request, 'DrgCalculator.html', context)
Questions:
- Any remarks on this part of the code? Answer: Missing
else: form = DrgCalculator()
. Will write amended code below. How I will access values which user choose using
FilteredSelectMultiple
? I imagine I should clean data informs.py
like with other widgets. So I should add nested function below to myclass CalculatorForm
informs.py
am I right? Answer: Yes, data should be cleaned like in other cases. Function is correct.def clean_CalculatorForm(self): drg_choice = self.cleaned_data['drg_choice'] return drg_choice
Data I will get after cleaning will be list or dictionary? Am I right? Answer: No, from this widget user input received as QuerySet
That is all my questions, sorry for long thread, I tried to make it as clear as possible. If I need to clarify something, please let me know. I will try to edit and update this, to make it friendly for people who will read it in future.
EDIT1: Answered some of my questions.
EDIT2: Answered rest of my questions.