概要
Djangoで検索ボックスを作っている時に、姓だけで検索、名だけで検索はできるがフルネームで検索したいという気分だったのでやり方を調べてみました。
モデルについては社員が複数人おり、複数のオフィスに属する可能性があるのでmanyToManyで作成しております。
models.py
from django.db import models
class Office(models.Model):
name = models.CharField("営業所名", max_length=50)
code = models.CharField("営業所記号", max_length=10, null=True, blank=True)
def __str__(self):
return self.name
class Employee(models.Model):
employeeNo = models.CharField(
"社員番号",
null=True,
blank=True,
max_length=5,
unique=True
)
lastName = models.CharField("姓", max_length=30)
firstName = models.CharField("名", max_length=30)
lastName_furigana = models.CharField("姓フリガナ", max_length=30)
firstName_furigana = models.CharField("名フリガナ", max_length=30)
belong_to_office = models.ManyToManyField(Office)
date_of_employment = models.DateField("入社日", blank=True, null=True)
date_of_leaving = models.DateField("退社日", blank=True, null=True)
created_at = models.DateTimeField("作成日", auto_now_add=True)
updated_at = models.DateTimeField("更新日", auto_now=True)
def __str__(self):
return self.lastName + self.firstName
views.py
from django.views.generic import ListView
from django.db.models.functions import Concat
from django.db.models import Q
from .models import Employee, Office
class EmployeeListView(LoginRequiredMixin, ListView):
model = Employee
template_name = "manager/employee_list.html"
paginate_by = 50
def get_queryset(self):
q_word = self.request.GET.get('query')
if q_word:
# 空白文字を完全に削除する
q_word = q_word.replace(' ','')
q_word = q_word.replace(' ','')
# フルネームフィールドを追加して検索条件に追加
object_list = Employee.objects.annotate(full_name=Concat('lastName','firstName')).filter(
Q(lastName__icontains=q_word) |
Q(firstName__icontains=q_word) |
Q(lastName_furigana__icontains=q_word) |
Q(firstName_furigana__icontains=q_word) |
Q(employeeNo__icontains=q_word) |
Q(belong_to_office__name__icontains=q_word) |
Q(belong_to_office__code__icontains=q_word) |
Q(full_name__icontains=q_word)
).order_by('pk').distinct()
else:
object_list = Employee.objects.all().order_by('pk')
return object_list
employee_list.html
省略
<div class="col-12 col-lg-6">
<form action="" method="get">
<div class="input-group">
<input name="query" class="form-control" type="text" placeholder="検索条件を入力"
value="{{ request.GET.query }}" aria-label="Search for..."
aria-describedby="btnNavbarSearch" />
<button class="btn btn-primary" type="submit"><i class="fas fa-search"></i></button>
</div>
</form>
</div>
ポイント
ポイントとしてはEmployee.object.annotateでfull_nameというフィールドを新しく追加してその中身に、元々のlastNameフィールドの値とfirstNameのフィールドをConcatを使って結合してから入れている所です。