derek1184405959

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
CourseOrg

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,
        })
OrgView

 

前端

 <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 }}">学习人数 &#8595;</a></li>
            <li class="{% if sort == 'courses' %}active{% endif %}"><a href="?sort=courses&ct={{ category }}&city={{ city_id }}">课程数 &#8595;</a></li>
        </ul>
    </div>

 

 

posted on 2018-03-24 16:52 zhang_derek 阅读(...) 评论(...) 编辑 收藏

分类:

技术点:

相关文章: