Reputation: 129
I need to implement multi-choice filter in my Django software. I have my model (database):
models.py
class Autor(models.Model):
naziv = models.CharField(max_length=30, null=False, blank=True)
email = models.EmailField(max_length=75, null=True, blank=True)
def __str__(self):
return str(self.naziv)
class Clanak(models.Model):
naslov = models.CharField(null=False, blank=True, max_length=120)
datumObjave = models.DateField(null=False, blank=False)
autor = models.ForeignKey(Autor, on_delete=models.CASCADE, null=True)
def __str__(self):
return str(self.naslov) + ', ' + str(self.datumObjave) + ', ' + str(self.autor)
My urls.py:
urlpatterns = [
path('filtar/',views.filtar, name='filtar'),
]
Views.py:
def filtar(request):
form = ChoiceForm(request.GET or None)
data = Clanak.objects.all()
if form.is_valid():
if 'Choice 1' in form.cleaned_data['filter']:
data = data.filter(naslov='name')
if 'Choice 2' in form.cleaned_data['year']:
data = data.filter(datumObjave__year='year')
return render(request, 'filtar.html', {'data': data, 'form': form})
Filtar.html:
<!DOCTYPE html>
<html>
<head>
{% extends 'base.html' %}
{% block main_content %}
<title></title>
</head>
<body>
<table border="1">
<tr>
<th>Naslov</th>
<th>Datum</th>
<th>Autor</th>
</tr>
{% for x in data %}
<tr>
<td>{{x.naslov}}</td>
<td>{{x.datumObjave}}</td>
<td>{{x.autor}}</td>
</tr>
{% endfor %}
</table>
</body>
</html>
{% endblock %}
footer.html
<br>
<div>Filter: </div>
<form>
{% csrf_token %}
<fieldset>
<legend>Filtar - Thing that is being chosen</legend>
{{ form.as_p }}
<input type="submit" value="Submit">
</fieldset>
</form>
<br>
<div>Copyright by </div>
Forms.py
class ChoiceForm(forms.Form):
filter = forms.MultipleChoiceField(choices=(('Choice 1', 'Choice 1'), ('Choice 2', 'Choice 2')), widget=forms.CheckboxSelectMultiple)
name = forms.CharField(label='name')
year = forms.CharField(label='year')
Screenshot:
Now my question is:
My problem is that whatever I write in textfields it do nothing, just refresh page with all same data. Name of dynamically created textboxes should be "nameinput" and "yearinput"
Upvotes: 0
Views: 72
Reputation: 3399
Your form is going to send GET
request to the same page. So when view start processing, it fetch both choice values (if they exists), get all Clanak
objects and filter them based on selected choices.
This way if no filters selected, you will get all objects. If both filters selected, it will filter both on names and year.
def filtar(request):
choice1 = request.GET.get('Autor', None)
choice2 = request.GET.get('Datum', None)
data = Clanak.objects.all()
if choice1:
data = data.filter(naslov='NAME')
if choice2:
data = data.filter(datumObjave__year=2019)
return render(request, 'filtar.html', {'data': data})
Note that it will not actually execute query before you try to access it (i.e. not until you render html).
Additionally, I would suggest you switch this form to django form, like this:
forms.py:
class ChoiceForm(forms.Form):
filter = forms.MultipleChoiceField(choices=(('Choice 1', 'Choice 1'), ('Choice 2', 'Choice 2')), widget=forms.CheckboxSelectMultiple)
views.py:
def filtar(request):
form = ChoiceForm(request.GET or None)
data = Clanak.objects.all()
if form.is_valid():
if 'Choice 1' in form.cleaned_data['filter']:
data = data.filter(naslov='NAME')
if 'Choice 2' in form.cleaned_data['filter']:
data = data.filter(datumObjave__year=2019)
return render(request, 'filtar.html', {'data': data, 'form': form})
footer.html:
<br>
<div>Filter: </div>
<form>
{% csrf_token %}
<fieldset>
<legend>Filtar - Thing that is being chosen</legend>
{{ form.as_p }}
<input type="submit" value="Submit">
</fieldset>
</form>
<br>
<div>Copyright by </div>
Upvotes: 1