Django+xadmin打造在线教育平台(四)
七、授课机构功能
7.1.模板继承
(1)创建母板
把org-list.html拷贝到templates目录下,新建base.html,剪切org-list.html内容到里面
再修改一下静态文件的地址(css、就是、image和media)
(2)机构首页路由
from organization.views import OrgView path('org_list/',OrgView.as_view(),name = 'org_list'),
(3)机构views
class OrgView(View): '''课程机构''' def get(self,request): return render(request,'org-list.html')
(4)org-list.html继承base
{#templates/org-list.html#}
{% extends 'base.html' %}
{% block title %}
课程机构列表
{% endblock %}
访问:http://127.0.0.1:8000/org_list/ 可以看到org_list页面
(5)修改base模板
把base中custom_bread和content两个block的内容剪切到org-list.html里面
base.html
org-list.html
7.2.添加城市和课程机构
(1)进xadmin后台添加城市
这里机构是静态固定不变的,所在地区是动态的,从数据库中获取得到的
(2)修改机构的models,添加一个机构类别字段
organization/models.py:
class CourseOrg(models.Model): ORG_CHOICES = ( ("pxjg", u"培训机构"), ("gx", u"高校"), ("gr", u"个人"), ) #添加字段 category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name=u"机构类别", default="pxjg")
class CourseOrg(models.Model): ORG_CHOICES = ( ("pxjg", u"培训机构"), ("gx", u"高校"), ("gr", u"个人"), ) name = models.CharField('机构名称',max_length=50) desc = models.TextField('机构描述') category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name=u"机构类别", default="pxjg") click_nums = models.IntegerField('点击数',default=0) fav_nums = models.IntegerField('收藏数',default=0) image = models.ImageField('logo',upload_to='org/%Y%m',max_length=100) address = models.CharField('机构地址',max_length=150,) city = models.ForeignKey(CityDict,verbose_name='所在城市',on_delete=models.CASCADE) add_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '课程机构' verbose_name_plural = verbose_name def __str__(self): return self.name
添加后makemigrations-->>migrate
(3)添加机构
添加机构信息的时候要上传机构的图片
在项目目录下面新建一个目录“media”,用来存放上传的图片
setting中要配置我们把文件存放在哪个根目录之下
#settings.py # 设置上传文件的路径 MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR,'media') #指定根目录
会跟upload里面拼接完整的路径
“/media/org/2018/月份/图片名字”
然后在后台添加十个机构
7.3.显示课程机构和城市
(1)写视图函数organization/views.py
class OrgView(View): '''课程机构''' def get(self,request): # 取出所有课程机构 all_orgs = CourseOrg.objects.all() org_onums = all_orgs.count() # 取出所有城市 all_citys = CityDict.objects.all() return render(request, "org-list.html", { "all_orgs": all_orgs, "all_citys": all_citys, 'org_onums':org_onums, })
(2)修改org-list.html
显示机构总共数量
显示城市
显示机构
然后还要做下面的设置
如何将image Field转换成图片地址
数据库中image以字符串格式保存的,是相对路径,直接取是取不出来的,必须补全路径
data-url="{{ MEDIA_URL }}{{ course_org.image }}"
MEDIA_URL = '/media/',这个是之前settings中设置好了
要向使用{{ MEDIA_URL }},要先在settings中TEMPLATES 里面添加media处理器:'django.core.context_processors.media'
然后也要添加处理图片相应路径的url
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', #添加图片处理器,为了在课程列表中前面加上MEDIA_URL 'django.template.context_processors.media', ], }, }, ]
urls.py
from django.views.static import serve from MxOnline.settings import MEDIA_ROOT # 处理图片显示的url,使用Django自带serve,传入参数告诉它去哪个路径找,我们有配置好的路径MEDIAROOT re_path(r'^media/(?P<path>.*)', serve, {"document_root": MEDIA_ROOT })
四个地方
7.4.分页功能
使用 分页神器 django-pure-pagination 分页,github上面有介绍使用方法
(1)安装
pip install django-pure-pagination
(2)settings里面添加
INSTALLED_APPS = ( ... 'pure_pagination', )
(3)views中使用方法
class OrgView(View): '''课程机构''' def get(self, request): # 所有课程机构 all_orgs = CourseOrg.objects.all() # 有多少家机构 org_nums = all_orgs.count() # 所有城市 all_citys = CityDict.objects.all() # 对课程机构进行分页 # 尝试获取前台get请求传递过来的page参数 # 如果是不合法的配置参数默认返回第一页 try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 # 这里指从allorg中取五个出来,每页显示5个 p = Paginator(all_orgs, 5, request=request) orgs = p.page(page) return render(request, "org-list.html", { "all_orgs": orgs, "all_citys": all_citys, "org_nums": org_nums, })
(4)修改org-list.html
这里变成 "all_orgs.object_list"
分页功能
<div class="pageturn"> <ul class="pagelist"> {% if all_orgs.has_previous %} <li class="long"><a href="?{{ all_orgs.previous_page_number.querystring }}">上一页</a></li> {% endif %} {% for page in all_orgs.pages %} {% if page %} {% ifequal page all_orgs.number %} <li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li> {% else %} <li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li> {% endifequal %} {% else %} <li class="none"><a href="">...</a></li> {% endif %} {% endfor %} {% if all_orgs.has_next %} <li class="long"><a href="?{{ all_orgs.next_page_number.querystring }}">下一页</a></li> {% endif %} </ul> </div>
改成每页显示2个列表,如下:
7.5.列表筛选功能
(1)城市列表筛选
- 点城市,筛选出对应的课程机构
- 默认“全部”是‘active’状态(绿色),如果点了某个城市,应该城市是‘active’状态
- 当用户点击city时,应该把city的id传到后台,然后后台在传到模板中,是的可以知道哪个城市被选中,然后加上‘’active‘’
后台处理city筛选
class OrgView(View): '''课程机构''' def get(self, request): # 所有课程机构 all_orgs = CourseOrg.objects.all() # 有多少家机构 org_nums = all_orgs.count() # 所有城市 all_citys = CityDict.objects.all() city_id = request.GET.get('city','') if city_id: all_orgs = all_orgs.filter(city_id=int(city_id)) # 对课程机构进行分页 # 尝试获取前台get请求传递过来的page参数 # 如果是不合法的配置参数默认返回第一页 try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 # 这里指从allorg中取五个出来,每页显示5个 p = Paginator(all_orgs, 2, request=request) orgs = p.page(page) return render(request, "org-list.html", { "all_orgs": orgs, "all_citys": all_citys, "org_nums": org_nums, 'city_id':city_id, })
前端页面
<h2>所在地区</h2> <div class="more">更多</div> <div class="cont"> <a href="?ct="><span class="{% ifequal city_id '' %}active2{% endifequal %}">全部</span></a> {% for city in all_citys %} <a href="?city={{ city.id }}"><span class="{% ifequal city.id|stringformat:'i' city_id %}active2{% endifequal %}">{{ city.name }}</span></a> {% endfor %} </div>
因为city.id是一个int类型,要转换成字符串,再作比较。
{% ifequal city_id '' %} 如果为空,说明没有city选中,则“全部”是“active”
(2)类别筛选
后台处理
# 类别筛选 category = request.GET.get('ct','') if category: all_orgs = all_orgs.filter(category=category) # 有多少家机构 org_nums = all_orgs.count()
把org_numsf放到后面,先筛选在统计数量
模板中
<h2>机构类别</h2> <div class="cont"> <a href="?city={{ city_id }}"><span class="{% ifequal category '' %}active2{% endifequal %}">全部</span></a> <a href="?ct=pxjg&city={{ city_id }}"><span class="{% ifequal category 'pxjg' %}active2{% endifequal %}">培训机构</span></a> <a href="?ct=gx&city={{ city_id }}"><span class="{% ifequal category 'gx' %}active2{% endifequal %}">高校</span></a> <a href="?ct=gr&city={{ city_id }}"><span class="{% ifequal category 'gr' %}active2{% endifequal %}">个人</span></a> </div>
<h2>所在地区</h2> <div class="more">更多</div> <div class="cont"> <a href="?ct={{ category }}"><span class="{% ifequal city_id '' %}active2{% endifequal %}">全部</span></a> {% for city in all_citys %} <a href="?city={{ city.id }}&ct={{ category }}"><span class="{% ifequal city_id city.id|stringformat:"i" %}active2{% endifequal %}">{{ city.name }}</span></a> {% endfor %} </div>
进行城市与分类的联动:
- 当选择全部类别的时候,就只通过当前城市id。
- 当选择全部城市的时候,就只通过当前目录id。
- 当两者都选的时候使用&连接。
(3)课程机构排名筛选
后台处理
按点击量排名,只取前三个
# 热门课程机构排名 hot_orgs = all_orgs.order_by('-click_nums')[:3]
模板中
<div class="right companyrank layout"> <div class="head">授课机构排名</div> {% for curent_org in hot_orgs %} <dl class="des"> <dt class="num fl">{{ foorloop.counter }}</dt> <dd> <a href="/company/2/"><h1>{{ curent_org.name }}</h1></a> <p>{{ curent_org.address }}</p> </dd> </dl> {% endfor %} </div>
循环时内置变量forloop.counter取当前循环到第几次
(4)学习人数和课程的筛选
在models中添加学习人数和课程数两个字段
students = models.IntegerField("学习人数",default=0) course_nums = models.IntegerField("课程数",default=0)
class CourseOrg(models.Model): ORG_CHOICES = ( ("pxjg", u"培训机构"), ("gx", u"高校"), ("gr", u"个人"), ) name = models.CharField('机构名称',max_length=50) desc = models.TextField('机构描述') category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name=u"机构类别", default="pxjg") click_nums = models.IntegerField('点击数',default=0) fav_nums = models.IntegerField('收藏数',default=0) students = models.IntegerField("学习人数",default=0) course_nums = models.IntegerField("课程数",default=0) image = models.ImageField('logo',upload_to='org/%Y/%m',max_length=100) address = models.CharField('机构地址',max_length=150,) city = models.ForeignKey(CityDict,verbose_name='所在城市',on_delete=models.CASCADE) add_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '课程机构' verbose_name_plural = verbose_name def __str__(self): return self.name
migrate到数据库
后台处理
# 学习人数和课程数筛选 sort = request.GET.get('sort', "") if sort: if sort == "students": all_orgs = all_orgs.order_by("-students") elif sort == "courses": all_orgs = all_orgs.order_by("-course_nums")
class OrgView(View): '''课程机构''' def get(self, request): # 所有课程机构 all_orgs = CourseOrg.objects.all() # 所有城市 all_citys = CityDict.objects.all() # 城市筛选 city_id = request.GET.get('city','') if city_id: all_orgs = all_orgs.filter(city_id=int(city_id)) # 类别筛选 category = request.GET.get('ct','') if category: all_orgs = all_orgs.filter(category=category) # 热门课程机构排名 hot_orgs = all_orgs.order_by('-click_nums')[:3] # 学习人数和课程数筛选 sort = request.GET.get('sort', "") if sort: if sort == "students": all_orgs = all_orgs.order_by("-students") elif sort == "courses": all_orgs = all_orgs.order_by("-course_nums") # 有多少家机构 org_nums = all_orgs.count() # 对课程机构进行分页 # 尝试获取前台get请求传递过来的page参数 # 如果是不合法的配置参数默认返回第一页 try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 # 这里指从allorg中取五个出来,每页显示5个 p = Paginator(all_orgs, 2, request=request) orgs = p.page(page) return render(request, "org-list.html", { "all_orgs": orgs, "all_citys": all_citys, "org_nums": org_nums, 'city_id':city_id, "category": category, 'hot_orgs':hot_orgs, 'sort':sort, })
前端
<div class="head"> <ul class="tab_header"> <li class="{% if sort == '' %}active{% endif %}"><a href="?sort=students&ct={{ category }}&city={{ city_id }}">全部</a></li> <li class="{% if sort == 'students' %}active{% endif %}"><a href="?sort=students&ct={{ category }}&city={{ city_id }}">学习人数 ↓</a></li> <li class="{% if sort == 'courses' %}active{% endif %}"><a href="?sort=courses&ct={{ category }}&city={{ city_id }}">课程数 ↓</a></li> </ul> </div>
posted on 2018-03-24 16:52 zhang_derek 阅读(...) 评论(...) 编辑 收藏