业务逻辑开发
—————— 学习周报 2018.12.30
完成情况:
- 1.配置全局导航
- 2.全局搜索功能开发
- 3.个人信息展示
- 4.修改密码和修改头像
- 5.修改邮箱和用户信息
- 6.我的课程
- 7.我的收藏功能
- 8.我的消息
- 9.登出
- 10.首页功能开发
- 11.404和500页面配置
笔记:
1.配置全局导航
- 修改
index.html
,继承base.html
页面 - 配置首页的
url
跳转: 修改base.html
文件 —— 利用以及写好的url进行相应导航栏配置
<ul>
<li ><a href="index.html">首页</a></li>
<li >
<a href="{% url 'course:course_list' %}">
公开课<img class="hot" src="{% static 'images/nav_hot.png' %}">
</a>
</li>
<li >
<a href="{% url 'org:teacher_list' %}">授课教师</a>
</li>
<li class="active" ><a href="{% url 'org:org_list' %}">授课机构</a></li>
</ul>
- 让跳转之后的栏目呈选中状态:在
base.html
中进行修改 —— 通过request中的path进行判断
<ul>
<li {% if request.path == '/' %}class="active" {% endif %}><a href="{% url 'index' %}">首页</a></li>
<li {% if request.path|slice:'7' == '/course' %}class="active"{% endif %}>
<a href="{% url 'course:course_list' %}">
公开课<img class="hot" src="{% static 'images/nav_hot.png' %}">
</a>
</li>
<li {% if request.path|slice:'12' == '/org/teacher' %}class="active"{% endif %}>
<a href="{% url 'org:teacher_list' %}">授课教师</a>
</li>
<li {% if request.path|slice:'9' == '/org/list' %}class="active" {% endif %}><a href="{% url 'org:org_list' %}">授课机构</a></li>
</ul>
首页点击公开课,跳转进公开课页面,选择栏并呈选中状态:
2.全局搜索功能开发
- 功能:选择搜索类型,输入内容,点击搜索按钮后,然后跳到对应界面
- 具体实现方法:
通过用户在输入搜索内容以后,在它的url
后面加上一个关键词——keywords
,用户输入KeyWords
后,通过数据库中的查询方法来把相关内容给它返回到页面。- 第一:实现课程搜索——重写
course/views.py
中的方法:CourseListView(View)
- 第二:实现机构搜索——重写
organzation/views.py
中的方法:OrgView(View)
- 第三:实现讲师搜索——重写
organzation/views.py
中的方法:TeacherListView(View)
“icontains”是django 中用来搜索语句的一种操作。(一般前面带有“ i ”,那就是搜索内容不区分大小写)
- 第一:实现课程搜索——重写
# 课程搜索
search_keywords = request.GET.get('keywords', "")
if search_keywords:
all_courses = all_courses.filter(
Q(name__icontains=search_keywords) | Q(desc__icontains=search_keywords) | Q(
detail__icontains=search_keywords))
# 机构搜索
search_keywords = request.GET.get('keywords', "")
if search_keywords:
all_orgs = all_orgs.filter(Q(name__icontains=search_keywords) | Q(desc__icontains=search_keywords))
# 课程讲师搜索
search_keywords = request.GET.get('keywords', "")
if search_keywords:
all_teachers = all_teachers.filter(Q(name__icontains=search_keywords)|
Q(work_company__icontains=search_keywords)|
Q(work_position__icontains=search_keywords))
示例1:搜索机构 —— “北京大学”:
示例2:搜索课程 ——“Java入门第一季”:
示例3:搜索讲师 —— “丽丽”:
3.个人信息展示
- 个人中心页面展示以下4大板块
| “个人资料” | “我的课程” | “我的收藏” | “我的消息” | - 先写一个
usercenter_base.html
页面; - 导入
usercenter-info.html
页面,进行修改继承usercenter_base.html
- 在
user/
下新建urls.py
文件,配置url
,
# 用户信息
url(r'^info/$', UserinfoView.as_view(), name="user_info"),
- 在
views.py
中编写实现方法——必须登录才能访问(LoginRequiredMixin
:):
class UserinfoView(LoginRequiredMixin, View):
"""
用户个人信息
"""
def get(self, request):
return render(request, 'usercenter-info.html', {})
def post(self, request):
user_info_form = UserInfoForm(request.POST, instance=request.user)
if user_info_form.is_valid():
user_info_form.save()
return HttpResponse('{"status":"success"}', content_type='application/json')
else:
return HttpResponse(json.dumps(user_info_form.errors), content_type='application/json')
4.修改密码和修改头像
功能:
- 1、点击修改密码,弹出窗口,输入两次一样的新密码就完成修改密码;
- 2、点击修改头像,弹出本地窗口,直接选择图片进行修改;
具体实现:
修改头像:
- 添加
url
:
# 用户头像上传
url(r'^image/upload/$', UploadImageView.as_view(), name="image_upload"),
- 在user/form.py中增加一个方法,专门用来处理用户上传头像:
class UploadImageForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['image']
- 编写
user/views.py
中的方法:
class UploadImageView(LoginRequiredMixin, View):
"""
用户修改头像
"""
def post(self, request):
image_form = UploadImageForm(request.POST, request.FILES, instance=request.user)
if image_form.is_valid():
image_form.save()
return HttpResponse('{"status":"success"}', content_type='application/json')
else:
return HttpResponse('{"status":"fail"}', content_type='application/json')
修改密码:
- 配置
url
:
# 用户个人中心修改密码
url(r'^update/pwd/$', UpdatePwdView.as_view(), name="update_pwd"),
- 编写
user/views.py
中的方法:
class UpdatePwdView(View):
"""
个人中心修改用户密码
"""
def post(self, request):
modify_form = ModifyPwdForm(request.POST)
if modify_form.is_valid():
pwd1 = request.POST.get("password1", "")
pwd2 = request.POST.get("password2", "")
if pwd1 != pwd2:
return HttpResponse('{"status":"fail","msg":"密码不一致"}', content_type='application/json')
user = request.user
user.password = make_password(pwd2)
user.save()
return HttpResponse('{"status":"success"}', content_type='application/json')
else:
return HttpResponse(json.dumps(modify_form.errors), content_type='application/json')
- 当两次密码书写不一致时:
- 当密码小于6位时:
- 当修改密码后,弹出“密码修改成功”,并自动跳转到登录界面:
5.修改邮箱和用户信息
功能:
- 点击修改邮箱,弹出窗口,完成邮箱验证才能进行修改;
具体实现:
- 配置
url
:
# 发送邮箱验证码
url(r'^sendemail_code/$', SendEmailCodeView.as_view(), name="sendemail_code"),
# 修改邮箱
url(r'^update_email/$', UpdateEmailView.as_view(), name="update_email"),
- 编写
user/views.py
中的方法:
class SendEmailCodeView(LoginRequiredMixin, View):
"""
发送邮箱验证码
"""
def get(self, request):
email = request.GET.get('email', '')
if UserProfile.objects.filter(email=email):
return HttpResponse('{"email":"邮箱已经存在"}', content_type='application/json')
send_register_email(email, "update_email")
return HttpResponse('{"status":"success"}', content_type='application/json')
class UpdateEmailView(LoginRequiredMixin, View):
"""
修改个人邮箱
"""
def post(self, request):
email = request.POST.get('email', '')
code = request.POST.get('code', '')
existed_records = EmailVerifyRecord.objects.filter(email=email, code=code, send_type='update_email')
if existed_records:
user = request.user
user.email = email
user.save()
return HttpResponse('{"status":"success"}', content_type='application/json')
else:
return HttpResponse('{"email":"验证码出错"}', content_type='application/json')
- 点击修改,弹出窗口(当输入邮箱是已经被注册的时,提示邮箱已经被注册,当验证码错误时,提示错误):
- 邮箱收到邮件:
当修改的信息更改完成后,点击保存:
6.我的课程
功能:
- 用户点击开始学习后,把用户与课程进行关联;
具体实现:
- 配置
url
:
# 我的课程
url(r'^mycourse/$', MyCourseView.as_view(), name="mycourse"),
- 编写
user/views.py
中的方法:
class MyCourseView(LoginRequiredMixin, View):
"""
我的课程
"""
def get(self, request):
user_courses = UserCourse.objects.filter(user=request.user)
return render(request, 'usercenter-mycourse.html', {
"user_courses":user_courses
})
7.我的收藏功能
功能:
- 收藏里面分为“课程机构收藏”、“授课老师收藏”、“公开课程收藏”
具体实现:
- 配置
url
:
# 我收藏的课程机构
url(r'^myfav/org/$', MyFavOrgView.as_view(), name="myfav_org"),
# 我收藏的授课讲师
url(r'^myfav/teacher/$', MyFavTeacherView.as_view(), name="myfav_teacher"),
# 我收藏的课程
url(r'^myfav/course/$', MyFavCourseView.as_view(), name="myfav_course"),
- 编写
user/views.py
中的方法:
class MyFavOrgView(LoginRequiredMixin, View):
"""
我收藏的课程机构
"""
def get(self, request):
org_list = []
fav_orgs = UserFavorite.objects.filter(user=request.user, fav_type=2)
for fav_org in fav_orgs:
org_id = fav_org.fav_id
org = CourseOrg.objects.get(id=org_id)
org_list.append(org)
return render(request, 'usercenter-fav-org.html', {
"org_list":org_list
})
class MyFavTeacherView(LoginRequiredMixin, View):
"""
我收藏的授课讲师
"""
def get(self, request):
teacher_list = []
fav_teachers = UserFavorite.objects.filter(user=request.user, fav_type=3)
for fav_teacher in fav_teachers:
teacher_id = fav_teacher.fav_id
teacher = Teacher.objects.get(id=teacher_id)
teacher_list.append(teacher)
return render(request, 'usercenter-fav-teacher.html', {
"teacher_list":teacher_list
})
class MyFavCourseView(LoginRequiredMixin, View):
"""
我收藏的课程
"""
def get(self, request):
course_list = []
fav_courses = UserFavorite.objects.filter(user=request.user, fav_type=1)
for fav_course in fav_courses:
course_id = fav_course.fav_id
teacher = Course.objects.get(id=course_id)
course_list.append(teacher)
return render(request, 'usercenter-fav-course.html', {
"course_list":course_list
})
8.我的消息
功能:
- 消息分为“个人消息”、“系统消息”
具体实现:
- 配置
url
:
# 我的消息
url(r'^mymessage/$', MymessageView.as_view(), name="mymessage"),
- 编写
user/views.py
中的方法:
class MymessageView(LoginRequiredMixin, View):
"""
我的消息
"""
def get(self, request):
all_messages = UserMessage.objects.filter(user=request.user.id)
# 用户进入个人消息后清空未读消息的记录
all_unread_messages = UserMessage.objects.filter(user=request.user.id, has_read=False)
for unread_message in all_unread_messages:
unread_message.has_read = True
unread_message.save()
# 对个人消息进行分页
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
p = Paginator(all_messages, 5, request=request)
messages = p.page(page)
return render(request, 'usercenter-message.html', {
"messages":messages
})
9.登出
功能:用户点击退出,则状态栏恢复到未登录状态
在django的core中导入reverse。
- 在
Mxonline/url
中配置url
:
url('^logout/$', LogoutView.as_view(), name="logout"),
- 编写
user/views.py
中的方法:
class LogoutView(View):
"""
用户登出
"""
def get(self, request):
logout(request)
from django.core.urlresolvers import reverse
return HttpResponseRedirect(reverse("index"))
10.首页功能开发
完成首页的课程展示,图片加载,轮播图展示,以及一些逻辑问题。
- 在
Mxonline/url
中配置url
:
from users.views import IndexView
url('^$', IndexView.as_view(), name="index"),
- 编写
user/views.py
中的方法:
class IndexView(View):
# 慕学在线网 首页
def get(self, request):
# 取出轮播图
all_banners = Banner.objects.all().order_by('index')
courses = Course.objects.filter(is_banner=False)[:6]
banner_courses = Course.objects.filter(is_banner=True)[:3]
course_orgs = CourseOrg.objects.all()[:15]
return render(request, 'index.html', {
'all_banners':all_banners,
'courses':courses,
'banner_courses':banner_courses,
'course_orgs':course_orgs
})
- 在
index.html
文件中进行修改; - 后台添加的所有课程已经课程机构,轮播图等进行展示:
11.404和500页面配置
- 在
Mxonline/url
中配置url
:
# 全局404页面配置
handler404 = 'users.views.page_not_found'
handler500 = 'users.views.page_error'
- 导入
404.html,500.html
文件;
- 编写
user/views.py
中的函数:
def page_not_found(request):
#全局404处理函数
from django.shortcuts import render_to_response
response = render_to_response('404.html', {})
response.status_code = 404
return response
def page_error(request):
#全局500处理函数
from django.shortcuts import render_to_response
response = render_to_response('500.html', {})
response.status_code = 500
return response
- 在
Mxonline/setting
中将DBUG关掉,并设置ALLOWED_HOSTS = ['*']
:
在生产环境中一定要更改DBUG为False,否则页面会暴露很多关键信息。
当DEBUG = False时,静态文件的自动寻找就会自动失效,django不会再代管static页面访问。静态文件在生产环境中一般不会用django的服务器,或者java服务器去代理静态文件,都是用http服务器转发的。
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = ['*']
- 在
Mxonline/setting.py
中更改root:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
- 当
DEBUG = False
时,我们可以自己配置一个url
处理函数,自己处理static的访问函数; - 在
Mxonline/url
中配置url
(记得import STATIC_ROOT
):
url(r'^static/(?P<path>.*)$', serve, {"document_root":STATIC_ROOT}),
- 404,505页面展示: