Я пытаюсь отобразить определенный набор объектов в моих моделях в ListView, и мне нужно создать набор запросов с соответствующими фильтрами. Я пытаюсь фильтровать протоколы по типам технологий, типам объектов и предметам. Все эти три фильтра имеют древовидную структуру, поэтому я импортировал модель MPTTM.

В 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 

Затем подключите это представление к моим URL-адресам:

urlpatterns = patterns('',
                      url(r'^index/', BPCategoryList.as_view()),
)

Шаблон для index.html выглядит следующим образом:

Примечания : В модели MPTT он автоматически генерирует поле «Уровень», указывающее уровень объекта в древовидной структуре, и я назначил название категории, например, «Тип технологии» / «Тип объекта» / «Тема» на уровне 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 позволяла пользователям сузить свой выбор, например, только некоторые протоколы в этом типе объекта с некоторыми конкретными предметами. Таким образом, я хочу создать фильтры на основе каждой из этих трех категорий. Я добавляю еще три ListView в свой views.py, здесь я просто выбираю один из них (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 ( )

Скрипты должны содержать повторяющиеся коды. Я с нетерпением жду каких-то лаконичных методов для создания динамического списка объектов с фильтрами этих трех категорий на одной странице. Любые идеи приветствуются. Большое тебе спасибо!

1
Bluesky 21 Авг 2014 в 13:12

1 ответ

Лучший ответ

Я исправил сам, добавив коды в

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
                        }
0
Bluesky 10 Сен 2014 в 11:03