Фильтрация поиска в django
Новичок в django, нужна помощь, пытаюсь реализовать фильтрацию поиска в django(сам поиск уже реализовал). Хочу выбирать пункты area(frontend, backend, etc.) и keywords(python, php, js, etc.) из моей таблицы Experience и по этим полям уже вести поиск. Допустим я выбираю в 'area' backend в 'keywords' python нажимаю кнопку поиск и он мне показывает всех Person, у которых area=backend и keywords=python . Поиск который я реализовал ищет по выбранным полям таблицы Person.
Мой файл views.py
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from main_page.models import *
from django.contrib.postgres.search import SearchQuery, SearchVector
class HomeView(ListView):
"""
This is our home page
"""
template_name = 'main_page/index.html'
model = Person
class SearchPageView(ListView):
"""
This is our search page
"""
template_name = 'main_page/search.html'
model = Person
paginate_by = 8
context_object_name = 'persons_item'
class SearchResView(ListView):
"""
Search results will be here
"""
model = Person
template_name = 'main_page/search_res.html'
paginate_by = 8
def get_queryset(self):
"""
Search fild functional realisation
input data: str
return: ur Model object with ur input params else None
"""
q = self.request.GET.get('q')
vector = SearchVector('first_name', 'surname', 'location', 'last_position', 'event', 'total_duration')
query = SearchQuery(q)
object_list = Person.objects.annotate(search=vector).filter(search=query)
return object_list
def get_context_data(self, **kwargs):
"""
The same as previous but it needs for
Functional implementation required for pagination
"""
context = super().get_context_data(**kwargs)
context['query'] = self.request.GET.get('q')
return context
class PersonView(DetailView):
"""
Full info link realisation
"""
context_object_name = 'person_item'
template_name = 'main_page/person_view.html'
model = Person
Models.py
from django.db import models
from django.urls import reverse
class Person(models.Model):
"""
Our general model
"""
first_name = models.CharField(max_length=150)
surname = models.CharField(max_length=150)
url = models.CharField(max_length=500)
location = models.CharField(max_length=150, blank=True)
last_position = models.CharField(max_length=150, blank=True)
event = models.CharField(max_length=100, blank=True)
event_date = models.CharField(max_length=100, blank=True)
total_duration = models.FloatField(blank=True, default=0, null=True)
person_hash_index = models.CharField(max_length=100, primary_key=True, null=False)
def get_absolute_url(self):
return reverse('person_view', kwargs={'pk': self.pk})
def __str__(self):
return self.first_name
class Meta:
ordering = ['first_name']
class Education(models.Model):
"""
Person education table
This table are inherited from Person table
"""
edu_id = models.CharField(max_length=100, primary_key=True, null=False)
person = models.ForeignKey('Person', on_delete=models.CASCADE, related_name='person_education')
university = models.CharField(max_length=150)
degree = models.CharField(max_length=150)
info = models.CharField(max_length=65000, blank=True)
admission_date = models.CharField(max_length=150)
graduation_date = models.CharField(max_length=150)
def __str__(self):
return '%s, %s, %s, %s, %s' % (
self.university, self.degree, self.info, self.admission_date, self.graduation_date
)
class Meta:
ordering = ['university']
class Experience(models.Model):
"""
Person Experience table
This table are inherited from Person table
"""
exp_id = models.CharField(max_length=100, primary_key=True, null=False)
person = models.ForeignKey('Person', on_delete=models.CASCADE, related_name='person_experience')
company = models.CharField(max_length=150)
position = models.CharField(max_length=150)
hiring_date = models.CharField(max_length=150)
fired_date = models.CharField(max_length=150)
job_location = models.CharField(max_length=150)
description = models.CharField(max_length=65535, blank=True)
duration = models.FloatField() # mb datetime
exp_index = models.CharField(max_length=50, blank=True)
area = models.CharField(max_length=2000, blank=True, null=True)
keywords = models.CharField(max_length=2000, blank=True, null=True)
def __str__(self):
return '%s, %s, %s, %s, %s, %s' % (
self.company, self.position, self.hiring_date, self.fired_date, self.job_location, self.description
)
class Meta:
ordering = ['exp_index']
Шаблон поиска search.html
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Search</title>
<link rel="stylesheet" href="{% static 'main_page/css/reset.css'%}">
<link rel="stylesheet" href="{% static 'main_page/css/search.css'%}">
<link rel="stylesheet" href="{% static 'main_page/css/sidebar.css'%}">
<link rel="stylesheet" href="{% static 'main_page/css/footer.css'%}">
<link rel="stylesheet" href="{% static 'main_page/css/pagination.css'%}">
<link rel="stylesheet" href="{% static 'main_page/css/table.css'%}">
<link rel="stylesheet" href="{% static 'main_page/css/person_view.css'%}">
</head>
<body>
<!--header-->
<div class='search_res'>
<div class="container">
<header class="header">
<div class="header__inner">
<a class="logo" href="{% url 'home' %}">
ITI<span>VA</span>
</a>
<section class="top_nav">
<input id="menu_toggle" type="checkbox"/>
<label class="menu_button_container" for="menu_toggle">
<div class="menu_button"></div>
</label>
<ul class="menu">
{% if user.is_authenticated %}
<li class="list">
<a class="nav__link" href="{% url 'search_page' %}">Search</a>
</li>
<li class="list">
<a class="nav__link" href="{% url 'logout' %}">Logout</a>
</li>
{% else %}
<li class="list">
<a class="nav__link" href="{% url 'signup' %}">Signup</a>
</li>
<li class="list">
<a class="nav__link" href="{% url 'login' %}">Login</a>
</li>
{% endif %}
</ul>
</section>
<ul class="links">
<li class="list">
<a class="nav__link" href="{% url 'search_page' %}">Search</a>
<div class="home_underline"></div>
</li>
{% if user.is_authenticated %}
<li class="list">
<a class="nav__link" href="{% url 'logout' %}">Logout</a>
<div class="home_underline"></div>
</li>
{% else %}
<li class="list">
<a class="nav__link" href="{% url 'signup' %}">Signup</a>
<div class="home_underline"></div>
</li>
<li class="list">
<a class="nav__link" href="{% url 'login' %}">Login</a>
<div class="home_underline"></div>
</li>
{% endif %}
</ul>
</div>
</header>
<!--sidebar-->
{% block sidebar %}
<div class="search_res__inner">
<aside class="sidebar">
<form action="{% url 'search_res' %}" method="get">
{% csrf_token %}
<input
class="search__input"
type="text"
id="searchbar"
value=""
placeholder="Search here..."
required
name="q">
<button type="submit" class="search__btn"></button>
</form>
<div class="sidebar__content">
<p>Выбираем Area далее выбираем Technology далее выбираем Framework</p>
{% for i in person.person_experience.all %}
<p>{{i.area}}</p>
{% endfor %}
</div>
</aside>
{% endblock %}
{% block table %}
<div class="search_res__content">
<table>
<thead>
<tr>
<th>Name</th>
<th>Location</th>
<th>Last_position</th>
<th>Total duration</th>
<th>Event</th>
<th>Event Date</th>
<th>Full info</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
{% if object_list %}
<tr>
<td>{{ object.first_name }} {{ object.surname }}</td>
<td>{{ object.location }}</td>
<td>{{ object.last_position }}</td>
<td>{{ object.total_duration|floatformat:1 }}</td>
<td>{{ object.event }}</td>
<td>{{ object.event_date }}</td>
<td>
<a href="{{ object.get_absolute_url }}">View</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% if page_obj.has_other_pages %}
<nav data-pagination>
<ul>
{% for p in page_obj.paginator.page_range %}
{% if page_obj.number == p %}
<li class=current><a href="?page={{ p }}">{{ p }}</a>
{% elif p > page_obj.number|add:-3 and p < page_obj.number|add:3 %}
<li><a href="?page={{ p }}">{{ p }}</a>
{% endif %}
{% endfor %}
</ul>
<!-- add next, previous and firs page, last page buttons -->
<!-- add Up, down button will be here-->
</nav>
{% endif %}
{% endblock %}
</div>
</div>
</div>
</div>
</body>
</html>
Шаблон результатов поиска search_res.html
{% extends 'main_page/search.html' %}
{% block table %}
<div class="container">
<table>
<thead>
<tr>
<th>Name</th>
<th>Location</th>
<th>Last_position</th>
<th>Total duration</th>
<th>Event</th>
<th>Event Date</th>
<th>Full info</th>
</tr>
</thead>
<tbody>
{% for object in object_list %}
{% if object_list %}
<tr>
<td>{{ object.first_name }} {{ object.surname }}</td>
<td>{{ object.location }}</td>
<td>{{ object.last_position }}</td>
<td>{{ object.total_duration|floatformat:1 }}</td>
<td>{{ object.event }}</td>
<td>{{ object.event_date }}</td>
<td>
<a href="{{ object.get_absolute_url }}">View</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
{% if page_obj.has_other_pages %}
<nav data-pagination>
<ul>
{% for p in page_obj.paginator.page_range %}
{% if page_obj.number == p %}
<li class=current><a href="/search_res?page={{ p }}&q={{ query }}">{{ p }}</a>
{% elif p > page_obj.number|add:-3 and p < page_obj.number|add:3 %}
<li><a href="/search_res?page={{ p }}&q={{ query }}">{{ p }}</a>
{% endif %}
{% endfor %}
</ul>
</nav>
{% endif %}
</div>
{% endblock %}
Шаблон просмотра полной информации человека person_view.html
{% extends 'main_page/search.html' %}
{% load static %}
{% block table %}
<div class="person_view">
<h2>
<a href="{{ person_item.url }}">{{ person_item.first_name }} {{ person_item.surname }}</a>
</h2><br/>
<p>
{{ person_item.event }} {{ person_item.event_date }}
</p>
<div class="person_view_list">
{% for exp in person_item.person_experience.all %}
<p>{{ exp.area }}</p>
<p>{{ exp.keywords }}</p>
<p style="font-size: 22px; font-weight: bold; line-height: 25px;">{{ exp.position }}</p>
<p style="font-weight: bold; font-size: 18px;">{{ exp.company }}</p>
<p style="font-size: 16px;">{{ exp.hiring_date }} - {{ exp.fired_date }} · {{ exp.duration}} года</p>
<p style="font-size: 16px;"> {{ exp.job_location }}</p>
<p style="font-size: 20px; margin-bottom: 25px; line-height: 25px;">{{ exp.description }}</p>
{% endfor %}
<hr>
<h2 style="margin-top: 20px;">Education</h2><br/>
{% for edu in person_item.person_education.all %}
<p style="font-size: 18px; font-weight: bold; line-height: 25px">{{ edu.university }}</p>
<p style="font-size: 18px;"> {{ edu.degree }} , {{ edu.info }}</p>
<p style="font-size: 18px;"> {{ edu.admission_date }} - {{ edu.graduation_date }}</p>
{% endfor %}
</div>
</div>
{% endblock %}