I would like to implement a narrow search on the side menu of https://www.gumtree.com.au using Django.
For example, if you click Jobs on the global menu on this site, the side menu displays a subcategory of Jobs, which is a large category.Also, if you select a subcategory, the corresponding Post will be displayed in the center.
At this point, the URL is /BigCategory/ or /SmallCategory/.
Also, there is a category column like the one below.
Large Category
| Small Category
| - Small Category
Below this is
State
| Region
| Region
It is possible to narrow down the position.
If you select State, /BigCategory/State/ or /SmallCategory/State/ will display Post depending on the category you are currently selecting (large or smallCategory/State/
If you select Region, it will be /BigCategory/Region/ or /SmallCategory/Region/.
I'd like to implement these things.
The above URL is /Category/Location/, but when I thought about it myself and implemented it,
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:
# raise404
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:
# raise404
return render (request, 'classifieds/index.html', c)
In the future, when I try to implement not only categories and locations, but also other options such as narrowing down, it will be a very long code that is hard to understand if I separate everything.
What I would like you to teach me is
URL How to separate URLs
If /BigCategory/SmallCategory/State/Region/, the implementation will be much easier than now, but if /BigCategory or SmallCategory/State or Region/, the URL will be shorter, so I would like to do this.Please tell me how to write an ideal view to achieve this
上記 I don't know Django yet, so I hit him hard, so please teach me how to review the entire code and the system itself.
For example, using custom template tags like this makes it easier.
Ideally, it is a reference site described at the beginning.
Please help me.
Considering the following, I think it can be implemented simply.
The differences between the models are as follows:
1. Whether BigCategory and SmallCategory have parent or not
2. Whether State and Region have parent or not
Considering this difference, it would be good to combine each into a single model.
class Category (models.Model):
# Have both BigCategory and SmallCategory roles
parent=models.ForeignKey(Category, related_name='children', null=True, blank=True)
name=models.CharField(max_length=255)
slug=models.SlugField()
def__str__(self):
return self.name
class Location (models.Model):
# Have both State and Region roles
parent=models.ForeignKey (State, related_name='children', null=True, blank=True)
name=models.CharField(max_length=255)
slug=models.SlugField()
Data so far can be retrieved as follows:
#BigCateogry (no parent)
Category.objects.filter (parent__isnull=True)
# SmallCategory
Category.objects.filter (parent__isnull=False)
# State (no parent)
Location.objects.filter (parent__isnull=True)
# region
Location.objects.filter(parent__isnull=False)
Also, by devising the Model method and QuerySet, we can implement the view without writing many conditional branches.Here is an example.(I didn't actually move it, so it might not work well.Please keep it for reference only)
models.py
class Category (models.Model):
parent=models.ForeignKey(Category, related_name='children', null=True, blank=True)
name=models.CharField(max_length=255)
slug=models.SlugField()
@property
default big_cat(self):
# If parent is null, return yourself as it is a parent category
if not self.parent:
return self
# Otherwise return parent category (parent)
else:
return self.parent
def__str__(self):
return self.name
class Location (models.Model):
parent=models.ForeignKey (State, related_name='children', null=True, blank=True)
name=models.CharField(max_length=255)
slug=models.SlugField()
@property
def state(self):
# If the parent is null, it is State, so return yourself.
if not self.parent:
return self
# Otherwise return State(parent)
else:
return self.parent
def__str__(self):
return self.name
classPostQuerySet(models.QuerySet):
def filter_category(self, category):
if not category.parent:
# If it's a Big Category, filter the Posts that belong to the children category.
return self.filter(category__in=category.children.all())
else:
# For Small Category, filter the Posts belonging to the category.
return self.filter(category=category)
def filter_location(self, location):
if not location.parent:
# If it is State, filter the Post belonging to the location of children.
return self.filter(location__in=location.children.all())
else:
# If it is a Region, filter the Post belonging to that location.
return self.filter(location=location)
class Post (models.Model):
category=models.ForeignKey(Category)
location=models.ForeignKey (Location)
title=models.CharField(max_length=255)
text=models.CharField(max_length=255)
objects=PostQuerySet.as_manager()
def__str__(self):
return self.title
views.py
from django.shortcuts import get_object_or_404
from.models import Category, Location, Post
def cat_index(request, cat):
category=get_object_or_404(Category,slug=cat)
return render(request, 'classifieds/index.html', {
'big_cat': category.big_cat,
'states': Location.objects.filter(parent__isnull=True).all(),
'posts': Post.objects.filter_category(category).all()
})
def loc_index(request, cat, loc):
category=get_object_or_404(Category,slug=cat)
location=get_object_or_404(Location,slug=loc)
ctx = {
'big_cat': category.big_cat,
'state': location.state,
'posts': Post.objects.filter_category(category).filter_location(location).all()
}
if not category.parent:
ctx.update({'selected_cat':'big'})
else:
ctx.update({'small_cat_for_loc':category})
return render (request, 'classifieds/index.html', ctx)
© 2024 OneMinuteCode. All rights reserved.