Как включить «Нет» в сравнение lte / gte? - PullRequest
2 голосов
/ 07 октября 2010

У меня есть этот сложный механизм фильтрации ...

d = copy(request.GET)
d.setdefault('sort_by', 'created')
d.setdefault('sort_dir', 'desc')
form = FilterShipmentForm(d)
filter = {
    'status': ShipmentStatuses.ACTIVE
}
exclude = {}
if not request.user.is_staff:
    filter['user__is_staff'] = False

if request.user.is_authenticated():
    exclude['user__blocked_by__blocked'] = request.user

if form.is_valid():
    d = form.cleaned_data
    if d.get('pickup_city'): filter['pickup_address__city__icontains'] = d['pickup_city']
    if d.get('dropoff_city'): filter['dropoff_address__city__icontains'] = d['dropoff_city']
    if d.get('pickup_province'): filter['pickup_address__province__exact'] = d['pickup_province']
    if d.get('dropoff_province'): filter['dropoff_address__province__exact'] = d['dropoff_province']
    if d.get('pickup_country'): filter['pickup_address__country__exact'] = d['pickup_country']
    if d.get('dropoff_country'): filter['dropoff_address__country__exact'] = d['dropoff_country']
    if d.get('min_price'): filter['target_price__gte'] = d['min_price']
    if d.get('max_price'): filter['target_price__lte'] = d['max_price']
    if d.get('min_distance'): filter['distance__gte'] = d['min_distance'] * 1000
    if d.get('max_distance'): filter['distance__lte'] = d['max_distance'] * 1000
    if d.get('available_on'): # <--- RELEVANT BIT HERE ---
        filter['pickup_earliest__lte'] = d['available_on'] # basically I want "lte OR none"
        filter['pickup_latest__gte'] = d['available_on']
    if d.get('shipper'): filter['user__username__iexact'] = d['shipper']

order = ife(d['sort_dir'] == 'desc', '-') + d['sort_by']

shipments = Shipment.objects.filter(**filter).exclude(**exclude).order_by(order) \
    .annotate(num_bids=Count('bids'), min_bid=Min('bids__amount'), max_bid=Max('bids__amount'))

И теперь мой клиент говорит мне, что он хочет, чтобы даты получения / отмены были «гибкими» в качестве опции.Поэтому я обновил базу данных, чтобы для этой цели даты были равны NULL, но теперь фильтр «доступен для получения» не будет работать должным образом.Это должно включать NULL / None даты.Есть ли простое решение для этого?

Ответы [ 3 ]

10 голосов
/ 07 октября 2010

Переверните логику и используйте exclude().Что вы действительно хотите сделать, так это исключить любые данные, в которых указана дата, которая не подходит.Если pickup_latest и pickup_earliest равны NULL, он не должен совпадать с запросом исключения и не будет удален.Например,

exclude['pickup_latest__lt'] = d['available_on']
exclude['pickup_earliest__gt'] = d['available_on']
3 голосов
/ 07 октября 2010

Большинство механизмов баз данных не любят реляционные сравнения со значениями NULL.Используйте <field>__isnull, чтобы явно проверить, является ли значение NULL в базе данных, но вам нужно будет использовать Q объекты до OR условия вместе.

0 голосов
/ 07 октября 2010

Не думайте, что это на самом деле специфический для Джанго вопрос.Переменная 'd' - это словарь Python, нет?Если это так, вы можете использовать это:

filter['pickup_latest__gte'] = d.get('available_on', None)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...