(项目)在线教育平台(六)

八、授课机构功能

1、模板继承

  如果几个页面的大体结构相同,可以使用继承的方式来实现母版的重用性,也就是子版继承母版的内容,既可以使用模板的内容,也可以重写需要改变的地地方。

  首先完成授课机构的页面,通过页面显示发现,

  先把org-list.html页面拷贝到templates下,在该目录下新建base.html页面,然后将org-list.html内容剪切到base.html下,然后修改静态文件的路径,在base.html页面下找到需要block的地方,以供子版继承重写:

  org-list.html继承base.html,自定义org-list.html页面中的内容:

  base.html页面还需要修改的地方是顶部登录注册的显示问题,这个问题和index.html页面的一样,只需要将index页面的拷贝过来即可。

2、后端机构列表接口

2.1 机构列表接口

  在organization/views.oy文件下编写机构列表的接口:

1 class OrgView(View):
2     """机构列表"""
3     def get(self, request):
4         return render(request, 'org-list.html')

  配置url:

1 from organization.views import OrgView
2 
3 urlpatterns = [
4     path('org_list/', OrgView.as_view(), name='org_list')  # 机构列表
5 ]

  然后修改index.html导航栏跳转到机构列表的url:

  现在访问机构列表页就可以看到页面了。

2.2 后台添加数据

  后台添加城市的相关数据:

  后台添加机构的相关数据,不过需要先在organization/models.py机构中添加一个字段category,用来区分机构的类别:

 1 class CourseOrg(models.Model):
 2     """课程机构"""
 3     CATEGORY_CHOICES = (
 4         ('pxjg', '培训机构'),
 5         ('gx', '高校'),
 6         ('gr', '个人')
 7     )
 8     name = models.CharField('机构名称', max_length=50)
 9     category = models.CharField('机构类别', max_length=20, choices=CATEGORY_CHOICES, default='pxjg')
10     desc = models.TextField('机构描述')
11     click_nums = models.IntegerField('点击数', default=0)
12     fav_nums = models.IntegerField('收藏数', default=0)
13     image = models.ImageField('封面图', upload_to='org/%Y/%m', max_length=100)
14     address = models.CharField('地址', max_length=150)
15     city = models.ForeignKey(CityDict, verbose_name='所在城市', on_delete=models.CASCADE)
16     add_time = models.DateTimeField('添加时间', default=datetime.now)
17 
18     class Meta:
19         verbose_name = '课程机构'
20         verbose_name_plural = verbose_name

  修改之后需要迁移数据库。

  在后台添加机构信息的时候需要上传机构的图片,在项目根目录下新建一个media,用来存放上传的图片,然后在settings.py文件中设置上传文件的路径:

1 # 上传文件的路径
2 MEDIA_URL = '/media/'
3 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

  然后现在添加机构的数据:

2.3 完善机构列表的接口

 1 class OrgView(View):
 2     """机构列表"""
 3     def get(self, request):
 4         # 取出所有的机构
 5         all_orgs = CourseOrg.objects.all()
 6         org_nums = all_orgs.count()
 7 
 8         # 取出所有的城市
 9         all_citys = CityDict.objects.all()
10 
11         return render(request, 'org-list.html', {
12             'all_orgs': all_orgs,
13             'all_citys': all_citys,
14             'org_nums': org_nums
15         })

  然后修改前端org-list.html显示的内容:

  要显示后台的图片,需要在settings.py中的TEMPLATES添加图片处理器django.template.context_processors.media,如下:

 1 TEMPLATES = [
 2     {
 3         'BACKEND': 'django.template.backends.django.DjangoTemplates',
 4         'DIRS': [os.path.join(BASE_DIR, 'templates')]
 5         ,
 6         'APP_DIRS': True,
 7         'OPTIONS': {
 8             'context_processors': [
 9                 'django.template.context_processors.debug',
10                 'django.template.context_processors.request',
11                 'django.contrib.auth.context_processors.auth',
12                 'django.contrib.messages.context_processors.messages',
13                 # 图片处理器,为了在课程列表中前面加上MEDIA_URL
14                 'django.template.context_processors.media',
15             ],
16         },
17     },
18 ]

  然后在urls中配置处理图片的url,固定写法:

1 from django.views.static import serve
2 from MxOnline.settings import MEDIA_ROOT
3 
4 urlpatterns = [
5     re_path(r'^media/(?P<path>.*)', serve, {"document_root": MEDIA_ROOT}),  # 处理图片显示
6 ]

  现在刷新列表页即可看到如下效果:

3、分页功能

  机构如果超出每一页的数量,就需要使用分页,在这里使用第三方库django-pure-pagination来实现分页。

3.1 安装

  在虚拟环境中直接pip install django-pure-pagination

3.2 注册

  将pure_pagination注册进INSTALLED_APPS中:

1 INSTALLED_APPS = [
2     'pure_pagination',
3 ]

3.3 在机构列表接口加入分页逻辑

 1 class OrgView(View):
 2     """机构列表"""
 3     def get(self, request):
 4         # 取出所有的机构
 5         all_orgs = CourseOrg.objects.all()
 6         org_nums = all_orgs.count()
 7 
 8         # 取出所有的城市
 9         all_citys = CityDict.objects.all()
10 
11         # 分页
12         try:
13             page = request.GET.get('page', 1)
14         except PageNotAnInteger:
15             page = 1
16         p = Paginator(all_orgs, 5, request=request)
17         orgs = p.page(page)
18 
19         return render(request, 'org-list.html', {
20             'all_orgs': orgs,
21             'all_citys': all_citys,
22             'org_nums': org_nums
23         })

  然后修改org-list.html中的all_orgs:

  在org-list.html中修改前端分页显示的代码:

  刷新列表页后,每页显示5条机构:

4、筛选功能

4.1 城市筛选

  在机构列表接口中完善筛选数据的逻辑:

 1 class OrgView(View):
 2     """机构列表"""
 3     def get(self, request):
 4         # 取出所有的机构
 5         all_orgs = CourseOrg.objects.all()
 6         org_nums = all_orgs.count()
 7 
 8         # 取出所有的城市
 9         all_citys = CityDict.objects.all()
10 
11         # 筛选(从request中获取城市的id)
12         city_id = request.GET.get('city', '')
13         if city_id:
14             all_orgs = all_orgs.filter(city_id=int(city_id))
15 
16         # 分页
17         try:
18             page = request.GET.get('page', 1)
19         except PageNotAnInteger:
20             page = 1
21         p = Paginator(all_orgs, 5, request=request)
22         orgs = p.page(page)
23 
24         return render(request, 'org-list.html', {
25             'all_orgs': orgs,
26             'all_citys': all_citys,
27             'org_nums': org_nums,
28             'city_id': city_id
29         })

  前端显示的修改如下:

4.2 类别筛选

  继续在机构列表接口完善类别筛选功能:

 1 class OrgView(View):
 2     """机构列表"""
 3     def get(self, request):
 4         # 取出所有的机构
 5         all_orgs = CourseOrg.objects.all()
 6 
 7         # 取出所有的城市
 8         all_citys = CityDict.objects.all()
 9 
10         # 城市筛选(从request中获取城市的id)
11         city_id = request.GET.get('city', '')
12         if city_id:
13             all_orgs = all_orgs.filter(city_id=int(city_id))
14 
15         # 类别筛选(从request中获取机构类别ct)
16         category = request.GET.get('ct', '')
17         if category:
18             all_orgs = all_orgs.filter(category=category)
19 
20         # 筛选完再统计数量
21         org_nums = all_orgs.count()
22 
23         # 分页
24         try:
25             page = request.GET.get('page', 1)
26         except PageNotAnInteger:
27             page = 1
28         p = Paginator(all_orgs, 5, request=request)
29         orgs = p.page(page)
30 
31         return render(request, 'org-list.html', {
32             'all_orgs': orgs,
33             'all_citys': all_citys,
34             'org_nums': org_nums,
35             'city_id': city_id,
36             'category': category
37         })

  前端的显示修改内容如下:

  修改完成之后,筛选功能完成,可以根据类别和城市筛选机构:

4.3 机构排名筛选

  机构的排名按照点击量进行排名,在机构列表接口中添加排名筛选逻辑:

 1 class OrgView(View):
 2     """机构列表"""
 3     def get(self, request):
 4         # 取出所有的机构
 5         all_orgs = CourseOrg.objects.all()
 6 
 7         # 取出所有的城市
 8         all_citys = CityDict.objects.all()
 9 
10         # 排名筛选(根据点击量排名)
11         hot_orgs = all_orgs.order_by('-click_nums')[:3]
12 
13         # 城市筛选(从request中获取城市的id)
14         city_id = request.GET.get('city', '')
15         if city_id:
16             all_orgs = all_orgs.filter(city_id=int(city_id))
17 
18         # 类别筛选(从request中获取机构类别ct)
19         category = request.GET.get('ct', '')
20         if category:
21             all_orgs = all_orgs.filter(category=category)
22 
23         # 筛选完再统计数量
24         org_nums = all_orgs.count()
25 
26         # 分页
27         try:
28             page = request.GET.get('page', 1)
29         except PageNotAnInteger:
30             page = 1
31         p = Paginator(all_orgs, 5, request=request)
32         orgs = p.page(page)
33 
34         return render(request, 'org-list.html', {
35             'all_orgs': orgs,
36             'all_citys': all_citys,
37             'org_nums': org_nums,
38             'city_id': city_id,
39             'category': category,
40             'hot_orgs': hot_orgs
41         })

  然后修改前端显示代码:

4.4 学习人数和课程排名筛选

  首先在organization/models.py中的CourseOrg中加入students和course_nums两个字段:

 1 class CourseOrg(models.Model):
 2     """课程机构"""
 3     CATEGORY_CHOICES = (
 4         ('pxjg', '培训机构'),
 5         ('gx', '高校'),
 6         ('gr', '个人')
 7     )
 8     name = models.CharField('机构名称', max_length=50)
 9     category = models.CharField('机构类别', max_length=20, choices=CATEGORY_CHOICES, default='pxjg')
10     desc = models.TextField('机构描述')
11     students = models.IntegerField('学习人数', default=0)
12     course_nums = models.IntegerField('课程数', default=0)
13     click_nums = models.IntegerField('点击数', default=0)
14     fav_nums = models.IntegerField('收藏数', default=0)
15     image = models.ImageField('封面图', upload_to='org/%Y/%m', max_length=100)
16     address = models.CharField('地址', max_length=150)
17     city = models.ForeignKey(CityDict, verbose_name='所在城市', on_delete=models.CASCADE)
18     add_time = models.DateTimeField('添加时间', default=datetime.now)
19 
20     class Meta:
21         verbose_name = '课程机构'
22         verbose_name_plural = verbose_name
23 
24     def __str__(self):
25         return self.name

  然后迁移数据库。

  然后在机构列表接口中完善学习人数和课程数排名的逻辑:

 1 class OrgView(View):
 2     """机构列表"""
 3     def get(self, request):
 4         # 取出所有的机构
 5         all_orgs = CourseOrg.objects.all()
 6 
 7         # 取出所有的城市
 8         all_citys = CityDict.objects.all()
 9 
10         # 排名筛选(根据点击量排名)
11         hot_orgs = all_orgs.order_by('-click_nums')[:3]
12 
13         # 学习人数和课程数排名筛选
14         sort = request.GET.get('sort', '')
15         if sort:
16             if sort == 'students':
17                 all_orgs = all_orgs.order_by('-students')
18             elif sort == 'courses':
19                 all_orgs = all_orgs.order_by('-course_nums')
20 
21         # 城市筛选(从request中获取城市的id)
22         city_id = request.GET.get('city', '')
23         if city_id:
24             all_orgs = all_orgs.filter(city_id=int(city_id))
25 
26         # 类别筛选(从request中获取机构类别ct)
27         category = request.GET.get('ct', '')
28         if category:
29             all_orgs = all_orgs.filter(category=category)
30 
31         # 筛选完再统计数量
32         org_nums = all_orgs.count()
33 
34         # 分页
35         try:
36             page = request.GET.get('page', 1)
37         except PageNotAnInteger:
38             page = 1
39         p = Paginator(all_orgs, 5, request=request)
40         orgs = p.page(page)
41 
42         return render(request, 'org-list.html', {
43             'all_orgs': orgs,
44             'all_citys': all_citys,
45             'org_nums': org_nums,
46             'city_id': city_id,
47             'category': category,
48             'hot_orgs': hot_orgs,
49             'sort': sort
50         })

  然后修改前端代码:

5、我要学习咨询功能

5.1 我要学习咨询接口

  我要学习咨询的表单这次使用ModelForm来实现,首先在organization下新建form.py文件:

1 from django import forms
2 from operation.models import UserAsk
3 
4 
5 class UserAskForm(forms.ModelForm):
6     """我要学习咨询表单验证"""
7     class Meta:
8         model = UserAsk
9         fields = ['name','mobile','course_name']

  编写我要学习咨询的后台接口:

 1 class UserAskView(View):
 2     """我要学习咨询"""
 3     def post(self, request):
 4         userask_form = UserAskForm(request.POST)
 5         if userask_form.is_valid():
 6             # 通过ModelForm可以直接将表单中的内容保存
 7             user_ask = userask_form.save(commit=True)
 8             # 通过ajax提交,给前端返回json数据
 9             return HttpResponse('{"status": "success"}', content_type='application/json')
10         else:
11             return HttpResponse('{"status": "fail", "msg": "添加出错"}', content_type='application/json')

  现在使用路由分发的方式来配置url,首先删除urls.py中的org_list这个路由,然后添加一级路由:

1 urlpatterns = [
2     # path('org_list/', OrgView.as_view(), name='org_list'),  # 机构列表
3     path('org/', include('organization.urls', namespace='org')),  # 机构列表
4 ]

  然后在organization下新建urls.py文件,在这个文件配置机构列表页的相关url,之前删除了机构列表的url,现在将机构列表和我要学习咨询的url都添加到这个文件下:

 1 from django.urls import path, re_path
 2 
 3 from .views import OrgView, UserAskView
 4 
 5 app_name = 'organization'
 6 
 7 urlpatterns = [
 8     path('list/',OrgView.as_view(),name='org_list'),  # 机构列表
 9     path('user_ask/', UserAskView.as_view(), name='user_ask'),  # 我要学习咨询
10 ]

  之前在首页跳转机构列表的url需要修改过来:

  然后在form中添加验证手机号码合法性的逻辑:

 1 import re
 2 
 3 from django import forms
 4 from operation.models import UserAsk
 5 
 6 
 7 class UserAskForm(forms.ModelForm):
 8     """我要学习咨询表单验证"""
 9     class Meta:
10         model = UserAsk
11         fields = ['name','mobile','course_name']
12 
13     def clean_mobile(self):
14         """验证手机号合法性"""
15         mobile = self.cleaned_data['mobile']
16         REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|176\d{8}$"
17         p = re.compile(REGEX_MOBILE)
18         if p.match(mobile):
19             return mobile
20         else:
21             raise forms.ValidationError('手机号非法', code='mobile_invalid')

  我要学习咨询表单是将数据ajax提交到后台的,不刷新页面,所以在前端要编写script代码:

 

posted @ 2018-11-17 15:30  Sweltering  阅读(462)  评论(0编辑  收藏  举报