Code review and perfomance tips

32 views
Skip to first unread message

Горобец Дмитрий

unread,
Jul 15, 2016, 1:31:31 PM7/15/16
to Django users
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

Main part of code looks:
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.

Reply all
Reply to author
Forward
0 new messages