模板文件夹中加入对应的html文件,并修改对应静态文件
与之前工作一样,在urls.py中建立include,在app中建立url,并写入总多子url
#urls.py
url(r'^courses/', include('courses.url', namespace='courses')), # organiztion 的url分发,namespace用于重名的处理
#app.url.py
urlpatterns = [
url(r'^courses_list/$', CoursesView.as_view(), name='courses_list'),
]
建立视图函数,后面再丰富
class CoursesView(View):
def get(self,request):
return render(request, 'course_list.html',{})
与其他模板复用共有元素(organization_list中能复用的元素),公用header,footer,bread
遍历课程数据,
all_course = Course.objects.all()
return render(request, 'course_list.html',{'all_course':all_course})
并在模板中进行展示
{% for course in all_course %}
<div class="box">
<a href="course-detail.html">
<img width="280" height="350" class="scrollLoading" src="{{ MEDIA_URL }}{{ course.CoursePicture }}"/>
</a>
<div class="des">
<a href="course-detail.html">
<h2>{{ course.CourseName }}</h2>
</a>
<span class="fl">时长:<i class="key">{{ course.LearnTime }}</i></span>
<span class="fr">学习人数:{{ course.Students }} </span>
</div>
<div class="bottom">
<a href="course-detail.html"><span class="fl">{{ course.Organization.Organization }}</span></a>
<span class="star fr notlogin" data-favid="15">
1
</span>
</div>
</div>
{% endfor %}
进行分页展示,参考课程机构列表,使用pure_pagination库进行分页
class CoursesView(View):
def get(self,request):
all_course = Course.objects.all()
###############################分页功能###################################
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
# Provide Paginator with the request object for complete querystring generation
p = Paginator(all_course, 2, request=request)
course = p.page(page)
##########################################################################
return render(request, 'course_list.html',{'all_course':course})
解决页码问题
{# 页码 #}
<div class="pageturn">
<ul class="pagelist">
{% if all_course.has_previous %} {# 判断是否有前一页逻辑 #}
<li class="long"><a href="?{{ all_course.previous_page_number.querystring }}" >上一页</a></li>
{% endif %}
{% for page in all_course.pages %}
{% if page %}
{% ifequal page all_course.number %} {# 判断是否是当前页 #}
<li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li>
{% else %} {# 如果不是当前页的话 #}
<li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
{% endifequal %}
{% endif %}
{% endfor %}
{% if all_course.has_next %} {# 判断是否有后一页逻辑 #}
<li class="long"><a href="?{{ all_course.next_page_number.querystring }}">下一页</a></li>
{% endif %}
</ul>
</div>
排序问题
改造视图函数view,通过get获取网页上传参数,用户数据排规则,并将数据重新返回给模板,用于高亮显示
class CoursesView(View):
def get(self,request):
if request.method == 'GET':
sort = request.GET.get('sort', '')
if sort == 'last':
all_course = Course.objects.all().order_by('-AddTime')
elif sort == 'hot':
all_course = Course.objects.all().order_by('-Students')
elif sort == 'student':
all_course = Course.objects.all().order_by('-ClikeNumber')
else:
all_course = Course.objects.all()
###############################分页功能###################################
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
# Provide Paginator with the request object for complete querystring generation
p = Paginator(all_course, 3, request=request)
course = p.page(page)
##########################################################################
return render(request, 'course_list.html',{'all_course':course,'sort':sort})
热门推荐课程
view.py
hot_course = Course.objects.all().order_by('-FavouriteNumber')[:3]
模板-利用get_model_display用于显示choice的选项代表值
<div class="right layout">
<div class="head">热门课程推荐</div>
<div class="group_recommend">
{% for course in hot_course %}
<dl>
<dt>
<a target="_blank" href="">
<img width="240" height="220" class="scrollLoading" src="{{ MEDIA_URL }}{{ course.CoursePicture }}"/>
</a>
</dt>
<dd>
<a target="_blank" href=""><h2> {{ course.CourseName }}</h2></a>
{# 利用get_model_display用于显示choice的选项代表值 #}
<span class="fl">难度:<i class="key">{{ course.get_degree_display }}</i></span>
</dd>
</dl>
{% endfor %}
</div>
</div>
课程详情配置
在courses_list模板中设定跳转至courses_detail,设置带参数进行跳转
<a href="{% url 'courses:course_detail' course.id %}">
设定app.url,带参数(course.id)传入
url(r'^courses_detail/(?P<course_id>\d+)/$', CourseDetailView.as_view(), name='course_detail'),
配置视图函数,获取course_id,并利用course_id进行数据过滤,get到对应的课程,传入模板中
class CourseDetailView(View):
def get(self,request,course_id):
course_detail = Course.objects.get(id=course_id)
return render(request, 'course_detail.html',{'course_detail':course_detail})
继承相应模板,复用相应元素(header,footer等元素),并修改对应内容,利用传入参数,设置动态内容
{% extends 'organization_base.html' %}
{% load staticfiles %}
{% block title %}公开课详情{% endblock %}
<!DOCTYPE html>
<html>
<body>
{% block header %}填入对应内容{% endblock %}
{% block custom_bread %}填入对应内容{% endblock %}
<!--crumbs start-->
{% block content %}填入对应内容{% endblock %}
{% block custom_js %}填入对应内容{% endblock %}
</body>
</html>
小技巧(主键和外键关系),前提说明:Lesson中有course作为外键,但是course中要获取Lesson的值。则在course中利用函数lesson_set反向进行获取
#Lesson
class Lesson(models.Model):
LessonName = models.CharField(max_length=100,verbose_name=u'章节名称')
Course = models.ForeignKey(Course,verbose_name=u'课程名称')
AddTime = models.DateTimeField(default=datetime.now,verbose_name=u'添加时间')
class Meta:
verbose_name = u'章节'
verbose_name_plural = verbose_name
def __str__(self):
return '{0}'.format(self.LessonName)
#Course
class Course(models.Model):
Organization = models.ForeignKey(CourseOrganization,verbose_name=u'所属机构',null=True,blank=True)
Describe = models.CharField(verbose_name=u'课程简介',max_length=500)
CourseName = models.CharField(max_length=100,verbose_name=u'课程名称')
Detail = models.TextField(verbose_name=u'课程详情')
degree = models.CharField(max_length=10,verbose_name=u'课程难度',choices=(('cj',u'初级'),('zj',u'中级'),('gj',u'高级')))
LearnTime = models.IntegerField(verbose_name=u'学习时长',default=0)
# Lesson = models.IntegerField(verbose_name=u'章节数',default=0)
CourseType = models.CharField(max_length=30,verbose_name=u'课程类型')
#LearnUser = models.ImageField(upload_to='static/Pic/courses/%Y/%m',max_length=500,verbose_name=u'学习用户')
CoursePicture = models.ImageField(upload_to='courses/%Y/%m',max_length=500,verbose_name=u'课程封面')
Students = models.IntegerField(default=0,verbose_name=u'学习人数')
FavouriteNumber = models.IntegerField(default=0,verbose_name=u'喜欢人数')
ClikeNumber = models.IntegerField(default=0,verbose_name=u'点击人数')
AddTime = models.DateTimeField(default=datetime.now,verbose_name=u'添加时间',)
def __str__(self):
return '{0}'.format(self.CourseName)
def get_lesson_nums(self):
"""
course作为lesson的外键,利用self.lesson_set获取lesson参数
"""
lesson_num = self.lesson_set.all().count()
return lesson_num
class Meta:
verbose_name = u'课程信息'
verbose_name_plural = verbose_name
利用“操作”数据库,管理用户和课程的行为。收藏作为一种行为,是将用户与课程进行关联,用于形成复杂的数据用户行为
#UserCourse,内包含User和Course两个外键,是将两个数据进行关联
class UserCourse(models.Model):
User = models.ForeignKey(UserProfile,verbose_name=u'用户')
Course = models.ForeignKey(Course,verbose_name=u'课程')
AddTime = models.DateTimeField(default=datetime.now,verbose_name=u'添加时间')
class Meta:
verbose_name = u'用户课程'
verbose_name_plural =verbose_name
在Course的model中,利用get_study_user函数反向获取usercourse数据库
def get_study_user(self):
study_user = self.usercourse_set.all()[:5]
return study_user
在模板中遍历course_detail.get_study_user,相当于查询所有符合course_id的UserCourse数据,再利用study_user.User.img查询对应的User下的img
{% for study_user in course_detail.get_study_user %}
<span class="pic"><img width="40" height="40" src="{{ MEDIA_URL }}{{ study_user.User.img }}"/></span>
{% endfor %}
其余数据自行进行关联
利用课程标签进行相关课程推荐,现在model中添加标签(Tag),更新数据库,给课程打上标签,视图函数中刷新时,获取到对应course_id的tag值,查询所有课程的tag,匹配出相应推荐课程
1.给model加上tag的参数,makemigration -> migrate
Tag = models.CharField(default='',max_length=10,verbose_name=u'所属机构',null=True,blank=True)
2.获取该课程下的tag参数,若有tag,利用获取的tag进行查询,将相同tag作为推荐课程返回模板中
class CourseDetailView(View):
def get(self,request,course_id):
course_detail = Course.objects.get(id=course_id)
#每次单击进入课程详情页面都会触发一次点击数
course_detail.ClikeNumber+=1
course_detail.save()
#查询所有tag,获取推荐课程
tag = course_detail.Tag
if tag: #如果有打标签
relate_course = Course.objects.filter(Tag=tag).filter(~Q(id= int(course_id)))[:1]
# else:
# relate_course = [] #怎么都要传回一个数组,如果传回模板是空的话,会取不到值,会报错
return render(request, 'course_detail.html',{'course_detail':course_detail,'relate_course':relate_course})
小技巧
1.Django filter符合表示”不等于”
2.filter要用for遍历,get不能遍历
3.多次过滤直接加多几次filter
重点提示
使用了xadmin之后,会在相应app下将model注册进xadmin,若model下的某些参数已经删除,但是在注册进xadmin下未删除,则会出现报错‘FieldDoesNotExist’
class CourseAdmin(object):
list_display = ['CourseName','degree','Lesson','CourseType','Students','FavouriteNumber','ClikeNumber','AddTime']
search_fields = ['CourseName','degree','Lesson','CourseType','Students','FavouriteNumber','ClikeNumber']
list_filter = ['CourseName','degree','Lesson''CourseType','Students','FavouriteNumber','ClikeNumber','AddTime']
#利用 admin.site.register 进行注册
xadmin.site.register(Course,CourseAdmin)
解决方法:
若model下的某些参数已经删除了,相应的将注册进xadmin的参数也删除
class CourseAdmin(object):
list_display = ['CourseName','degree','CourseType','Students','FavouriteNumber','ClikeNumber','AddTime']
search_fields = ['CourseName','degree','CourseType','Students','FavouriteNumber','ClikeNumber']
list_filter = ['CourseName','degree','CourseType','Students','FavouriteNumber','ClikeNumber','AddTime']
#利用 admin.site.register 进行注册
xadmin.site.register(Course,CourseAdmin)
添加课程章节
添加video的播放路径
class Video(models.Model):
LessonName = models.ForeignKey(Lesson,verbose_name=u'章节名称',default='未命名',)
VideoName = models.CharField(max_length=100, verbose_name=u'视频名称')
AddTime = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')
VideoUrl = models.CharField(default='',verbose_name='播放路径',max_length=200,null=True,blank=True) #播放地址
class Meta:
verbose_name = u'视频'
verbose_name_plural = verbose_name
在xadmin中添加课程和视频信息
完善model,利用_set函数获取外键信息
#model中利用_set函数获取外键信息
class Lesson(models.Model):
LessonName = models.CharField(max_length=100,verbose_name=u'章节名称',default='未命名',null=True,blank=True)
Course = models.ForeignKey(Course,verbose_name=u'课程名称')
AddTime = models.DateTimeField(default=datetime.now,verbose_name=u'添加时间')
class Meta:
verbose_name = u'章节'
verbose_name_plural = verbose_name
def __str__(self):
return '{0}'.format(self.LessonName)
#获取各个章节下的课程video
def get_video(self):
video = self.video_set.all()
return video
class Video(models.Model):
LessonName = models.ForeignKey(Lesson,verbose_name=u'章节名称',default='未命名',)
VideoName = models.CharField(max_length=100, verbose_name=u'视频名称')
AddTime = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')
VideoUrl = models.CharField(default='',verbose_name='播放路径',max_length=200,null=True,blank=True) #播放地址
LearnTime = models.IntegerField(verbose_name=u'学习时长',default=0)
class Meta:
verbose_name = u'视频'
verbose_name_plural = verbose_name
def __str__(self):
return '{0}'.format(self.VideoName)
class CourseResource(models.Model):
Course = models.ForeignKey(Course, verbose_name=u'课程')
Name = models.CharField(max_length=100, verbose_name=u'名称')
DownLoad = models.FileField(upload_to='course/resource/%Y/%m/%d',max_length=100, verbose_name=u'下载')
AddTime = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')
class Meta:
verbose_name = u'课程资源'
verbose_name_plural = verbose_name
附件上传利用models.FileField,将路径会上传至media路径下,在模板中要切记添加{{MEDIA_URL}},该可以路由至正确地址进行下载
DownLoad = models.FileField(upload_to='course/resource/%Y/%m/%d',max_length=100, verbose_name=u'下载')
完成课程信息的视图函数
#课程通过筛选项对数据进行过滤
class CoursesView(View):
def get(self,request):
###############################筛选功能###################################
sort = request.GET.get('sort', '')
if sort == 'last':
all_course = Course.objects.all().order_by('-AddTime')
elif sort == 'hot':
all_course = Course.objects.all().order_by('-Students')
elif sort == 'student':
all_course = Course.objects.all().order_by('-ClikeNumber')
else:
all_course = Course.objects.all()
###############################分页功能###################################
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
# Provide Paginator with the request object for complete querystring generation
p = Paginator(all_course,9, request=request)
course = p.page(page)
###########################热门课程推荐################################
hot_course = Course.objects.all().order_by('-FavouriteNumber')[:3]
return render(request, 'course_list.html',{'all_course':course,'sort':sort,'hot_course':hot_course})
#通过course_id选择到正确的课程进行信息展示,通过标签的方式,完成课程推荐动作
class CourseDetailView(View):
def get(self,request,course_id):
course_detail = Course.objects.get(id=course_id)
#每次单击进入课程详情页面都会触发一次点击数
course_detail.ClikeNumber+=1
course_detail.save()
#查询所有tag,获取推荐课程
tag = course_detail.Tag
if tag: #如果有打标签
relate_course = Course.objects.filter(Tag=tag).filter(~Q(id= int(course_id)))[:1]
# else:
# relate_course = [] #怎么都要传回一个数组,如果传回模板是空的话,会取不到值,会报错
return render(request, 'course_detail.html',{'course_detail':course_detail,'relate_course':relate_course})
#通过course_id获取课程下的lesson和course_resourse,并将信息返回至模板中通过遍历对信息进行展示
class CourseVideoView(View):
def get(self,request,course_id):
course = Course.objects.get(id=course_id)
lesson = Lesson.objects.filter(Course=course)
course_resource = CourseResource.objects.filter(Course=course)
##########################学过该课程的同学还学过##########################
#利用opreation-UserCourse记录的用户行为
Other_User = UserCourse.objects.filter(Course=course)
Other_User_List = []
for u in Other_User:
Other_User_List.append(u.id)
##########################################################################
return render(request, 'course_video.html',{'course':course,'lesson':lesson,'course_resource':course_resource})
关于站内绝对地址和相对地址跳转和站外访问
1.绝对地址:在要模板中,要跳转的绝对地址前加上反斜杠“/”
2.相对地址:在要模板中,要跳转的相对地址中,直接加上要访问的地址
3.站外访问:外站需要包含协议(http)域名的,如果省略域名则浏览器会认为是当前域名
“学过该课程的同学还学过”,该处需要利用用户行为的数据,创建用户行为数据,通过该课程的id查询所有学习过该课程的用户,通过遍历所有学习过该课程的用户及用户数据下的学习的所有的课程数据,进行推荐
#用户行为记录数据,用于绑定记录用户和用户学习过的课程的行为
class UserCourse(models.Model):
User = models.ForeignKey(UserProfile,verbose_name=u'用户')
Course = models.ForeignKey(Course,verbose_name=u'课程')
AddTime = models.DateTimeField(default=datetime.now,verbose_name=u'添加时间')
class Meta:
verbose_name = u'用户课程'
verbose_name_plural =verbose_name
#对学习过该课程的用户进行遍历,获取其他用户还学习过的课程
class CourseVideoView(View):
def get(self,request,course_id):
course = Course.objects.get(id=course_id)
lesson = Lesson.objects.filter(Course=course)
course_resource = CourseResource.objects.filter(Course=course)
##########################学过该课程的同学还学过##########################
#利用opreation-UserCourse记录的用户行为,在用户选择学习后,需要将用户行为存储进入该数据库中
Other_User_List = UserCourse.objects.filter(Course=course) #利用课程数据遍历出所有学习该课程下的用户
Related_Courses = set()
Related_Courses_id = set()
for u in Other_User_List:
user_courses = UserCourse.objects.filter(User_id=u.id) #遍历所有用户,并利用用户id遍历出所有的course,注意起名字不要重复了
for c in user_courses:
if c.Course_id not in Related_Courses_id: #利用课程id进行去重
Related_Courses.add(c)
Related_Courses_id.add(c.Course_id)
##########################################################################
return render(request, 'course_video.html',{'course':course,'lesson':lesson,'course_resource':course_resource,'Related_Courses':Related_Courses,})