Django+Xadmin打造在线教育系统(七)

Stella981
• 阅读 667

全局导航&个人中心&全局搜索

配置全局导航

让index页面也继承base页面,注意首页有个单独的__index.js__ base页面的导航栏也进行配置

    <nav>
        <div class="nav">
            <div class="wp">
                <ul>
                    <li ><a href="{% url 'index' %}">首页</a></li>
                    <li >
                        <a href="{% url '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>
            </div>
        </div>
    </nav>

但是现在我们不知道当前是哪一个页面,因为后端没有传值过来 这里可以使用request.path进行判断 比如http://127.0.0.1:8000/org/teacher_list/,则request.path 就是`/org/teacher_list/`` slice:12 是过滤器,取前12位数 利用这种方法可以达到全局的“active”效果,而不用每个子页面都要去设置“active”了

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

全局搜索功能

通过url中加参数keywords来达到全局搜索的功能

以Course搜索为例:

        # 搜索功能
        search_keywords = request.GET.get('keywords', '')
        if search_keywords:
            # icontains是包含的意思(不区分大小写)
            # Q可以实现多个字段,之间是or的关系
            all_course = all_course.filter(
                Q(name__icontains=search_keywords) | Q(desc__icontains=search_keywords) | Q(
                    detail__icontains=search_keywords))

搜索的代码放在deco-common.js中 如果自己写的url和js文件中的不同,可自行修改

//顶部搜索栏搜索方法
function search_click(){
    var type = $('#jsSelectOption').attr('data-value'),
        keywords = $('#search_keywords').val(),
        request_url = '';
    if(keywords == ""){
        return
    }
    if(type == "course"){
        request_url = "/course/list?keywords="+keywords
    }else if(type == "teacher"){
        request_url = "/org/teacher/list?keywords="+keywords
    }else if(type == "org"){
        request_url = "/org/list?keywords="+keywords
    }
    window.location.href = request_url
}

课程机构搜索功能

    # 机构搜索功能
    search_keywords = request.GET.get('keywords', '')
    if search_keywords:
        # 在name字段进行操作,做like语句的操作。i代表不区分大小写
        # or操作使用Q
        all_orgs = all_orgs.filter(Q(name__icontains=search_keywords) | Q(desc__icontains=search_keywords))

授课老师搜索功能

        # 搜索功能
        search_keywords = request.GET.get('keywords', '')
        if search_keywords:
            # 在name字段进行操作,做like语句的操作。i代表不区分大小写
            # or操作使用Q
            all_teachers = all_teacher.filter(name__icontains=search_keywords)

个人中心信息展示

新建usercenter-bae.html当模板 进行配置

 path("users/", include('users.urls', namespace="users")),


from django.urls import path

from users.views import UserinfoView

app_name = 'users'

urlpatterns = [
    #用户信息
    path("info/", UserinfoView.as_view(),name='user_info'),
]


class UserinfoView(LoginRequiredMixin,View):
    '''用户个人信息'''
    def get(self,request):
        return render(request,'usercenter-info.html',{})

前端显示个人信息

    <div class="right">
        <div class="personal_des ">
            <div class="head" style="border:1px solid #eaeaea;">
                <h1>个人信息</h1>
            </div>
            <div class="inforcon">
                <div class="left" style="width:242px;">
                    <iframe id='frameFile' name='frameFile' style='display: none;'></iframe>
                    <form class="clearfix" id="jsAvatarForm" enctype="multipart/form-data" autocomplete="off" method="post" action="/users/image/upload/" target='frameFile'>
                        <label class="changearea" for="avatarUp">
                            <span id="avatardiv" class="pic">
                                <img width="100" height="100" class="js-img-show" id="avatarShow" src="{{ MEDIA_URL }}{{ request.user.image }}"/>
                            </span>
                            <span class="fl upload-inp-box" style="margin-left:70px;">
                                <span class="button btn-green btn-w100" id="jsAvatarBtn">修改头像</span>
                                <input type="file" name="image" id="avatarUp" class="js-img-up"/>
                            </span>
                        </label>
                        {% csrf_token %}
                    </form>
                    <div style="border-top:1px solid #eaeaea;margin-top:30px;">
                        <a class="button btn-green btn-w100" id="jsUserResetPwd" style="margin:80px auto;width:100px;">修改密码</a>
                    </div>
                </div>
                <form class="perinform" id="jsEditUserForm" autocomplete="off">
                    <ul class="right">
                        <li>昵&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;称:
                           <input type="text" name="nick_name" id="nick_name" value="{{ request.user.name }}" maxlength="10">
                            <i class="error-tips"></i>
                        </li>
                        <li>生&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;日:
                           <input type="text" id="birth_day" name="birday" value="{{ request.user.birthday }}" readonly="readonly"/>
                            <i class="error-tips"></i>
                        </li>
                        <li>性&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;别:
                            <label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="radio"  name="gender" value="male"
                                    {% ifequal request.user.gender "male"  %}
                                    checked="checked"
                                    {% endifequal %}
                                    >男</label>
                            <label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="radio" name="gender" value="female"
                                    {% ifequal request.user.gender "female"  %}
                                    checked="checked"
                                    {% endifequal %}
                            >女</label>
                        </li>
                        <li class="p_infor_city">地&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;址:
                            <input type="text" name="address" id="address" placeholder="请输入你的地址" value="{{ request.user.address }}" maxlength="10">
                            <i class="error-tips"></i>
                        </li>
                        <li>手&nbsp;&nbsp;机&nbsp;&nbsp;号:
                            <input type="text" name="mobile" id="mobile" placeholder="请输入你的手机号码" value="{{ request.user.mobile|default_if_none:'' }}" maxlength="11">
                        </li>
                        <li>邮&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱:
                            <input class="borderno" type="text" name="email" readonly="readonly" value="{{ request.user.email }}"/>
                            <span class="green changeemai_btn">[修改]</span>
                        </li>
                        <li class="button heibtn">
                            <input type="button" id="jsEditUserBtn" value="保存">
                        </li>
                    </ul>
                    {% csrf_token %}
                </form>
            </div>
        </div>
    </div>

修改密码和修改头像

    #用户图像上传
    path("image/upload/", UploadImageView.as_view(),name='image_upload'),

新建一个用于保存图片的form 这里继承的是ModelForm,该类具有save功能

# 用于文件上传,修改头像
class UploadImageForm(forms.ModelForm):

    class Meta:
        model = UserProfile
        fields = ['image']


class UploadImageView(LoginRequiredMixin,View):
    '''用户图像修改'''
    def post(self,request):
        # 这时候用户上传的文件就已经被保存到image_form了 ,为modelform添加instance值直接保存
        image_form = UploadImageForm(request.POST, request.FILES, instance=request.user)
        if image_form.is_valid():
            image_form.save()
            # 所有验证通过的字段放在cleaned data
            # # 取出cleaned data中的值,一个dict
            # image = image_form.cleaned_data['image']
            # request.user.image = image
            # request.user.save()
            return HttpResponse('{"status":"success"}', content_type='application/json')
        else:
            return HttpResponse('{"status":"fail"}', content_type='application/json')


#用户个人中心修改密码
    path("update/pwd/", UpdatePwdView.as_view(),name='update_pwd'),


# 在个人中心修改用户密码
class UpdatePwdView(View):
    def post(self, request):
        modiypwd_form = ModifyPwdForm(request.POST)
        if modiypwd_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)
            # save保存到数据库
            user.save()
            return HttpResponse('{"status":"success"}', content_type='application/json')
        # 验证失败说明密码位数不够。
        else:
            return HttpResponse('{"status":"fail", "msg":"填写错误请检查"}', content_type='application/json')

Ajxa代码放在deco-user.js里面 如果url不正确可自行配置' 如果遇到403,检查base中的csrf_token是否填写

发送修改邮箱验证码

有两个接口需要完成。点击获取验证码时,后台需要向用户新邮箱发送验证码。 邮箱如果出错,会返回错误信息。 输入了邮箱和验证码,验证是否匹配。 给EmailVerifyRecord再添加一个选择类型

    SEND_CHOICES = (
        ("register", "注册"),
        ("forget", "找回密码"),
        ("update_email", "修改邮箱")
    )


    #发送邮箱验证码
    path("sendemail_code/", SendEmailCodeView.as_view(),name='sendemail_code'),


# 发送邮箱验证码view
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_eamil(email, "update_email")
        return HttpResponse('{"status":"success"}', content_type='application/json')

修改utils/email_send.py

    if send_type == "update_email":
        email_title = "慕课在线 修改邮箱"
        email_body = "验证码:{0}".format(code)

        # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,从哪里发,接受者list
        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        # 如果发送成功
        if send_status:
            pass

修改邮箱

    #修改邮箱
    path("update_email/", UpdateEmailView.as_view(),name='update_email'),


# 修改邮箱的view:
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')

个人信息修改

# 个人中心信息修改
class UserInfoForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ['nick_name','gender','birthday','address','mobile']

UserinfoView添加post方法

class UserinfoView(LoginRequiredMixin,View):
    '''用户个人信息'''
    def get(self,request):
        return render(request,'usercenter-info.html',{})

    def post(self, request):
        # 需要指明instance。不然无法修改,而是新增用户
        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')

我的课程

# 用户中心我的课程
path('mycourse/', MyCourseView.as_view(), name="mycourse"),


# 个人中心页我的课程
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,
        })


    {% block custom_right_content %}
        <div class="right" >
            <div class="personal_des Releasecont">
                <div class="head">
                    <h1>我的课程</h1>
                </div>
            </div>
            <div class="personal_des permessage">
                <div class="companycenter">
                    <div class="group_list brief">
                        {% for cours in user_courses %}
                            <div class="module1_5 box">
                                <a href="course-detail.html">
                                    <img width="214" height="190" class="scrollLoading" src="{{ MEDIA_URL }}{{ cours.course.image }}"/>
                                </a>
                                <div class="des">
                                    <a href="course-detail.html"><h2>{{ cours.course.name }}</h2></a>
                                    <span class="fl">课时:<i class="key">{{ cours.course.learn_times }}</i></span>
                                    <span class="fr">学习人数:{{ cours.course.students }}</span>
                                </div>
                                <div class="bottom">
                                    <span class="fl">{{ cours.course.course_org.name }}</span>
                                    <span class="star fr  notlogin" data-favid="15">{{ cours.course.course_org.fav_nums }}</span>
                                </div>
                            </div>
                        {% endfor %}
                    </div>
                </div>
            </div>
        </div>
    {% endblock %}

我的收藏--课程机构

 # 我的收藏--课程机构
    path('myfav/org/', MyFavOrgView.as_view(), name="myfav_org"),


# 我收藏的课程机构
class MyFavOrgView(LoginRequiredMixin, View):
    def get(self, request):
        org_list = []
        fav_orgs= UserFavorite.objects.filter(user=request.user, fav_type=2)
        # 上面的fav_orgs只是存放了id。我们还需要通过id找到机构对象
        for fav_org in fav_orgs:
            # 取出fav_id也就是机构的id。
            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,
        })

我的收藏--授课讲师

Teacher添加一个方法

    def get_course_nums(self):
        return self.course_set.all().count()


# 我收藏的授课讲师
path('myfav/teacher/', MyFavTeacherView.as_view(), name="myfav_teacher"),


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

我的收藏--公开课程

 #我的收藏--课程
    path('myfav/course/', MyFavCourseView.as_view(), name="myfav_course"),


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
            course = Course.objects.get(id=course_id)
            course_list.append(course)

        return render(request, 'usercenter-fav-course.html', {
            "course_list":course_list,
        })

我的消息页面

#我的消息
    path('my_message/', MyMessageView.as_view(), name="my_message"),


class MyMessageView(LoginRequiredMixin, View):
    '''我的消息'''

    def get(self, request):
        all_message = UserMessage.objects.filter(user= request.user.id)

        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        p = Paginator(all_message, 4,request=request)
        messages = p.page(page)
        return  render(request, "usercenter-message.html", {
        "messages":messages,
        })

取消收藏

修改usercenter-bae.html模板中的Ajax代码 Django+Xadmin打造在线教育系统(七)

修改HTML文件 Django+Xadmin打造在线教育系统(七)

注册时发生欢迎消息

# 写入欢迎注册消息
           user_message = UserMessage()
           user_message.user = user_profile.id
           user_message.message = "欢迎注册!!"
           user_message.save()

页面顶部小喇叭

所有页面都要读取一个共同的变量:未读消息的数量。我们需要向request中注入这个变量 所有页面都有request.user对象。所以我们在userprofile中自定义方法,

# 获取用户未读消息的数量
def unread_nums(self):
    from operation.models import UserMessage
    return  UserMessage.objects.filter(user=self.id).count()

退出

# 退出功能url
path('logout/', LogoutView.as_view(), name="logout"),


class LogoutView(View):
    def get(self, request):
        # django自带的logout
        logout(request)
        # 重定向到首页,
        return HttpResponseRedirect(reverse("index"))

点击数加1

课程 CourseInfoView

course.students += 1
course.save()

TeacherDetailView

teacher.click_nums += 1
teacher.save()

OrgHomeView

course_org.click_nums += 1
course_org.save()

收藏数

organization/views.py中的 AddFavView

        if exist_records:
            # 如果记录已经存在, 则表示用户取消收藏
            exist_records.delete()
            if int(type) == 1:
                course = Course.objects.get(id=int(id))
                course.fav_nums -= 1
                if course.fav_nums < 0:
                    course.fav_nums = 0
                course.save()
            elif int(type) == 2:
                org = CourseOrg.objects.get(id=int(id))
                org.fav_nums -= 1
                if org.fav_nums < 0:
                    org.fav_nums = 0
                org.save()
            elif int(type) == 3:
                teacher = Teacher.objects.get(id=int(id))
                teacher.fav_nums -= 1
                if teacher.fav_nums < 0:
                    teacher.fav_nums = 0
                teacher.save()

            return HttpResponse('{"status":"success", "msg":"收藏"}', content_type='application/json')
        else:
            user_fav = UserFavorite()
            # 过滤掉未取到fav_id type的默认情况
            if int(type) > 0 and int(id) > 0:
                user_fav.fav_id = int(id)
                user_fav.fav_type = int(type)
                user_fav.user = request.user
                user_fav.save()
                if int(type) == 1:
                    course = Course.objects.get(id=int(id))
                    course.fav_nums += 1
                    course.save()
                elif int(type) == 2:
                    org = CourseOrg.objects.get(id=int(id))
                    org.fav_nums += 1
                    org.save()
                elif int(type) == 3:
                    teacher = Teacher.objects.get(id=int(id))
                    teacher.fav_nums += 1
                    teacher.save()
                    
                return HttpResponse('{"status":"success", "msg":"已收藏"}', content_type='application/json')

修改消息已读

class MyMessageView(LoginRequiredMixin, View):
    '''我的消息'''

    def get(self, request):
        all_message = UserMessage.objects.filter(user= request.user.id)
        # 用户进入个人中心消息页面,清空未读消息记录
        all_unread_messages = all_message.filter(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_message, 4, request=request)
        messages = p.page(page)

        return  render(request, "usercenter-message.html", {
            "messages":messages,
        })

个人中心左侧active状态

    <div class="left">
        <ul>
            <li {% ifequal  '/users/info/' request.path %}
            class="active2"
            {% endifequal %}><a href="{% url 'users:user_info' %}">个人资料</a></li>
            <li {% ifequal  '/users/mycourse/' request.path %}
            class="active2"
            {% endifequal %}><a href="{% url 'users:mycourse' %}">我的课程</a></li>
            <li {% ifequal  '/users/myfav/' request.path|slice:'13' %}
            class="active2"
            {% endifequal %}><a href="{% url 'users:myfav_org' %}">我的收藏</a></li>
            <li {% ifequal  '/users/my_message/' request.path %}
            class="active2"
            {% endifequal %}>
                <a href="{% url 'users:my_message' %}" style="position: relative;">
                    我的消息
                </a>
            </li>
        </ul>
    </div>
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
AndroidStudio封装SDK的那些事
<divclass"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,2.55,5z"id"raphael
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
9个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这