Djangoの絞込検索について
Djangoを用いてhttps://www.gumtree.com.auのサイドメニューにある絞込検索を実装したいと思っています。
例としてこのサイトでグローバルメニューにあるJobsをクリックするとサイドメニューに大カテゴリーであるJobsの小カテゴリーが表示されます。また小カテゴリーを選択するとそれに応じたPostが中央にリストで表示されます。
この時点でURLは/BigCategory/、または/SmallCategory/となっています。
また下のようなカテゴリー欄があり
大カテゴリー
|ー小カテゴリー
|ー小カテゴリー
この下には
State
|ーRegion
|ーRegion
と位置の絞込ができるようになっています。
もしStateを選択すると今選択しているカテゴリー(大カテゴリーか小カテゴリー)に応じて/BigCategory/State/か/SmallCategory/State/でPostが表示されます。
Regionを選択した場合は/BigCategory/Region/か/SmallCategory/Region/となります。
これらのことを実装したいのですが
上記のURLについてまとめると/Category/Location/となりますが、これを自分で考えて実装してみたところ、
urls.py
urlpatterns = [
url(r'^(?P<cat>[-\w]+)/(?P<loc>[-\w]+)/$', views.loc_index, name='index'),
url(r'^(?P<cat>[-\w]+)/$', views.cat_index, name='index'),
]
models.py
class BigCategory(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
def __str__(self):
return self.name
class SmallCategory(models.Model):
parent = models.ForeignKey(BigCategory, related_name='children')
name = models.CharField(max_length=255)
slug = models.SlugField()
def __str__(self):
return self.name
class State(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField()
def __str__(self):
return self.name
class Region(models.Model):
parent = models.ForeignKey(State, related_name='children')
name = models.CharField(max_length=255)
slug = models.SlugField()
def __str__(self):
return self.name
class Post(models.Model):
category = models.ForeignKey(SmallCategory)
location = models.ForeignKey(Region)
title = models.CharField(max_length=255)
text = models.CharField(max_length=255)
def __str__(self):
return self.title
views.py
from .models import BigCategory, SmallCategory, State, Region, Post
def cat_index(request, cat):
if BigCategory.objects.filter(slug=cat):
# cat == big
big_cat = BigCategory.objects.get(slug=cat)
states = State.objects.all()
posts = Post.objects.filter(category__parent__slug=cat)
c = {'big_cat': big_cat, 'states': states, 'posts': posts}
elif SmallCategory.objects.filter(slug=cat):
# cat == small
big_cat = BigCategory.objects.get(children__slug=cat)
states = State.objects.all()
posts = Post.objects.filter(category__slug=cat)
c = {'big_cat': big_cat, 'states': states, 'posts': posts}
else:
# raise 404
return render(request, 'classifieds/index.html', c)
def loc_index(request, cat, loc):
if BigCategory.objects.filter(slug=cat):
# cat == big
big_cat = BigCategory.objects.get(slug=cat)
selected_cat = 'big'
if State.objects.filter(slug=loc):
state = State.objects.get(slug=loc)
posts = Post.objects.filter(category__parent__slug=cat, location__parent__slug=loc)
c = {'big_cat': big_cat, 'selected_cat': selected_cat, 'state': state, 'posts': posts}
elif Region.objects.filter(slug=loc):
state = State.objects.get(children__slug=loc)
posts = Post.objects.filter(category__parent__slug=cat, location__slug=loc)
c = {'big_cat': big_cat, 'selected_cat': selected_cat, 'state': state, 'posts': posts}
else:
print('no location')
elif SmallCategory.objects.filter(slug=cat):
# cat == small
big_cat = BigCategory.objects.get(children__slug=cat)
selected_cat = 'small'
small_cat_for_loc = SmallCategory.objects.get(slug=cat)
if State.objects.filter(slug=loc):
state = State.objects.get(slug=loc)
posts = Post.objects.filter(category__slug=cat, location__parent__slug=loc)
c = {'big_cat': big_cat, 'small_cat_for_loc': small_cat_for_loc, 'state': state, 'posts': posts}
elif Region.objects.filter(slug=loc):
state = State.objects.get(children__slug=loc)
posts = Post.objects.filter(category__slug=cat, location__slug=loc)
c = {'big_cat': big_cat, 'small_cat_for_loc': small_cat_for_loc, 'state': state, 'posts': posts}
else:
print('no location')
else:
# raise 404
return render(request, 'classifieds/index.html', c)
このようになりましたが、将来的にカテゴリーや位置だけでなく他のオプションである絞込も実装しようとしたときにいちいち全ての場合分けをしていたらとてもわかりづらく長いコードになってしまいます。
ご教授頂きたいのは、
①URLの場合分けの方法
/BigCategory/SmallCategory/State/Region/とすれば実装は今よりはるかに楽になるのですが、/BigCategory or SmallCategory/State or Region/とすればURLも短くなるのでこのようにしたいです。これを実現するために理想的なviewの書き方をご教授ください。
②上記に記載したコードは私にまだDjangoの知識がなく、がむしゃらに書く殴ったものなのでコード全体、そしてシステム自体の見直しをするにあたっての手ほどきをお願い致します。
例えばカスタムテンプレートタグをこんな風に使えばより楽になる、等
理想は冒頭に記載した参考サイトです。
どうかお助けください。