justStarting
justStarting

Reputation: 129

Filter - How to implement

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:

Image

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

Answers (1)

Gasanov
Gasanov

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

Related Questions