Python Django如何允许在IntegerRangeField中使用空范围
我使用IntegerRangeField(PostgreSQL的特定字段)来表示发行bancnote的年份 将对象添加到db并使用非空范围(如1990-2000)进行过滤时效果良好,但是只有很少的bancnotes是在一年内发布的,因此这段时间是2005-2005年。当这样设置范围时,对象添加到db后,该值变为“无” 似乎IntegerRangeField不接受空范围 我试着用blank=True,null=True来设置像“2005-(此处无值)”这样的范围,这对我来说很好,但在本例中,过滤器不适用于此对象 要更清楚,请查看以下示例:Python Django如何允许在IntegerRangeField中使用空范围,python,django,postgresql,django-filter,Python,Django,Postgresql,Django Filter,我使用IntegerRangeField(PostgreSQL的特定字段)来表示发行bancnote的年份 将对象添加到db并使用非空范围(如1990-2000)进行过滤时效果良好,但是只有很少的bancnotes是在一年内发布的,因此这段时间是2005-2005年。当这样设置范围时,对象添加到db后,该值变为“无” 似乎IntegerRangeField不接受空范围 我试着用blank=True,null=True来设置像“2005-(此处无值)”这样的范围,这对我来说很好,但在本例中,过滤器
- 2003-2008:正确显示和筛选
- 2003-2003:显示为“无”,过滤错误
- 2003年-(无值)/(无值)-2003年:显示为“2003无”/“无-2003”(对我来说令人满意),过滤器对此不起作用
{%extends'目录/base.html%}
{%block title%}目录{%endblock%}
{%load widget_tweaks%}
{%块边栏%}
-
{filter.form.type%中的类型为%1}
{%endfor%}
-
{%render\u field filter.form.par\u gt id='from'%}{%render\u field filter.form.par\u lt id='to'%}
{%render_field filter.form.year maxlength='4%}
搜寻
{%endblock%}
{%block content%}
{#在这里过滤#}
{filter.qs%中的bon的百分比}
{%if-forloop.counter0 |可除数为:“4”%}
{%endif%}
{%endfor%}
{%endblock%}
主要问题是没有正确存储范围。根据django postgres
在python中,所有范围字段都转换为,但如果不需要边界信息,也接受元组作为输入。默认为包含下限,不包含上限;也就是说,[)
总之,
无效,因为postgres有效地将空边界视为无穷大。过滤反过来会失败,因为无穷大存在于边界检查之外tuple(2005,None)
无效,因为Django默认为排除的上限。Postgres将tuple(20052005)
标准化为空,因为范围实际上不存在[20052005)
- 此外,您的
范围不正确,因为2008不包括在内。我很确定,如果您筛选的范围是2008到2010,它将被排除在外tuple(2003,2008)
tuple(20052006)
注意,bounds是一个字符串文本()Range(20052005,bounds='[]')
startwsith
和endswith
检查,我认为这是包括在内的。因此,在2005年到2005年对您的年份进行过滤应该会从数据库中产生预期值。一旦范围正确存储,过滤器应该正常工作
Postgres范围供参考。第8.17.5节包含关于边界行为和规范化的信息
示例范围:
from psycopg2.extras import NumericRange
NumericRange(2005, 2008, bounds='[]')
主要问题是没有正确存储范围。根据django postgres 在python中,所有范围字段都转换为,但如果不需要边界信息,也接受元组作为输入。默认值为包含下限,排除上限;即
[)
总之,
无效,因为postgres有效地将空边界视为无穷大。过滤反过来会失败,因为无穷大存在于边界检查之外tuple(2005,None)
无效,因为Django默认为排除的上限。Postgres将tuple(20052005)
标准化为空,因为范围实际上不存在[20052005)
- 此外,您的
范围不正确,因为2008不包括在内。我很确定,如果您筛选的范围是2008到2010,它将被排除在外tuple(2003,2008)
tuple(20052006)
注意,bounds是一个字符串文本()Range(20052005,bounds='[]')
startwsith
和endswith
检查,我认为这是包括在内的。因此,在2005年到2005年对您的年份进行过滤应该会从数据库中产生预期值。一旦范围正确存储,过滤器应该正常工作
参考的Postgres范围
from django import forms
import django_filters
from .models import Bancnote
class BancnoteFilter(django_filters.FilterSet):
type = django_filters.ChoiceFilter(name='type', choices=Bancnote.TYPE_CHOICES,
widget=forms.RadioSelect(attrs={'class': 'radio'}), empty_label=None)
par_gt = django_filters.NumberFilter(name='par', lookup_expr='gte', widget=forms.Select)
par_lt = django_filters.NumberFilter(name='par', lookup_expr='lte', widget=forms.Select)
year = django_filters.NumericRangeFilter(name='year', lookup_expr='contained_by')
class Meta:
model = Bancnote
fields = ['type', 'par_gt', 'par_lt', 'year']
from django.shortcuts import render, render_to_response
from django.template import RequestContext
from django.shortcuts import render
from .models import Bancnote
from .filters import BancnoteFilter
def index(request):
bons_list = Bancnote.objects.all().order_by('par')
bons_filter = BancnoteFilter(request.GET, queryset=bons_list)
def image(request):
bons = Bancnote()
variables = RequestContext(request, {
'bons': bons
})
return render_to_response('catalogue/bon_detail.html', variables)
{% extends 'catalogue/base.html' %}
{% block title %}Catalogue{% endblock %}
{% load widget_tweaks %}
{% block sidebar %}
<form method="get">
<div class="well bs-sidebar" id="style" style="background-color:#fff">
<ul class="nav nav-pills nav-stacked">
<li>
<a href="#" class="toggle-menu" onclick="showcontent('#money-type')">Bancnote type
<i class="fa fa-chevron-up"></i>
</a>
</li>
<div id="money-type">
<ul class="nav nav-pills nav-stacked">
{% for type in filter.form.type %}
<li><a href="#">
{{ type.tag }}
<label for="{{ type.id_for_label }}">{{ type.choice_label }}</label>
</a></li>
{% endfor %}
</ul>
</div>
<li>
<a href="#" class="toggle-menu" onclick="showcontent('#par')">Bancnote par
<i class="fa fa-chevron-up"></i>
</a>
</li>
<div id="par">
{% render_field filter.form.par_gt id='from' %}{% render_field filter.form.par_lt id='to' %}
</div>
<li><a href="#" class="toggle-menu" onclick="showcontent('#period')">Issue years
<i class="fa fa-chevron-up"></i></a></li>
<div id="period">
<div class="range-input">
{% render_field filter.form.year maxlength='4' %}
</div>
<div class="range-slider">
<input value="1917" min="1917" max="2017" step="1" type="range">
<input value="2017" min="1917" max="2017" step="1" type="range">
</div>
</div>
</ul>
<button type="submit" class="btn btn-primary" style="text-align: center; width: 100%">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</div>
</form>
{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
{# filtering here #}
{% for bon in filter.qs %}
{% if forloop.counter0|divisibleby:"4" %}
</div>
<div class="row">
{% endif %}
<div class="col-sm-3 col-lg-3">
<div style="display: block; text-align: center; margin: 0 auto">
<a href="{{ bon.id }}">
<img src="{{ bon.image.url }}" style="width: 50%; height: 50%"/>
<h5>{{ bon.par }} {{ bon.type }} {{ bon.year.lower}}-{{ bon.year.upper }}</h5>
</a>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
from psycopg2.extras import NumericRange
NumericRange(2005, 2008, bounds='[]')