Блог Андрея Федосеева

In English

Сниппеты #1

Опубликовано

Время от времени буду выкладывать небольшие кусочки кода собственного сочинения. Буду рад, если кому-то они пригодятся. И ещё больше рад, если кто-то придумает, как их улучшить. Сегодня таких кусочков будет два.

Номер раз. Дано: Django и модель с несколькими текстовыми полями. Надо сделать простейший поиск по этим полям. При этом достаточно, чтобы искомый текст содержался хотя бы в одном поле. И самое интересное — список полей для поиска заранее не определён, он может варьироваться.

1
2
3
4
5
6
7
from django.db import models

class MyModel(models.Model):

    field_1 = models.CharField(max_length=100)
    field_2 = models.CharField(max_length=100)
    field_3 = models.CharField(max_length=100)

Поиск по одному полю сделать просто:

1
MyModel.objects.filter(field_1__icontains=search_term)

В случае с несколькими полями их нужно соединить оператором OR. В Django это делается так:

1
2
3
MyModel.objects.filter(
    models.Q(field_1__icontains=search_term) | models.Q(field_2__icontains=search_term)
)

А что делать, если полей много и они заранее не известны? Например, названия полей хранятся в списке:

1
fields_to_search = ["field_1", "field_2", "field_3"]

Я сделал вот так:

1
2
3
4
5
6
7
8
from operators import or_

MyModel.objects.filter(
    reduce(or_, map(
        lambda f: models.Q(**{f+"__icontains":search}),
        fields_to_search)
    ))
)

Номер два. Надо узнать дату первого дня текущей недели. Например, сегодня пятница, 23 сентября 2011 года. В этом случае, какое число было в понедельник?

Я сделал вот так:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import datetime
import calendar

today = datetime.date.today()
cal = calendar.Calendar()

# Или, если неделя начинатеся с воскресенья
# cal = calendar.Calendar(6)

week_start_date = None  # Сюда мы сохраним искомую дату
for week in cal.monthdatescalendar(today.year, today.month):
    if today in week:
        week_start_date = week[0]
        break

Комментарии

Написать комментарий
Dmitriy Baranov

from datetime import datetime, timedelta today = datetime.today() today - timedelta(days=today.weekday()) datetime.datetime(2011, 9, 19, 8, 6, 40, 416497)

Dmitriy Baranov

кхм, простите за битую разметку

Андрей Федосеев

Всё верно, но в этом случае всегда возвращается понедельник. А что если неделя начинается в воскресенья?

Dmitriy Baranov

Конпенсируй один день, за исключением воскресения:

today - timedelta(days=today.weekday()+(today.weekday()==6 and -6 or 1))

Пример неного грязен, но в одну строку.

Anatoly Bubenkov

по поиску плюсадин Андрею по дате плюсадин Диме

Sergey Fedoseev

Я бы вместо map использовал генераторное выражение.

Можно использовать разметку Markdown.
 
Необязательно.