Hello, everybody.
I'm working on one project where I need to render cities on the page in 1-4 columns like this. I'm rendering cities using 'regroup' filter:
A D M U
Aberdeen Danbury Macomb Ukiah
Akron Delano Mandan Urbana
Manhattan
B H P W
Babylon Haledon Pace Waipio
Bangor Hanover Walker
C I R
Calhoun Indiana Raleigh
Calipatria Irondale Ridge
Cheval Riverdale
def get_columns(location):
qs = Location.objects.filter(parent=location, active=True)
qs = qs.annotate(first_char=Upper(Substr('name', 1, 1)))
locations = qs.values()
first_chars = qs.distinct('first_char').order_by('first_char')
first_chars = first_chars.values_list('first_char', flat=True)
first_chars_count = len(first_chars)
num_of_columns = 4 if (first_chars_count / 4) >= 1 else first_chars_count
chars_per_column = math.ceil(first_chars_count / num_of_columns)
start = 0
stop = chars_per_column
for i in range(num_of_columns):
yield [location for location in locations
if location['first_char'] in first_chars[start:stop]]
start += chars_per_column
stop += chars_per_column
It can be rewritten using QuerySet filter, but this approach adds more queries in database:
def get_columns(location):
qs = Location.objects.filter(parent=location, active=True)
qs = qs.annotate(first_char=Upper(Substr('name', 1, 1)))
first_chars = qs.distinct('first_char').order_by('first_char')
first_chars = first_chars.values_list('first_char', flat=True)
first_chars_count = len(first_chars)
num_of_columns = 4 if (first_chars_count / 4) >= 1 else first_chars_count
chars_per_column = math.ceil(first_chars_count / num_of_columns)
start = 0
stop = chars_per_column
for i in range(num_of_columns):
yield qs.filter(first_char__in=first_chars[start:stop])
start += chars_per_column
stop += chars_per_column
Which is better? Filter using list comprehension or using queryset filter?
Thanks.