我试图在ListView中的模型中显示一组特定的对象,我需要使用适当的过滤器构造一个查询集。我试图通过其技术类型,对象类型和主题来过滤协议。这三个过滤器都是树形的,因此我导入了MPTTModel。
在models.py中,我有这些模型:
from django.db import models
from mptt.models import MPTTModel
class BPSubject(MPTTModel, models.Model):
name = models.CharField(max_length=100, unique=False)
engname = models.CharField(max_length=100, unique=False)
parent = TreeForeignKey('self',null=True, blank=True, related_name='children', db_index=True)
scopenote = models.TextField(blank = True)
annotation = models.TextField(blank=True)
class BPTechnoType(MPTTModel, models.Model):
name = models.CharField(max_length=100)
engname = models.CharField(max_length=100)
parent = TreeForeignKey('self',null=True, blank=True, related_name='children', db_index=True)
class BPObjectType(MPTTModel, models.Model):
name = models.CharField(max_length=100)
engname = models.CharField(max_length=100)
parent = TreeForeignKey('self',null=True, blank=True, related_name='children', db_index=True)
bptechno = models.ManyToManyField(BPTechnoType, blank=True)
class Bioprotocol(models.Model):
Title = models.CharField(max_length=200)
TechnoType = models.ManyToManyField(BPTechnoType)
ObjectType = models.ManyToManyField(BPObjectType)
Abstract = models.TextField(blank=True)
Subject = models.ManyToManyField(BPSubject)
然后我为索引页面定义了一个显示所有类别(Subject,ObjectType和TechnoType)的视图:
在views.py中:
class BPCategoryList(ListView):
model = BPSubject
context_object_name = "bpsubject_list"
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super(BPCategoryList, self).get_context_data(**kwargs)
context['bpobjecttype_list'] = BPObjectType.objects.all()
context['bptechnotype_list'] = BPTechnoType.objects.all()
context['bioprotocol_list'] = Bioprotocol.objects.all()
return context
然后将该视图挂钩到我的网址:
urlpatterns = patterns('',
url(r'^index/', BPCategoryList.as_view()),
)
index.html的模板如下:
注意:在MPTT模型中,它会自动生成一个“Level”字段,指示树结构中对象的级别,并且我在类别名称上分配了“技术类型”/“对象类型”/“主题”等级0.
<div id="container">
<div id="sidebar">
<div class="mainNavs">
<div class="menu_box">
{% for bptechnotype in bptechnotype_list %}
{% if bptechnotype.level = 0 %} <!-- The Level 0 of the MPTT Model -->
<div class="menu_main">
<h2>{{ bptechnotype.name }}</h2>
</div>
<div class="menu_sub dn">
{% elif bptechnotype.level = 1 %}
<dl class="reset">
<dt><a href="/bptechnotype/{{ bptechnotype.name }}">{{ bptechnotype.name }}</a></dt>
<dd>
{% for children in bptechnotype.get_children %}
<a href="/bptechnotype/{{ children.name }}">{{ children.name }}</a>
{% endfor %}
</dd>
</dl>
{% endif %}
{% endfor %}
</div>
</div>
<div class="menu_box">
{% for bpobjecttype in bpobjecttype_list %}
{% if bpobjecttype.level = 0 %}
<div class="menu_main">
<h2>{{ bpobjecttype.name }}</h2>
</div>
<div class="menu_sub dn">
{% elif bpobjecttype.level = 1 %}
<dl class="reset">
<dt><a href="/bpobjecttype/{{ bpobjecttype.name }}">{{ bpobjecttype.name }}</a></dt>
<dd>
{% for children in bpobjecttype.get_children %}
<a href="/bpobjecttype/{{ children.name }}">{{ children.name }}</a>
{% endfor %}
</dd>
</dl>
{% endif %}
{% endfor %}
</div>
</div>
<div class="menu_box">
{% for bpsubject in bpsubject_list %}
{% if bpsubject.level = 0 %}
<div class="menu_main">
<h2>{{ bpsubject.name }}</h2>
</div>
<div class="menu_sub dn">
{% elif bpsubject.level = 1 %}
<dl class="reset">
<dt><a href="/bpsubject/{{ bpsubject.name }}">{{ bpsubject.name }}</a></dt>
<dd>
{% for children in bpsubject.get_children %}
<a href="/bpsubject/{{ children.name }}">{{ children.name }}</a>
{% endfor %}
</dd>
</dl>
{% endif %}
{% endfor %}
</div>
</div>
</div>
上面的脚本工作得很好。但是,每次只能使用一种类型的过滤器来获取相应的协议。但是在得到上述结果后我想做更多。我希望下一页使用ListView,使用户能够缩小他们的选择范围,例如,只有一些具有某些特定主题的此对象类型的协议。因此,我想基于这三个类别构建过滤器。我在views.py中添加了三个ListView,在这里我只选择其中一个(BPTechnoTypeBioprotocolList)来解决问题:
class BPTechnoTypeBioprotocolList(ListView):
template_name = 'bioprotocol_list.html'
def get_queryset(self):
self.technotype = get_object_or_404(BPTechnoType, name=self.args[0])
bptechnotype_list = Bioprotocol.objects.filter(TechnoType__lft__gte=self.technotype.lft, TechnoType__rght__lte=self.technotype.rght)
return bptechnotype_list
def get_context_data(self, **kwargs):
context = super(BPTechnoTypeBioprotocolList, self).get_context_data(**kwargs)
bpobjecttype_list = []
bptechnotype_list = []
bpsubject_list = []
for item in self.get_queryset():
bpobjecttype = BPObjectType.objects.filter(bioprotocol__id=item.id)
bpsubject = BPSubject.objects.filter(bioprotocol__id=item.id)
bptechnotype = BPTechnoType.objects.filter(bioprotocol__id=item.id)
bpobjecttype_list += bpobjecttype
bpsubject_list += bpsubject
bptechnotype_list += bptechnotype
objecttypecount = Counter(bpobjecttype_list).most_common()
technotypecount = Counter(bptechnotype_list).most_common()
subjectcount = Counter(bpsubject_list).most_common()
# Add in the subject
context['bpobjecttype_list'] = objecttypecount
context['bptechnotype_list'] = technotypecount
context['bpsubject_list'] = subjectcount
context['bptechnotype'] = self.technotype
return context
并在我的urls.py中添加:
url(r'^bptechnotype/([\w-]+)/$', BPTechnoTypeBioprotocolList.as_view()),
bioprotocol_list.html的模板是:
<div class="sidebar">
<div id="options" class="greybg">
<dl>
<dt>
"Object Type"
</dt>
<dd>
{% for objecttype in bpobjecttype_list %}
<div class="option">
<label>
<input type="checkbox" checked="" value="">{{ objecttype.0 }}</label> ({{ objecttype.1 }})
</div>
{% endfor %}
</dd>
</dl>
<dl>
<dt>
"Technology Type"
</dt>
<dd>
{% for technotype in bptechnotype_list %}
<div class="option">
<label>
<input type="checkbox" checked="" value="">{{ technotype.0 }}</label> ({{ technotype.1 }})
</div>
{% endfor %}
</dd>
</dl>
<dl>
<dt>
"Subject"
</dt>
<dd>
{% for subject in bpsubject_list %}
<div class="option">
<label>
<input type="checkbox" checked="" value="">{{ subject.0 }}</label> ({{ subject.1 }})
</div>
{% endfor %}
</dd>
</dl>
<button type="button" id="selectall">Select All</button>
<button type="button" id="cancelall">Cancel</button>
<button type="button" id="applyfilter">Filter</button>
<script type="text/javascript">
$(document).ready(function(){
$("#selectall").click(function(){
$("input").prop('checked', true)
});
$("#cancelall").click(function(){
$("input").prop('checked',false)
});
$("#applyfilter").click(function(){
SHOULD DO SOMETHING AND SEND THE QUERYSET TO THE LISTVIEW
});
});
})
</script>
</div>
</div>
主要思想是应用jQuery函数($(“#applyfilter”)。click(function(){})遍历每个复选框输入,并获取所有选中的过滤器并将请求发送到ListView并更改get_queryset()
脚本必须包含一些重复的代码。我期待一些简洁的方法,在一个页面上使用这三个类别的过滤器制作动态的对象列表。任何想法都赞赏。非常感谢你!
答案 0 :(得分:0)
我通过将代码添加到
来自行修复function getvalue(){
var objectchk = [];
var technochk = [];
var subjectchk = [];
$("input[name='objecttype']:checked").each(function(){
objectchk.push($(this).val());
});
$("input[name='technotype']:checked").each(function(){
technochk.push($(this).val());
});
$("input[name='subject']:checked").each(function(){
subjectchk.push($(this).val());
});
var dict = {
'ObjectType':objectchk, 'TechnoType':technochk, 'Subject':subjectchk
};
var params = $.param(dict);
$.ajax({
type: "GET",
data: {'ObjectType':objectchk, 'TechnoType':technochk, 'Subject':subjectchk},
});
window.location = "?" + params
}