八、授课机构功能

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代码:

 

版权声明:本文为Sweltering原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Sweltering/archive/2018/11/17/9973522.html