zoukankan      html  css  js  c++  java
  • Django多条件筛选查询

    转自:https://www.jianshu.com/p/a86281df530e

    Django多条件筛选查询

    主模型只存在外键一对多关系

    模型设计

    # 快捷筛选状态
    class Status(models.Model):
        order_number = models.PositiveIntegerField(unique=True, verbose_name='状态编号')
        status_tag = models.CharField(max_length=10, verbose_name='状态名称')
    
        class Meta:
            ordering = ['order_number', ]
            verbose_name = '事件选择'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.status_tag
    
    
    # 项目分类
    class Project(models.Model):
        project_name = models.CharField(max_length=10, verbose_name='项目名称')
    
        class Meta:
            ordering = ['project_name']
            verbose_name = '项目分类'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.project_name
    
    
    # 事件分类
    class Category(models.Model):
        category_name = models.CharField(max_length=10, verbose_name='分类名称')
    
        class Meta:
            ordering = ['category_name', ]
            verbose_name = '事件分类'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.category_name
    
    
    # 事件级别
    class Level(models.Model):
        order_number = models.PositiveIntegerField(unique=True, verbose_name='级别编号')
        level_tag = models.CharField(max_length=10, verbose_name='级别名称')
    
        class Meta:
            ordering = ['order_number', ]
            verbose_name = '事件级别'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.level_tag
    
    
    # 事件内容
    class EventContent(models.Model):
        title = models.CharField(max_length=50, verbose_name='事件标题')
        content = models.TextField(verbose_name='事件正文')
        image = models.ImageField(upload_to='images/%Y/%m', blank=True, null=True, verbose_name='描述图片')
        created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
        updated = models.DateTimeField(auto_now=True, verbose_name='更新时间')
        status = models.ForeignKey(Status, on_delete=models.SET_NULL, null=True, blank=True, related_name='event_content', verbose_name='事件状态')
        project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True, related_name='event_content', verbose_name='项目分类')
        category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='event_content', verbose_name='事件分类')
        level = models.ForeignKey(Level, on_delete=models.SET_NULL, null=True, blank=True, related_name='event_content', verbose_name='事件级别')
        user = models.ForeignKey(User, related_name='event_content', verbose_name='创建人')
        start_time = models.DateTimeField(default=timezone.now, verbose_name='事件开始时间')
        end_time = models.DateTimeField(default=timezone.now, verbose_name='事件结束时间')
        pause_time = models.DateTimeField(default=timezone.now, verbose_name='事件暂停时间')
    
        class Meta:
            ordering = ['-created']
            verbose_name = '事件内容'
            verbose_name_plural = verbose_name
    
        def time_interval(self):
            time_diff = (self.end_time-timezone.now())
            days = time_diff.days
            seconds = time_diff.seconds
            minutes = seconds // 60  # 得到这些秒换算的分钟整数
            second = seconds % 60  # 得到除去分钟后剩余的秒数
            hours = minutes // 60
            minute = minutes % 60
            if self.status.order_number == 6:
                return '事件已关闭!'
            if days <= -1:
                return '处理已超时!'
    
            return '{}天{}时{}分'.format(days, hours, minute)
    
        def __str__(self):
            return self.title
    
        def get_content_as_markdown(self):
            """
            当使用Mardown功能时,我们需要先让它转义一下特殊字符,然后再解析出Markdown标签。
            这样做之后,输出字符串可以安全的在模板中使用。
            :return:
            """
            return mark_safe(markdown(self.content, safe_mode='escape'))
    

    路由设计

        url(r'^event/$', event, name='event'),
        url(r'^event-(?P<user_id>d+)-(?P<status_id>d+)-(?P<level_id>d+)-(?P<category_id>d+)-(?P<project_id>d+).html$', event, name='event_filter'),
    

    视图设计

    该视图只需要查看kwargs有值的情况

    def get_group_url_list(url):
        """
        将访问的url存储在列表中,用于前端判断
        EVENT_MENU_GROUP : 事件菜单组
        OTHER_MENU_GROUP : 其他菜单组
        :param url:
        :return:
        """
        group_url_list = list()
        group_url_list.append(url)
        return group_url_list
    
    
    # 显示事件列表
    def event(request, **kwargs):
        print('视图**kwargs的值:', kwargs)
        if not kwargs:
            # 原来的事件列表和post筛选
            # events = EventContent.objects.all()
            queryset = EventContent.objects.all()
            if request.method == 'POST':
                visit_url = reverse('event')
                event_url_list = get_group_url_list(visit_url)
    
                filter_event_form = FilterEventForm(request.POST)
                if filter_event_form.is_valid():
                    print('表单验证通过')
                    user = filter_event_form.cleaned_data['user']
                    status = filter_event_form.cleaned_data['status']
                    project = filter_event_form.cleaned_data['project']
                    category = filter_event_form.cleaned_data['category']
                    level = filter_event_form.cleaned_data['level']
                    queryset = queryset.filter(user=user, status=status, project=project, category=category, level=level)
                    print(queryset)
            else:
                visit_url = reverse('event')
                event_url_list = get_group_url_list(visit_url)
    
                filter_event_form = FilterEventForm()
    
            page = request.GET.get('page', 1)
            paginator = Paginator(queryset, settings.PAGE_NUM)  # paginator是分页对象
            try:
                events = paginator.page(page)
            except PageNotAnInteger:
                events = paginator.page(1)
            except EmptyPage:
                events = paginator.page(paginator.num_pages)
            return render(request, 'event.html',
                          {
                              'events': events,
                              'EVENT_MENU_GROUP': event_url_list,
                              'filter_event_form': filter_event_form,
                              'old_filter': True
                          })
        else:
            """
            多条件事件筛选
            event-(?P<user_id>d+)-(?P<status_id>d+)-(?P<level_id>d+)-(?P<category_id>d+)-(?P<project_id>d+).html
            {'user_id': '0', 'status_id': '0', 'level_id': '0', 'category_id': '0', 'project_id': '0'}
            """
            filter_dict = dict()
            request_path = request.path
            print('请求地址:', request_path)
            if kwargs['user_id'] != '0':
                filter_dict['user'] = get_object_or_404(User, id=kwargs['user_id'])
            if kwargs['status_id'] != '0':
                filter_dict['status'] = get_object_or_404(Status, id=kwargs['status_id'])
            if kwargs['level_id'] != '0':
                filter_dict['level'] = get_object_or_404(Level, id=kwargs['level_id'])
            if kwargs['category_id'] != '0':
                filter_dict['category'] = get_object_or_404(Category, id=kwargs['category_id'])
            if kwargs['project_id'] != '0':
                filter_dict['project'] = get_object_or_404(Project, id=kwargs['project_id'])
    
            user_list = User.objects.all().values('id', 'username')
            # print(user_list)
            status_list = Status.objects.all().values('id', 'status_tag')
            # print(status_list)
            level_list = Level.objects.all().values('id', 'level_tag')
            category_list = Category.objects.all().values('id', 'category_name')
            project_list = Project.objects.all().values('id', 'project_name')
    
            url_id_list = kwargs.values()  # url中所有id:[0, 0, 0, 0, 0 ]
            visit_url = reverse('event_filter', args=url_id_list)
            event_url_list = get_group_url_list(visit_url)
            queryset = EventContent.objects.filter(**filter_dict)
            page = request.GET.get('page', 1)
            paginator = Paginator(queryset, settings.PAGE_NUM)  # paginator是分页对象
            try:
                events = paginator.page(page)
            except PageNotAnInteger:
                events = paginator.page(1)
            except EmptyPage:
                events = paginator.page(paginator.num_pages)
            return render(request, 'event.html',
                          {
                              'events': events,
                              'EVENT_MENU_GROUP': event_url_list,
                              'user_list': user_list,
                              'status_list': status_list,
                              'level_list': level_list,
                              'category_list': category_list,
                              'project_list': project_list,
                          })
    

    模板设计

    <div class="card-header">
        <h3 class="card-title">事件列表</h3>
    </div>
    <!-- /.card-header -->
    {% if old_filter %}
        <div class="card-body card-comment">
            <form role="form" action="{% url 'event' %}?page=2" method="post">
                <div class="row">
                    <div class="col-2">
                        <div class="input-group mb-12">
                            {% with filter_event_form.user as filter_fields %}
                            <div class="input-group-prepend">
                                <label class="input-group-text {% if filter_fields.errors %}bg-danger {% endif %}" for="{{ filter_fields.id_for_label }}">{{ filter_fields.label }}</label>
                            </div>
                            <select class="form-control col-sm-12" name="user" id="{{ filter_fields.id_for_label }}">
                                <option>{% for select in filter_fields %}{{ select }}{% endfor %}</option>
                            </select>
                            {% endwith %}
                        </div>
                    </div>
                    <div class="col-2">
                        <div class="input-group mb-12">
                            {% with filter_event_form.status as filter_fields %}
                            <div class="input-group-prepend">
                                <label class="input-group-text {% if filter_fields.errors %}bg-danger{% endif %}" for="{{ filter_fields.id_for_label }}">{{ filter_fields.label }}</label>
                            </div>
                            <select class="form-control col-sm-12" name="status" id="{{ filter_fields.id_for_label }}">
                                <option>{% for select in filter_fields %}{{ select }}{% endfor %}</option>
                            </select>
                            {% endwith %}
                        </div>
                    </div>
                    <div class="col-2">
                        <div class="input-group mb-12">
                            {% with filter_event_form.project as filter_fields %}
                            <div class="input-group-prepend">
                                <label class="input-group-text {% if filter_fields.errors %}bg-danger {% endif %}" for="{{ filter_fields.id_for_label }}">{{ filter_fields.label }}</label>
                            </div>
                            <select class="form-control col-sm-12" name="project" id="{{ filter_fields.id_for_label }}">
                                <option>{% for select in filter_fields %}{{ select }}{% endfor %}</option>
                            </select>
                            {% endwith %}
                        </div>
                    </div>
                    <div class="col-2">
                        <div class="input-group mb-12">
                            {% with filter_event_form.category as filter_fields %}
                            <div class="input-group-prepend">
                                <label class="input-group-text {% if filter_fields.errors %}bg-danger {% endif %}" for="{{ filter_fields.id_for_label }}">{{ filter_fields.label }}</label>
                            </div>
                            <select class="form-control col-sm-12" name="category" id="{{ filter_fields.id_for_label }}">
                                <option>{% for select in filter_fields %}{{ select }}{% endfor %}</option>
                            </select>
                            {% endwith %}
                        </div>
                    </div>
                    <div class="col-2">
                        <div class="input-group mb-12">
                            {% with filter_event_form.level as filter_fields %}
                            <div class="input-group-prepend">
                                <label class="input-group-text {% if filter_fields.errors %}bg-danger {% endif %}" for="{{ filter_fields.id_for_label }}">{{ filter_fields.label }}</label>
                            </div>
                            <select class="form-control col-sm-12" name="level" id="{{ filter_fields.id_for_label }}">
                                <option>{% for select in filter_fields %}{{ select }}{% endfor %}</option>
                            </select>
                            {% endwith %}
                        </div>
                    </div>
                    <button type="submit" class="btn btn-primary">筛选事件</button>
                </div>
                {% csrf_token %}
            </form>
        </div>
    {% else %}
        <div class="card-body d-flex p-0">
            <h3 class="card-title p-3">用户</h3>
            <ul class="nav nav-pills p-2">
                {% active_all request.path 1 %}
                {% for user_item in user_list %}
                    {% active request.path user_item 1 %}
                {% endfor %}
            </ul>
        </div>
        <div class="card-body d-flex p-0">
            <h3 class="card-title p-3">状态</h3>
            <ul class="nav nav-pills p-2">
                {% active_all request.path 2 %}
                {% for status_item in status_list %}
                    {% active request.path status_item 2 %}
                {% endfor %}
            </ul>
        </div>
        <div class="card-body d-flex p-0">
            <h3 class="card-title p-3">级别</h3>
            <ul class="nav nav-pills p-2">
                {% active_all request.path 3 %}
                {% for level_item in level_list %}
                    {% active request.path level_item 3 %}
                {% endfor %}
            </ul>
        </div>
        <div class="card-body d-flex p-0">
            <h3 class="card-title p-3">分类</h3>
            <ul class="nav nav-pills p-2">
                {% active_all request.path 4 %}
                {% for category_item in category_list %}
                    {% active request.path category_item 4 %}
                {% endfor %}
            </ul>
        </div>
        <div class="card-body d-flex p-0">
            <h3 class="card-title p-3">项目</h3>
            <ul class="nav nav-pills p-2">
                {% active_all request.path 5 %}
                {% for project_item in project_list %}
                    {% active request.path project_item 5 %}
                {% endfor %}
            </ul>
        </div>
    {% endif %}
    

    链接生成模板标签

    使用模板标签,在应用下创建templatetags的python包,然后创建active.py文件,需要在模板中通过{% load active %}引入模板标签。

    from django.utils.safestring import mark_safe
    from django import template
    
    
    register = template.Library()
    
    
    @register.simple_tag
    def active_all(request_path, index):
        url_part_list = request_path.split('-')
        # print(url_part_list)
        # ['/event', '0', '0', '0', '0', '0.html']
        # 第五组带.html,需要分开判断
    
        if url_part_list[index] == '0' or url_part_list[index] == '0.html':
            temp = '''
            <li class="nav-item">
                <a class="nav-link active" href="{href}">全部</a>
            </li>
            '''
        else:
            temp = '''
            <li class="nav-item">
                <a class="nav-link" href="{href}">全部</a>
            </li>
            '''
    
        if index != 5:
            url_part_list[index] = '0'
        else:
            url_part_list[index] = '0.html'
    
        href = '-'.join(url_part_list)
        return mark_safe(temp.format(href=href))
    
    
    @register.simple_tag
    def active(request_path, item, index):
        url_part_list = request_path.split('-')
        # 下面判断中,前面表示 event-0-1-5-1-,后面表示 3.html
        if url_part_list[index] == str(item['id']) or url_part_list[index] == str(item['id']) + '.html':
            temp = '''
            <li class="nav-item">
                <a href="{href}" class="nav-link active">{name}</a>
            </li>
            '''
        else:
            temp = '''
            <li class="nav-item">
                <a href="{href}" class="nav-link">{name}</a>
            </li>
            '''
        if index == 5:
            # 第五组有后缀.html,需单独处理
            url_part_list[index] = str(item['id']) + '.html'
        else:
            url_part_list[index] = str(item['id'])
        href = '-'.join(url_part_list)
    
        if index == 1:
            """
            event-1-0-0-0-0.html
            event-2-0-0-0-0.html
            event-3-0-0-0-0.html
            """
            return mark_safe(temp.format(href=href, name=item['username']))
        if index == 2:
            return mark_safe(temp.format(href=href, name=item['status_tag']))
        if index == 3:
            return mark_safe(temp.format(href=href, name=item['level_tag']))
        if index == 4:
            return mark_safe(temp.format(href=href, name=item['category_name']))
        if index == 5:
            return mark_safe(temp.format(href=href, name=item['project_name']))
    

    两级分类筛选

    模型设计

    from django.db import models
    from django.utils.timezone import now
    
    
    class GoodsTag(models.Model):
        name = models.CharField(max_length=64, verbose_name='标签名称')
    
        def __str__(self):
            return self.name
    
        class Meta:
            ordering = ['name', ]
            verbose_name = '商品标签'  # 后台显示模型名称
            verbose_name_plural = verbose_name
    
    
    # 智能家居、手机、电视、电脑
    class FirstCategory(models.Model):
        name = models.CharField(max_length=64, verbose_name='分类名称')
    
        def __str__(self):
            return self.name
    
        class Meta:
            ordering = ['name', ]
            verbose_name = '一级分类'
            verbose_name_plural = verbose_name
    
    
    # 小米6、小米8、红米10
    class SubCategory(models.Model):
        name = models.CharField(max_length=64, verbose_name='分类名称')
        first_category = models.ForeignKey(FirstCategory, related_name='sub_categories', verbose_name='上级分类')
    
        def __str__(self):
            return self.name
    
        class Meta:
            ordering = ['name', ]
            verbose_name = '二级分类'
            verbose_name_plural = verbose_name
    
    
    class GoodsInfo(models.Model):
        STATUS_CHOICES = (
            (1, '上架'),
            (2, '下架'),
        )
    
        title = models.CharField(max_length=100, verbose_name='标题')
        content = models.TextField(blank=True, null=True, verbose_name='正文')
        image = models.FileField(upload_to='images/goods/%Y/%m', blank=True, null=True, verbose_name='图片')
        status = models.IntegerField(choices=STATUS_CHOICES, default=1, verbose_name='状态')
        created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
        publish_time = models.DateTimeField(blank=True, null=True, default=now, verbose_name='发布时间')
        updated_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
        category = models.ForeignKey(SubCategory, on_delete=models.CASCADE, related_name='goods_info', verbose_name='所属分类')
        tags = models.ManyToManyField(GoodsTag, blank=True, verbose_name='标签集合')
    
        def __str__(self):
            return self.title
    
        class Meta:
            verbose_name = '商品信息'
            verbose_name_plural = verbose_name
    

    主路由

    urlpatterns = [
        url(r'^test/', include('multiple_filter.urls', namespace='test')),
    ]
    

    应用路由

    访问 http://127.0.0.1:8000/test/goods.html 可跳转到 http://127.0.0.1:8000/test/goods-0-0-0-0.html

    urlpatterns = [
        url(r'^goods.html$', goods, name='goods'),
        url(r'^goods-(?P<first_category_id>d+)-(?P<sub_category_id>d+)-(?P<tags_id>d+)-(?P<status_id>d+).html', goods, name='goods_filter'),
    ]
    

    视图

    from .models import GoodsTag, FirstCategory, SubCategory, GoodsInfo
    from django.shortcuts import get_object_or_404
    
    
    def goods(request, **kwargs):
        if not kwargs:
            return redirect('test:goods_filter', first_category_id='0', sub_category_id='0', tags_id='0', status_id='0')
        else:
            request_path = request.path
            print('
    当前请求路径:', request_path, '
    ')
            print('kwargs:', kwargs)  # {'first_category_id': '0', 'sub_category_id': '0', 'tags_id': '0', 'status_id': '0'}
    
            goods_tag_list = GoodsTag.objects.all().values('id', 'name')
            first_category_list = FirstCategory.objects.all().values('id', 'name')
            sub_category_list = SubCategory.objects.all().values('id', 'name')
            status_list = list(map(lambda x: {'id': x[0], 'status': x[1]}, GoodsInfo.STATUS_CHOICES))
            filter_dict = dict()
    
            if kwargs['first_category_id'] == '0':
                # goods-0-x-x-x.html
                if kwargs['sub_category_id'] != '0':
                    # goods-0-1-x-x.html
                    sub_category = get_object_or_404(SubCategory, id=kwargs['sub_category_id'])
                    # 选择二级分类后,由于多对一关系,一级分类也会跟着变化
                    first_category_list = [{'id': sub_category.first_category.id, 'name': sub_category.first_category.name}]
                    filter_dict['category'] = sub_category
            else:
                # 一级分类不为0,需要进行筛选
                # goods-1-x-x-x.html
                first_category = get_object_or_404(FirstCategory, id=kwargs['first_category_id'])
                sub_category_list = first_category.sub_categories.values('id', 'name')  # 选择一级分类后获取二级分类的列表
                if kwargs['sub_category_id'] != '0':
                    sub_category = get_object_or_404(SubCategory, id=kwargs['sub_category_id'], first_category=first_category)
                    # 选择二级分类后,由于多对一关系,一级分类也会跟着变化
                    first_category_list = [{'id': sub_category.first_category.id, 'name': sub_category.first_category.name}]
                    filter_dict['category'] = sub_category
    
            if kwargs['tags_id'] != '0':
                filter_dict['tags'] = kwargs['tags_id']
    
            if kwargs['status_id'] != '0':
                filter_dict['status'] = int(kwargs['status_id'])
    
            goods_list = GoodsInfo.objects.filter(**filter_dict)
    
            return render(request, 'goods.html',
                          {
                              'first_category_list': first_category_list,
                              'sub_category_list': sub_category_list,
                              'goods_tag_list': goods_tag_list,
                              'status_list': status_list,
                              'goods_list': goods_list
                          })
    

    模板

    <!DOCTYPE html>
    {% load goods_active %}
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>多条件筛选</title>
    </head>
    <body>
    {% active_all request.path 1 %}
    {% for first_category in first_category_list %}
        {% active request.path first_category 1 %}
    {% endfor %}
    <br><br>
    {% active_all request.path 2 %}
    {% for sub_category in sub_category_list %}
        {% active request.path sub_category 2 %}
    {% endfor %}
    <br><br>
    {% active_all request.path 3 %}
    {% for goods_tag in goods_tag_list %}
        {% active request.path goods_tag 3 %}
    {% endfor %}
    <br><br>
    {% active_all request.path 4 %}
    {% for status in status_list %}
        {% active request.path status 4 %}
    {% endfor %}
    <p>
        {% for goods in goods_list %}
            <p>
                【{{ goods.title }}】{{ goods.content }}
            </p>
        {% endfor %}
    </p>
    </body>
    </html>
    

    链接生成模板标签

    应用下创建templatetags包,创建 goods_active.py 文件,用来放置模板标签

    from django.utils.safestring import mark_safe
    from django import template
    
    
    register = template.Library()
    
    
    @register.simple_tag
    def active_all(current_url, index):
        """
        获取当前url,进行值修改拼接
        :param current_url: http://127.0.0.1:8000/test/goods-0-0-0-0.html
        :param index:
        :return:
        """
        a_href_active = """
        <a href="{href}" class="active">【全部】</a>
        """
        a_href_unactive = """
        <a href="{href}">全部</a>
        """
        url_part_list = current_url.split('-')
        if index == len(url_part_list)-1:  # 最后一个带.html要特殊处理
            if url_part_list[index] == '0.html':
                a_href = a_href_active
            else:
                a_href = a_href_unactive
    
            url_part_list[index] = '0.html'
        else:
            if url_part_list[index] == '0':
                a_href = a_href_active
            else:
                a_href = a_href_unactive
    
            url_part_list[index] = '0'
    
        href = '-'.join(url_part_list)
        a_href = a_href.format(href=href)
        return mark_safe(a_href)
    
    
    @register.simple_tag
    def active(current_url, item, index):
        """
        获取当前url,进行值修改拼接
        :param current_url: http://127.0.0.1:8000/test/goods-0-0-0-0.html
        :param index:
        :return:
        """
        a_href_active = """
        <a href="{href}" class="active">【{name}】</a>
        """
        a_href_unactive = """
        <a href="{href}">{name}</a>
        """
        url_part_list = current_url.split('-')
        if index == len(url_part_list)-1:  # 最后一个带.html要特殊处理
            if url_part_list[index] == str(item['id']) + '.html':
                a_href = a_href_active
            else:
                a_href = a_href_unactive
    
            url_part_list[index] = str(item['id']) + '.html'
        else:
            # print(item['id'], type(item['id']))  # item['id']是int类型
            if url_part_list[index] == str(item['id']):
                a_href = a_href_active
            else:
                a_href = a_href_unactive
    
            url_part_list[index] = str(item['id'])
    
        href = '-'.join(url_part_list)
        if index in range(1, 4):
            a_href = a_href.format(href=href, name=item['name'])
        if index == len(url_part_list)-1:
            a_href = a_href.format(href=href, name=item['status'])
        return mark_safe(a_href)
    

    多对多模型进行筛选

    模型

    # 课程分类
    class Category(models.Model):
        weight = models.IntegerField(verbose_name='权重(按从大到小排列)', default=0)
        name = models.CharField(max_length=32, verbose_name='分类名称')
    
        class Meta:
            verbose_name = '分类方向'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    # 编程语言,一个课程分类里可能有多种编程语言,一种编程语言可能存在不同的课程分类
    class Code(models.Model):
        weight = models.IntegerField(default=0, verbose_name='权重(按从大到小排列)')
        name = models.CharField(max_length=32, verbose_name='编程语言')
        category = models.ManyToManyField(Category, related_name='codes', verbose_name='课程分类')
    
        class Meta:
            verbose_name = '编程语言'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    # 课程详情
    class Course(models.Model):
        STATUS_CHOICE = (
            (0, '下线'),
            (1, '上线')
        )
    
        LEVEL_CHOICE = (
            (1, '初级'),
            (2, '中级'),
            (3, '高级')
        )
    
        status = models.IntegerField(choices=STATUS_CHOICE, default=1, verbose_name='状态')
        level = models.IntegerField(choices=LEVEL_CHOICE, default=1, verbose_name='难度级别')
        category = models.ForeignKey(Category, null=True, blank=True, related_name='courses', verbose_name='课程分类')
        weight = models.IntegerField(default=0, verbose_name='权重(按从大到小排列)')
        title = models.CharField(max_length=32, verbose_name='标题')
        summary = models.CharField(max_length=100, verbose_name='简介')
        image = models.ImageField(upload_to='images/course/%Y/%m', verbose_name='图片')
        video_url = models.CharField(max_length=256, verbose_name='视频地址')
        create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    
        class Meta:
            verbose_name = '课程详情'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.title
    

    路由

    urlpatterns = [
        # 访问形式http://127.0.0.1:8000/test/course-0-0-0.html,
        # 第一个0代表课程分类,第二个0代表编程语言,第三个0代表课程级别
        # 0代表全部,然后递增,当选择课程分类中的第一项,第一个0就会变成1
        url(r'^course-(?P<code_id>d+)-(?P<category_id>d+)-(?P<level_id>d+).html', course, name='course'),
    ]
    

    视图

    def course(request, *args, **kwargs):
        print(args, kwargs)  # () {'code_id': '0', 'category_id': '0', 'level_id': '0'}
        request_path = request.path  # http://127.0.0.1:8000/test/course-0-0-0.html
    
        # 筛选字典
        filter_dict = dict()
    
        code_list = Code.objects.all().values('id', 'name')
        category_list = Category.objects.all().values('id', 'name')
        level_list = list(map(lambda x: {'id': x[0], 'name': x[1]}, Course.LEVEL_CHOICE))
    
        if kwargs['code_id'] == '0':
            if kwargs['category_id'] != '0':
                category_list = Category.objects.filter(id=kwargs['category_id']).values('id', 'name')
                category = get_object_or_404(Category, id=kwargs['category_id'])
                # 分类不是全部,得到这个分类对应的所有编程语言
                code_list = category.codes.values('id', 'name')
                # 筛选这一分类
                filter_dict['category'] = category
        else:
            # 如果编程语言不为0,则获取对应的编程语言
            code = get_object_or_404(Code, id=kwargs['code_id'])
            # 得到编程语言对应的所有分类
            categories = code.category.all()
            category_list = categories.values('id', 'name')
            # 筛选课程在这些分类的结果
            filter_dict['category__in'] = categories
            if kwargs['category_id'] != '0':
                # 如果分类不为0,对分类进行筛选,得到该编程语言和该分类下的结果
                category = get_object_or_404(categories, id=kwargs['category_id'])
                code_list = category.codes.values('id', 'name')
                filter_dict['category'] = category
    
        if kwargs['level_id'] != '0':
            filter_dict['level'] = int(kwargs['level_id'])
    
        filter_dict['status'] = 1
    
        course_list = Course.objects.filter(**filter_dict)
        return render(request, 'course.html',
                      {
                          'category_list': category_list,
                          'code_list': code_list,
                          'level_list': level_list,
                          'course_list': course_list,
                      })
    

    模板

    <!DOCTYPE html>
    {% load course_active %}
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>多条件筛选多对多模型</title>
    </head>
    <body>
    
    <h3>选择:</h3>
    
    <p>
        编程语言:
        {% active_all request.path 1 %}
        {% for code in code_list %}
            <!--{{ code }}-->
            {% active request.path code 1 %}
        {% endfor %}
    </p>
    
    <p>
        课程分类:
        {% active_all request.path 2 %}
        {% for category in category_list %}
            <!--{{ category }}-->
            {% active request.path category 2 %}
        {% endfor %}
    </p>
    
    <p>
        课程信息:
        {% active_all request.path 3 %}
        {% for level in level_list %}
            <!--{{ level }}-->
            {% active request.path level 3 %}
        {% endfor %}
    </p>
    
    <h3>视频:</h3>
    {% for course in course_list %}
        <a class="item" href="{{ course.video.url }}">
            <img src="/media/{{ course.image }}" width="300px" height="200px">
            <p>《{{ course.title }}》{{ course.summary }}</p>
            <hr>
        </a>
    {% endfor %}
    
    </body>
    </html>
    

    链接生成模板标签

    应用下创建templatetags包,创建 course_active.py 文件,用来放置模板标签

    from django.utils.safestring import mark_safe
    from django import template
    
    
    register = template.Library()
    
    
    @register.simple_tag
    def active_all(current_url, index):
        """
        获取当前url, course-1-1-2.html
        :param current_url:
        :param index:
        :return:
        """
        url_part_list = current_url.split('-')
        if index == 3:
            if url_part_list[index] == '0.html':
                temp = '<a href="%s" class="active">【全部】</a>'
            else:
                temp = '<a href="%s"">全部</a>'
    
            url_part_list[index] = '0.html'
        else:
            if url_part_list[index] == '0':
                temp = '<a href="%s" class="active">【全部】</a>'
            else:
                temp = '<a href="%s"">全部</a>'
    
            url_part_list[index] = '0'
    
        url_str = '-'.join(url_part_list)
    
        temp = temp % (url_str, )
        return mark_safe(temp)
    
    
    @register.simple_tag
    def active(current_url, item, index):
        """
        course-0-0-1.html
        :param current_url:
        :param item:
        :param index:
        :return:
        """
        # print('
    当前访问地址:', current_url, item, index, type(index))
        url_part_list = current_url.split('-')
        # print(url_part_list)  # ['/test/course', '0', '0', '0.html']
        if index == 3:
            if str(item['id']) == url_part_list[3].split('.')[0]:  # 如果当前标签被选中
                temp = '<a href="%s" class="active">【%s】</a>'
            else:
                temp = '<a href="%s"">%s</a>'
    
            url_part_list[index] = str(item['id']) + '.html'  # 拼接对应位置的url
    
        else:
            if str(item['id']) == url_part_list[index]:
                temp = '<a href="%s" class="active">【%s】</a>'
            else:
                temp = '<a href="%s">%s</a>'
    
            url_part_list[index] = str(item['id'])
    
        url_str = '-'.join(url_part_list)  # 拼接整体url
        # print(url_str)
        temp = temp % (url_str, item['name'])  # 生成对应的a标签
        return mark_safe(temp)
  • 相关阅读:
    hduoj1285确定比赛名次
    HDU 1041 Computer Transformation 数学DP题解
    使用Git【转】
    Git-标签管理【转】
    Git-分支管理【转】
    Git-远程仓库【转】
    Git-时光穿梭【转】
    创建版本库【转】
    安装Git【转】
    Git简介【转】
  • 原文地址:https://www.cnblogs.com/zmdComeOn/p/12163487.html
Copyright © 2011-2022 走看看