您现在的位置是: 网站首页 >Django >Django2.0.8+xadmin2实现在线学习网站 Django

【Django在线教育平台】07.授课机构列表显示,分页、分类筛选、排序功能

admin2019年6月4日 13:56 Django | Html | JQuery 394人已围观

Django2.0.8+xadmin2实现在线学习网站简介 Django2.0.8+xadmin2实现在线学习网站,课程、讲师、机构、用户收藏功能。GitHub地址:https://github.com/xyliurui/OnlineLearningPlatform ;Django版本:2.0.8

# 授课机构功能实现 ## 定义父模板base.html 用户其他模板扩展 ## 机构列表基础 ### 机构列表展示模板org-list.html 该模板继承base.html,使用`{% extends 'base.html' %}` ### 机构列表视图OrgListView(View) **organization/views.py** ```python from django.shortcuts import render from django.views.generic.base import View class OrgListView(View): def get(self, request): return render(request, 'org-list.html') ``` ### 机构列表url 修改主url,配置课程机构首页url ```python from organization.views import OrgListView urlpatterns = [ path('admin/', admin.site.urls), path('xadmin/', xadmin.site.urls), path('', TemplateView.as_view(template_name='index.html'), name='index'), # path('login/', TemplateView.as_view(template_name='login.html'), name='login'), # path('login/', user_login, name='login'), path('login/', LoginView.as_view(), name='login'), # 基于类方法实现登录,这里是调用它的方法 path('register/', RegisterView.as_view(), name='register'), re_path('register/active/(?P<active_code>.*)/', ActiveUserView.as_view(), name='user_active'), # 激活 path('captcha/', include('captcha.urls')), path('forgetpwd/', ForgetPwdView.as_view(), name='forgetpwd'), # 忘记密码 re_path('forgetpwd/reset/(?P<active_code>.*)/', RestpwdView.as_view(), name='resetpwd'), # 密码重置验证 path('modify_pwd/', ModifypwdView.as_view(), name="modify_pwd"), # 密码修改 path('org/list/', OrgListView.as_view(), name="org_list"), # 机构列表 ] ``` 这样,访问 http://127.0.0.1:8000/org/list/ 即可查看机构列表 ## 机构列表数据展示 确定由后台传过来的动态数据:授课机构列表本身, 授课机构的排名,所在地区(后台取出所有地区), 机构类别写成静态,因为一般不怎么变动。 在xadmin中添加城市信息,课程信息。 ### 机构models中添加机构类别 **organization/models.py** ```python # 课程机构信息 class CourseOrg(models.Model): ORG_CHOICES = ( ("pxjg", "培训机构"), ("gx", "高校"), ("gr", "个人"), ) name = models.CharField(max_length=50, verbose_name='机构名称') desc = models.TextField(verbose_name='机构描述') category = models.CharField(choices=ORG_CHOICES, max_length=10, default='pxjg', verbose_name='机构类别') click_nums = models.IntegerField(default=0, verbose_name='点击数') fav_nums = models.IntegerField(default=0, verbose_name='收藏数') image = models.ImageField(upload_to='org/%Y/%m', max_length=100, verbose_name='封面图') address = models.CharField(max_length=150, verbose_name='机构地址') city = models.ForeignKey(CityDict, on_delete=models.CASCADE, verbose_name='所在城市') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') class Meta: verbose_name_plural = verbose_name = '课程机构' def __str__(self): return self.name ``` 然后需要进行数据同步 ```python manage.py@DjangoOnlineLearningPlatform > makemigrations manage.py@DjangoOnlineLearningPlatform > migrate ``` ### 完善机构列表视图 将列表里的静态数据变成后台获取的动态数据 **organization/views.py** ```python from .models import CourseOrg, CityDict class OrgListView(View): def get(self, request): # 查找所有的机构 all_org = CourseOrg.objects.all() # 取出所有城市 all_city = CityDict.objects.all() # 机构类别 all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES)) return render(request, 'org-list.html', locals()) ``` ### 模板中进行数据填充org-list.html ```html <div class="short-lst"> <ul> <li><b>机构类别</b></li> <li><a href="?category=&city="> 全部 </a></li> {% for category in all_category %} <li><a href="?category={{ category.code }}&city="> {{ category.explain }} </a></li> {% endfor %} </ul> </div> <div class="short-lst"> <ul> <li><b>所在地区</b></li> <li><a href="?category=&city="> 全部 </a></li> {% for city in all_city %} <li><a href="?category=&city={{ city.id }}"> {{ city.name }} </a></li> {% endfor %} </ul> </div> <div class="short-lst"> <h2>授课机构<small>(共{{ all_org.count }}家)</small></h2> <ul> <!-- Short List --> <li> <p>全部</p> </li> <li> <p>学习人数↓</p> </li> <li> <p>课程数↓</p> </li> </ul> </div> {% for org in all_org %} <div class="product"> <article> <!-- Product img --> <div class="media-left"> <div class="item-img"><img class="img-responsive" src="{{ org.image.url }}" alt=""></div> </div> <!-- Content --> <div class="media-body"> <div class="row"> <!-- Content Left --> <div class="col-sm-7"><span class="tag"></span> <h4><a href="#.">{{ org.name }}</a></h4> <!-- Reviews --> <ul class="bullet-round-list"> <li>课程数:xx</li> <li>学习人数:xx</li> <li>地址:</li> <li>经典课程</li> </ul> </div> <!-- Content Right --> <div class="col-sm-5 text-center"> <div class="position-center-center"> <a href="#." class="btn-round">联系</a> </div> </div> </div> </div> </article> </div> {% endfor %} ``` ![BLOG_20190604_135852_84](/media/blog/images/2019/06/BLOG_20190604_135852_84.png "博客图集BLOG_20190604_135852_84.png") ## 列表分页功能 首先需要安装相应的库 ```python pip install django-pure-pagination ``` ### 分页设置 修改settings.py添加分页app:`pure_pagination` ```python INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'users', 'courses', 'organization', 'operation', 'xadmin', 'crispy_forms', 'reversion', 'captcha', 'pure_pagination', ] PAGINATION_SETTINGS = { 'PAGE_RANGE_DISPLAYED': 10, 'MARGIN_PAGES_DISPLAYED': 2, 'SHOW_FIRST_PAGE_WHEN_INVALID': True, } ``` * `PAGE_RANGE_DISPLAYED`是总共会显示多少个page。(包括省略号,包括两边和中间) * `MARGIN_PAGES_DISPLAYED`是旁边会显示多少个。 * `SHOW_FIRST_PAGE_WHEN_INVALID`当输入页数不合法是否要跳到第一页 ### 视图中分页实现 参照官方的文档 ```python from pure_pagination import Paginator, EmptyPage, PageNotAnInteger from .models import CourseOrg, CityDict class OrgListView(View): def get(self, request): # 查找所有的机构 all_org = CourseOrg.objects.all() # 取出所有城市 all_city = CityDict.objects.all() # 机构类别 all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES)) # 机构数量 org_nums = all_org.count() # 对课程机构进行分页 # 尝试获取前台get请求传递过来的page参数 # 如果是不合法的配置参数默认返回第一页 try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 # 从列表中取5个出来,也就是每页显示5个 p = Paginator(all_org, 5, request=request) all_org = p.page(page) return render(request, 'org-list.html', locals()) ``` ### html配置分页 ```html <h2>授课机构<small>(共{{ org_nums }}家,本页显示{{ all_org.object_list.count }}家)</small></h2> {% for org in all_org.object_list %} # .... {% endofr %} <!-- pagination --> <ul class="pagination"> {% if all_org.has_previous %} <li><a href="?{{ all_org.previous_page_number.querystring }}" aria-label="Previous"> <i class="fa fa-angle-left"></i> </a></li> {% endif %} {% for page in all_org.pages %} {% if page %} {% ifequal page all_org.number %} <li><a class="active" href="?{{ page.querystring }}">{{ page }}</a></li> {% else %} <li><a href="?{{ page.querystring }}">{{ page }}</a></li> {% endifequal %} {% else %} <li><a href="">...</a></li> {% endif %} {% endfor %} {% if all_org.has_next %} <li><a href="?{{ all_org.next_page_number.querystring }}" aria-label="Next"> <i class="fa fa-angle-right"></i> </a></li> {% endif %} </ul> ``` 机构列表不再是objects,而是`all_org.object_list` ![BLOG_20190604_135839_53](/media/blog/images/2019/06/BLOG_20190604_135839_53.png "博客图集BLOG_20190604_135839_53.png") ## 分类筛选功能 直接在url中添加参数,例如当用户点击某一个city时对应加上参数city的id ```html <li><a href="?category=&city={{ city.id }}"> {{ city.name }} </a></li> ``` ### 后台处理类别筛选 ```python class OrgListView(View): def get(self, request): # 查找所有的机构 all_org = CourseOrg.objects.all() # 取出所有城市 all_city = CityDict.objects.all() # 机构类别 all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES)) # 处理类别筛选 category_code = request.GET.get('category', '') if category_code: all_org = all_org.filter(category=category_code) # 机构数量 org_nums = all_org.count() # 对课程机构进行分页 # 尝试获取前台get请求传递过来的page参数 # 如果是不合法的配置参数默认返回第一页 try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 # 从列表中取5个出来,也就是每页显示5个 p = Paginator(all_org, 5, request=request) all_org = p.page(page) return render(request, 'org-list.html', locals()) ``` ### 后台处理城市筛选 ```python class OrgListView(View): def get(self, request): # 查找所有的机构 all_org = CourseOrg.objects.all() # 取出所有城市 all_city = CityDict.objects.all() # 机构类别 all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES)) # 处理类别筛选,取回的是字符串 category_code = request.GET.get('category', '') if category_code: all_org = all_org.filter(category=category_code) # 处理城市筛选,取回的是city的ID city_id = request.GET.get('city', '') if city_id: all_org = all_org.filter(city=city_id) # 机构数量 org_nums = all_org.count() # 对课程机构进行分页 # 尝试获取前台get请求传递过来的page参数 # 如果是不合法的配置参数默认返回第一页 try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 # 从列表中取5个出来,也就是每页显示5个 p = Paginator(all_org, 5, request=request) all_org = p.page(page) return render(request, 'org-list.html', locals()) ``` ### 模板中处理两种筛选 已经选中的进行标记 ```html <div class="short-lst"> <ul> <li><b>机构类别</b></li> <li><a href="?category=&city={{ city_id }}" {% ifequal category_code '' %} style="color: #BEBEBE" {% endifequal %}> 全部 </a></li> {% for category in all_category %} <li><a href="?category={{ category.code }}&city={{ city_id }}" {% ifequal category_code category.code %} style="color: #BEBEBE" {% endifequal %}> {{ category.explain }} </a></li> {% endfor %} </ul> </div> <div class="short-lst"> <ul> <li><b>所在地区</b></li> <li><a href="?category={{ category_code }}&city=" {% ifequal city_id '' %} style="color: #BEBEBE" {% endifequal %}> 全部 </a></li> {% for city in all_city %} <li><a href="?category={{ category_code }}&city={{ city.id }}" {% ifequal city_id city.id|stringformat:'i' %} style="color: #BEBEBE" {% endifequal %}> {{ city.name }} </a></li> {% endfor %} </ul> </div> ``` ![BLOG_20190604_135827_76](/media/blog/images/2019/06/BLOG_20190604_135827_76.png "博客图集BLOG_20190604_135827_76.png") 由于我们使用的是分页库,这里变动page的时候url中其他参数不会变化 例如 访问 http://127.0.0.1:8000/org/list/?category=pxjg&city= 如果这时候点第2也, 则url会跳转到 http://127.0.0.1:8000/org/list/?category=pxjg&city=&page=2 进行城市与分类的联动: * 当选择全部类别的时候,就只通过当前城市id。 * 当选择全部城市的时候,就只通过当前类别id。 * 当两者都选的时候使用`&`连接。 ## 课程机构排序 学习人数,课程数 **organization/models.py** ### 模型中添加排序字段 CourseOrg模型中添加两个字段`students`和`course_nums` ```python # 课程机构信息 class CourseOrg(models.Model): ORG_CHOICES = ( ("pxjg", "培训机构"), ("gx", "高校"), ("gr", "个人"), ) name = models.CharField(max_length=50, verbose_name='机构名称') desc = models.TextField(verbose_name='机构描述') category = models.CharField(choices=ORG_CHOICES, max_length=10, default='pxjg', verbose_name='机构类别') click_nums = models.IntegerField(default=0, verbose_name='点击数') fav_nums = models.IntegerField(default=0, verbose_name='收藏数') students = models.IntegerField(default=0, verbose_name='学习人数') course_nums = models.IntegerField(default=0, verbose_name='课程数数') image = models.ImageField(upload_to='org/%Y/%m', max_length=100, blank=True, null=True, verbose_name='封面图') address = models.CharField(max_length=150, verbose_name='机构地址') city = models.ForeignKey(CityDict, on_delete=models.CASCADE, verbose_name='所在城市') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') class Meta: verbose_name_plural = verbose_name = '课程机构' def __str__(self): return self.name ``` 然后执同步 ```python manage.py@DjangoOnlineLearningPlatform > makemigrations organization manage.py@DjangoOnlineLearningPlatform > migrate organization ``` ### 视图中增加排序OrgListView(View) ```pytohn class OrgListView(View): def get(self, request): # 查找所有的机构 all_org = CourseOrg.objects.all() # 取出所有城市 all_city = CityDict.objects.all() # 机构类别 all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES)) # 热门机构,选择点击数最多的3个机构显示到右边 hot_org = all_org.order_by('-click_nums')[:3] # 处理类别筛选,取回的是字符串 category_code = request.GET.get('category', '') if category_code: all_org = all_org.filter(category=category_code) # 处理城市筛选,取回的是city的ID city_id = request.GET.get('city', '') if city_id: all_org = all_org.filter(city=city_id) # 排序,按照学习人数或者课程数排序 sort = request.GET.get('sort', '') if sort: if sort == 'students': all_org = all_org.order_by('-students') elif sort == 'courses': all_org = all_org.order_by('-course_nums') # 机构数量 org_nums = all_org.count() # 对课程机构进行分页 # 尝试获取前台get请求传递过来的page参数 # 如果是不合法的配置参数默认返回第一页 try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 # 从列表中取5个出来,也就是每页显示5个 p = Paginator(all_org, 5, request=request) all_org = p.page(page) return render(request, 'org-list.html', locals()) ``` ### 模板中排序url修改 ```html <div class="short-lst"> <h2>授课机构<small>(共{{ org_nums }}家,本页显示{{ all_org.object_list.count }}家)</small></h2> <ul> <!-- Short List --> <li> <p><a href="?category={{ category_code }}&city={{ city_id }}" {% ifequal sort '' %} style="font-weight: bold" {% endifequal %}> 全部 </a></p> </li> <li> <p><a href="?sort=students&category={{ category_code }}&city={{ city_id }}" {% ifequal sort 'students' %} style="color: #BEBEBE" {% endifequal %}> 学习人数 ↓</a></p> </li> <li> <p><a href="?sort=courses&category={{ category_code }}&city={{ city_id }}" {% ifequal sort 'courses' %} style="color: #BEBEBE" {% endifequal %}>课程数 ↓</a></p> </li> </ul> </div> ```

很赞哦! (1)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行657天
  • 系统信息:Linux
  • 后台程序:Python: 3.6.6
  • 网站框架:Django: 2.2.12
  • 文章统计:235 篇
  • 文章评论:40 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 公众号:微信扫描二维码,关注我们
  • QQ群:QQ加群,下载网站的学习源码
返回
顶部
标题 换行 登录
网站