首页 > 其他 > 详细

在线教育平台 (二)

时间:2020-05-31 10:19:37      阅读:58      评论:0      收藏:0      [点我收藏+]

一.用户登录注册

 

1.1 登录

 

①.settings中设置引用静态资源

STATICFILES_DIRS = (
    os.path.join(BASE_DIR,static),
)

 

②.urls更新

path(login/,LoginView.as_view(),name = login),

 

③.view.py中写登录的版块

技术分享图片
from django.shortcuts import render
from django.contrib.auth import authenticate,login

from django.contrib.auth.backends import ModelBackend
from .models import UserProfile
from django.db.models import Q
from django.views.generic.base import View
from .forms import LoginForm

#邮箱和用户名都可以登录
# 基础ModelBackend类,因为它有authenticate方法
class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            # 不希望用户存在两个,get只能有一个。两个是get失败的一种原因 Q为使用并集查询
            user = UserProfile.objects.get(Q(username=username)|Q(email=username))

            # django的后台中密码加密:所以不能password==password
            # UserProfile继承的AbstractUser中有def check_password(self, raw_password):
            if user.check_password(password):
                return user
        except Exception as e:
            return None


class LoginView(View):
    def get(self,request):
        return render(request, login.html)

    def post(self,request):
        # 实例化
        login_form = LoginForm(request.POST)
        if login_form.is_valid():
            # 获取用户提交的用户名和密码
            user_name = request.POST.get(username, None)
            pass_word = request.POST.get(password, None)
            # 成功返回user对象,失败None
            user = authenticate(username=user_name, password=pass_word)
            # 如果不是null说明验证成功
            if user is not None:
                # 登录
                login(request, user)
                return render(request, index.html)
            # 只有当用户名或密码不存在时,才返回错误信息到前端
            else:
                return render(request, login.html, {msg: 用户名或密码错误,login_form:login_form})

        # form.is_valid()已经判断不合法了,所以这里不需要再返回错误信息到前端了
        else:
            return render(request,login.html,{login_form:login_form})
users下view.py

 

④.新建form.py文件写入,并在settings添加

AUTHENTICATION_BACKENDS = (
    users.views.CustomBackend,
)
from django import forms

# 登录表单验证
class LoginForm(forms.Form):
    # 用户名密码不能为空
    username = forms.CharField(required=True)
    password = forms.CharField(required=True,min_length=5)

 

1.2 注册

 

①.urls中更新注册需要的url

# 注册
path(register/, RegisterView.as_view(), name=register),
# 验证码
path(captcha/,include(captcha.urls)),
# 邮件激活url
re_path(active/(?P<active_code>.*)/,ActiveUserView.as_view(),name=user_active),

 

 

②.settings下INSTALLED_APPS中添加验证码

captcha,

 

 

③.重新生成一下数据库

python manage.py makemigrations

python manage.py migrate

 

④.更新form.py文件

技术分享图片
from django import forms
from captcha.fields import CaptchaField


class LoginForm(forms.Form):
    ‘‘‘登录验证表单‘‘‘

    username = forms.CharField(required=True)
    password = forms.CharField(required=True,min_length=5)


class RegisterForm(forms.Form):
    ‘‘‘注册验证表单‘‘‘

    email = forms.EmailField(required=True)
    password = forms.CharField(required=True,min_length=5)
    # 验证码
    captcha = CaptchaField(error_messages={invalid:验证码错误})
注册所需的版块

 

⑤.更新view.py

技术分享图片
from django.shortcuts import render
from django.contrib.auth import authenticate,login

from django.contrib.auth.backends import ModelBackend
from .models import UserProfile,EmailVerifyRecord
from django.db.models import Q
from django.views.generic.base import View
from .forms import LoginForm,RegisterForm
from django.contrib.auth.hashers import make_password
from utils.email_send import send_register_eamil

#邮箱和用户名都可以登录
# 基础ModelBackend类,因为它有authenticate方法
class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            # 不希望用户存在两个,get只能有一个。两个是get失败的一种原因 Q为使用并集查询
            user = UserProfile.objects.get(Q(username=username)|Q(email=username))

            # django的后台中密码加密:所以不能password==password
            # UserProfile继承的AbstractUser中有def check_password(self, raw_password):
            if user.check_password(password):
                return user
        except Exception as e:
            return None


class LoginView(View):
    ‘‘‘用户登录‘‘‘

    def get(self,request):
        return render(request, login.html)

    def post(self,request):
        # 实例化
        login_form = LoginForm(request.POST)
        if login_form.is_valid():
            # 获取用户提交的用户名和密码
            user_name = request.POST.get(username, None)
            pass_word = request.POST.get(password, None)
            # 成功返回user对象,失败None
            user = authenticate(username=user_name, password=pass_word)
            # 如果不是null说明验证成功
            if user is not None:
                if user.is_active:
                    # 只有注册激活才能登录
                    login(request, user)
                    return render(request, index.html)
                else:
                    return render(request, login.html, {msg: 用户名或密码错误, login_form: login_form})
            # 只有当用户名或密码不存在时,才返回错误信息到前端
            else:
                return render(request, login.html, {msg: 用户名或密码错误,login_form:login_form})

        # form.is_valid()已经判断不合法了,所以这里不需要再返回错误信息到前端了
        else:
            return render(request,login.html,{login_form:login_form})


# 激活用户的view
class ActiveUserView(View):
    def get(self, request, active_code):
        # 查询邮箱验证记录是否存在
        all_record = EmailVerifyRecord.objects.filter(code = active_code)

        if all_record:
            for record in all_record:
                # 获取到对应的邮箱
                email = record.email
                # 查找到邮箱对应的user
                user = UserProfile.objects.get(email=email)
                user.is_active = True
                user.save()
                # 激活成功跳转到登录页面
                return render(request, "login.html", )
        # 自己瞎输的验证码
        else:
            return render(request, "register.html", {"msg": "您的激活链接无效"})


class RegisterView(View):
    ‘‘‘用户注册‘‘‘
    def get(self,request):
        register_form = RegisterForm()
        return render(request,register.html,{register_form:register_form})

    def post(self,request):
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():

            user_name = request.POST.get(email, None)
            pass_word = request.POST.get(password, None)

            # 实例化一个user_profile对象
            user_profile = UserProfile()
            user_profile.username = user_name
            user_profile.email = user_name
            user_profile.is_active = False
            # 对保存到数据库的密码加密
            user_profile.password = make_password(pass_word)
            user_profile.save()
            send_register_eamil(user_name,register)
            return render(request,login.html)
        else:
            return render(request,register.html,{register_form:register_form})
注册及邮箱注册登录

 

⑥.settings中添加

EMAIL_HOST = "smtp.qq.com"  # SMTP服务器主机
EMAIL_PORT = 25             # 端口
EMAIL_HOST_USER = "xxx"       # 邮箱地址
EMAIL_HOST_PASSWORD = "xxx"    # 授权码
EMAIL_USE_TLS= False
EMAIL_FROM = "xxx"            # 邮箱地址

 

⑦.apps下新建utils文件夹,并创建email_send.py文件

技术分享图片
from random import Random
from django.core.mail import send_mail

from users.models import EmailVerifyRecord
from RcOnline.settings import EMAIL_FROM

# 生成随机字符串
def random_str(random_length=8):
    str = ‘‘
    # 生成字符串的可选字符串
    chars = AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789
    length = len(chars) - 1
    random = Random()
    for i in range(random_length):
        str += chars[random.randint(0, length)]
    return str

# 发送注册邮件
def send_register_eamil(email, send_type="register"):
    # 发送之前先保存到数据库,到时候查询链接是否存在
    # 实例化一个EmailVerifyRecord对象
    email_record = EmailVerifyRecord()
    # 生成随机的code放入链接
    code = random_str(16)
    email_record.code = code
    email_record.email = email
    email_record.send_type = send_type

    email_record.save()

    # 定义邮件内容:
    email_title = ""
    email_body = ""

    if send_type == "register":
        email_title = "Rc注册激活链接"
        email_body = "请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/{0}".format(code)

        # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,发件人邮箱地址,收件人(是一个字符串列表)
        send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
        # 如果发送成功
        if send_status:
            pass
邮箱激活使用

 

1.3 找回密码

 

①.更新urls.py                         # 找回,重置,修改密码的url

技术分享图片
import xadmin

from django.urls import path, include, re_path

from django.views.generic import TemplateView
from users import views
from users.views import LoginView, RegisterView, ActiveUserView, ForgetPwdView, ResetView, ModifyPwdView

urlpatterns = [
    path(xadmin/, xadmin.site.urls),
    # 首页
    path(‘‘, TemplateView.as_view(template_name=index.html),name=index),
    # 登录
    path(login/,LoginView.as_view(),name = login),
    # 注册
    path(register/, RegisterView.as_view(), name=register),
    # 验证码
    path(captcha/,include(captcha.urls)),
    # 邮件激活url
    re_path(active/(?P<active_code>.*)/,ActiveUserView.as_view(),name=user_active),
    # 找回密码
    path(forget/,ForgetPwdView.as_view(),name=forget_pwd),
    # 重置密码
    re_path(reset/(?P<active_code>.*)/, ResetView.as_view(), name=reset_pwd),
    # 修改密码url
    path(modify_pwd/, ModifyPwdView.as_view(), name=modify_pwd),
]
urls.py

 

②.forms.py中增加找回,重置密码的表单

class ForgetPwdForm(forms.Form):
    ‘‘‘忘记密码‘‘‘
    email = forms.EmailField(required=True)
    captcha = CaptchaField(error_messages={invalid: 验证码错误})

class ModifyPwdForm(forms.Form):
    ‘‘‘重置密码‘‘‘
    password1 = forms.CharField(required=True, min_length=5)
    password2 = forms.CharField(required=True, min_length=5)

 

③.email_send.py里面新增找回并重置修改等一系列操作的url

技术分享图片
from random import Random
from django.core.mail import send_mail

from users.models import EmailVerifyRecord
from RcOnline.settings import EMAIL_FROM

# 生成随机字符串
def random_str(random_length=8):
    str = ‘‘
    # 生成字符串的可选字符串
    chars = AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789
    length = len(chars) - 1
    random = Random()
    for i in range(random_length):
        str += chars[random.randint(0, length)]
    return str

# 发送注册邮件
def send_register_eamil(email, send_type="register"):
    # 发送之前先保存到数据库,到时候查询链接是否存在
    # 实例化一个EmailVerifyRecord对象
    email_record = EmailVerifyRecord()
    # 生成随机的code放入链接
    code = random_str(16)
    email_record.code = code
    email_record.email = email
    email_record.send_type = send_type

    email_record.save()

    # 定义邮件内容:
    email_title = ""
    email_body = ""

    if send_type == "register":
        email_title = "Rc注册激活链接"
        email_body = "请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/{0}".format(code)

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

    if send_type == "forget":
        email_title = "Rc找回密码链接"
        email_body = "请点击下面的链接找回你的密码: http://127.0.0.1:8000/reset/{0}".format(code)

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

 

④.view中写找回,重置,修改密码的逻辑

技术分享图片
class ForgetPwdView(View):
    ‘‘‘找回密码‘‘‘
    def get(self,request):
        forget_form = ForgetPwdForm()
        return render(request,forgetpwd.html,{forget_form:forget_form})

    def post(self,request):
        forget_form = ForgetPwdForm(request.POST)
        if forget_form.is_valid():
            email = request.POST.get(email,None)
            send_register_eamil(email,forget)
            return render(request, send_success.html)
        else:
            return render(request,forgetpwd.html,{forget_form:forget_form})

class ResetView(View):
    def get(self, request, active_code):
        all_records = EmailVerifyRecord.objects.filter(code=active_code)
        if all_records:
            for record in all_records:
                email = record.email
                return render(request, "password_reset.html", {"email":email})
        else:
            return render(request, "active_fail.html")
        return render(request, "login.html")

class ModifyPwdView(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", "")
            email = request.POST.get("email", "")
            if pwd1 != pwd2:
                return render(request, "password_reset.html", {"email":email, "msg":"密码不一致!"})
            user = UserProfile.objects.get(email=email)
            user.password = make_password(pwd2)
            user.save()

            return render(request, "login.html")
        else:
            email = request.POST.get("email", "")
            return render(request, "password_reset.html", {"email":email, "modify_form":modify_form })
后台逻辑

 

二.授课机构相关功能

 

2.1 机构

 

①.urls添加机构首页路由

# 机构首页路由
path("org/", include(organization.urls, namespace="org")),
# 处理图片显示的url,使用Django自带serve,传入参数告诉它去哪个路径找,我们有配置好的路径MEDIAROOT
re_path(r^media/(?P<path>.*), serve, {"document_root": MEDIA_ROOT }),

 

②.view.py增加逻辑

技术分享图片
class OrgView(View):
    ‘‘‘课程机构‘‘‘

    def get(self, request):
        # 所有课程机构
        all_orgs = CourseOrg.objects.all()

        # 所有城市
        all_citys = CityDict.objects.all()
        # 城市筛选
        city_id = request.GET.get(city,‘‘)
        if city_id:
            all_orgs = all_orgs.filter(city_id=int(city_id))

        # 类别筛选
        category = request.GET.get(ct,‘‘)
        if category:
            all_orgs = all_orgs.filter(category=category)

        # 热门课程机构排名
        hot_orgs = all_orgs.order_by(-click_nums)[:3]
        # 学习人数和课程数筛选
        sort = request.GET.get(sort, "")
        if sort:
            if sort == "students":
                all_orgs = all_orgs.order_by("-students")
            elif sort == "courses":
                all_orgs = all_orgs.order_by("-course_nums")
        # 有多少家机构
        org_nums = all_orgs.count()
        # 对课程机构进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get(page, 1)
        except PageNotAnInteger:
            page = 1
        # 这里指从allorg中取五个出来,每页显示5个
        p = Paginator(all_orgs, 2, request=request)
        orgs = p.page(page)

        return render(request, "org-list.html", {
            "all_orgs": orgs,
            "all_citys": all_citys,
            "org_nums": org_nums,
            city_id:city_id,
            "category": category,
            hot_orgs:hot_orgs,
            sort:sort,
        })
organization下view.py

 

③.增加分页

技术分享图片
INSTALLED_APPS = [
    django.contrib.admin,
    django.contrib.auth,
    django.contrib.contenttypes,
    django.contrib.sessions,
    django.contrib.messages,
    django.contrib.staticfiles,

    course,
    operation,
    organization,
    users,

    xadmin,
    crispy_forms,

    captcha,
    pure_pagination,
]
更新settings下INSTALLED_APPS

 

④.models下CourseOrg更新

技术分享图片
class CourseOrg(models.Model):
    ORG_CHOICES = (
        ("pxjg", u"培训机构"),
        ("gx", u"高校"),
        ("gr", u"个人"),
    )
    name = models.CharField(机构名称,max_length=50)
    desc = models.TextField(机构描述)
    category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name=u"机构类别", default="pxjg")
    click_nums = models.IntegerField(点击数,default=0)
    fav_nums = models.IntegerField(收藏数,default=0)
    students = models.IntegerField("学习人数",default=0)
    course_nums = models.IntegerField("课程数",default=0)
    image = models.ImageField(logo,upload_to=org/%Y/%m,max_length=100)
    address = models.CharField(机构地址,max_length=150,)
    city = models.ForeignKey(CityDict,verbose_name=所在城市,on_delete=models.CASCADE)
    add_time = models.DateTimeField(default=datetime.now)

    class Meta:
        verbose_name = 课程机构
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name
organization下models.py

 

⑤.settings下TEMPLATES增加图片处理器

#添加图片处理器,为了在课程列表中前面加上MEDIA_URL
django.template.context_processors.media,

 

2.2 学习咨询

 

①.新建form.py文件

技术分享图片
import re
from django import forms
from operation.models import UserAsk


class UserAskForm(forms.ModelForm):

    class Meta:
        model = UserAsk
        fields = [name, mobile, course_name]

    def clean_mobile(self):
        """
        验证手机号码是否合法
        """
        mobile = self.cleaned_data[mobile]
        REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|176\d{8}$"
        p = re.compile(REGEX_MOBILE)
        if p.match(mobile):
            return mobile
        else:
            raise forms.ValidationError(u"手机号码非法", code="mobile_invalid")
organization下

 

②.更改之前org_list的路由

path("org/", include(organization.urls, namespace="org")),

  并在organization下新建urls.py

技术分享图片
from organization.views import OrgView, AddUserAskView, OrgHomeView, OrgCourseView, OrgDescView, OrgTeacherView, AddFavView

from django.urls import path,re_path

# 要写上app的名字
app_name = "organization"

urlpatterns = [
    path(list/,OrgView.as_view(),name=org_list),
    path(add_ask/, AddUserAskView.as_view(), name="add_ask"),
    # home页面的url
    re_path(home/(?P<org_id>\d+)/, OrgHomeView.as_view(), name="org_home"),
    # 机构课程url
    re_path(course/(?P<org_id>\d+)/, OrgCourseView.as_view(), name="org_course"),
    # 机构介绍
    re_path(desc/(?P<org_id>\d+)/, OrgDescView.as_view(), name="org_desc"),
    # 机构讲师
    re_path(teacher/(?P<org_id>\d+)/, OrgTeacherView.as_view(), name="org_teacher"),
    # 收藏
    path(add_fav/, AddFavView.as_view(), name="add_fav"),
]
urls.py

 

 ③.后台逻辑更新

技术分享图片
from django.shortcuts import render

from django.views.generic import View
from .models import CourseOrg,CityDict
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger

from django.http import HttpResponse
from .forms import UserAskForm
from operation.models import UserFavorite
from django.contrib.auth import authenticate

class OrgView(View):
    ‘‘‘课程机构‘‘‘

    def get(self, request):
        # 所有课程机构
        all_orgs = CourseOrg.objects.all()

        # 所有城市
        all_citys = CityDict.objects.all()
        # 城市筛选
        city_id = request.GET.get(city,‘‘)
        if city_id:
            all_orgs = all_orgs.filter(city_id=int(city_id))

        # 类别筛选
        category = request.GET.get(ct,‘‘)
        if category:
            all_orgs = all_orgs.filter(category=category)

        # 热门课程机构排名
        hot_orgs = all_orgs.order_by(-click_nums)[:3]
        # 学习人数和课程数筛选
        sort = request.GET.get(sort, "")
        if sort:
            if sort == "students":
                all_orgs = all_orgs.order_by("-students")
            elif sort == "courses":
                all_orgs = all_orgs.order_by("-course_nums")
        # 有多少家机构
        org_nums = all_orgs.count()
        # 对课程机构进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get(page, 1)
        except PageNotAnInteger:
            page = 1
        # 这里指从allorg中取五个出来,每页显示5个
        p = Paginator(all_orgs, 2, request=request)
        orgs = p.page(page)

        return render(request, "org-list.html", {
            "all_orgs": orgs,
            "all_citys": all_citys,
            "org_nums": org_nums,
            city_id:city_id,
            "category": category,
            hot_orgs:hot_orgs,
            sort:sort,
        })


class AddUserAskView(View):
    """
    用户添加咨询
    """
    def post(self, request):
        userask_form = UserAskForm(request.POST)
        if userask_form.is_valid():
            user_ask = userask_form.save(commit=True)
            # 如果保存成功,返回json字符串,后面content type是告诉浏览器返回的数据类型
            return HttpResponse({"status":"success"}, content_type=application/json)
        else:
            # 如果保存失败,返回json字符串,并将form的报错信息通过msg传递到前端
            return HttpResponse({"status":"fail", "msg":"添加出错"}, content_type=application/json)


class OrgHomeView(View):
    ‘‘‘机构首页‘‘‘

    def get(self,request,org_id):
        current_page = home
        # 根据id找到课程机构
        course_org = CourseOrg.objects.get(id=int(org_id))
        # 判断收藏状态
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True
        # 反向查询到课程机构的所有课程和老师
        all_courses = course_org.course_set.all()[:4]
        all_teacher = course_org.teacher_set.all()[:2]
        return render(request,org-detail-homepage.html,{
            course_org:course_org,
            all_courses:all_courses,
            all_teacher:all_teacher,
            current_page:current_page,
            has_fav:has_fav,
        })

class OrgCourseView(View):
    """
   机构课程列表页
    """
    def get(self, request, org_id):
        current_page = course
        # 根据id取到课程机构
        course_org = CourseOrg.objects.get(id= int(org_id))
        # 通过课程机构找到课程。内建的变量,找到指向这个字段的外键引用
        all_courses = course_org.course_set.all()
        # 判断收藏状态
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True

        return render(request, org-detail-course.html,{
           all_courses:all_courses,
            course_org: course_org,
            current_page:current_page,
            has_fav: has_fav,
        })


class OrgDescView(View):
    ‘‘‘机构介绍页‘‘‘
    def get(self, request, org_id):
        current_page = desc
        # 根据id取到课程机构
        course_org = CourseOrg.objects.get(id= int(org_id))
        # 判断收藏状态
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True
        return render(request, org-detail-desc.html,{
            course_org: course_org,
            current_page:current_page,
            has_fav: has_fav,
        })

class OrgTeacherView(View):
    """
   机构教师页
    """
    def get(self, request, org_id):
        current_page = teacher
        course_org = CourseOrg.objects.get(id= int(org_id))
        all_teacher = course_org.teacher_set.all()
        # 判断收藏状态
        has_fav = False
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course_org.id, fav_type=2):
                has_fav = True

        return render(request, org-detail-teachers.html,{
           all_teacher:all_teacher,
            course_org: course_org,
            current_page:current_page,
            has_fav: has_fav,
        })

class AddFavView(View):
    """
    用户收藏和取消收藏
    """
    def post(self, request):
        fav_id = request.POST.get(fav_id, 0)         # 防止后边int(fav_id)时出错
        fav_type = request.POST.get(fav_type, 0)     # 防止int(fav_type)出错

        if not request.user.is_authenticated:
            # 未登录时返回json提示未登录,跳转到登录页面是在ajax中做的
            return HttpResponse({"status":"fail", "msg":"用户未登录"}, content_type=application/json)

        exist_record = UserFavorite.objects.filter(user=request.user, fav_id=int(fav_id), fav_type=int(fav_type))
        if exist_record:
            # 如果记录已经存在,表示用户取消收藏
            exist_record.delete()
            return HttpResponse({"status":"fail", "msg":"已取消收藏"}, content_type=application/json)
        else:
            user_fav = UserFavorite()
            if int(fav_id) > 0 and int(fav_type) > 0:
                user_fav.user = request.user
                user_fav.fav_id = int(fav_id)
                user_fav.fav_type = int(fav_type)
                user_fav.save()
                return HttpResponse({"status":"success", "msg":"已收藏"}, content_type=application/json)
            else:
                return HttpResponse({"status":"fail", "msg":"收藏出错"}, content_type=application/json)
organization下view.py

 

④.更新course下的models

技术分享图片
class Course(models.Model):
    DEGREE_CHOICES = (
        ("cj", "初级"),
        ("zj", "中级"),
        ("gj", "高级")
    )
    name = models.CharField("课程名",max_length=50)
    desc = models.CharField("课程描述",max_length=300)
    detail = models.TextField("课程详情")
    degree = models.CharField(难度,choices=DEGREE_CHOICES, max_length=2)
    learn_times = models.IntegerField("学习时长(分钟数)",default=0)
    students = models.IntegerField("学习人数",default=0)
    fav_nums = models.IntegerField("收藏人数",default=0)
    image = models.ImageField("封面图",upload_to="courses/%Y/%m",max_length=100)
    click_nums = models.IntegerField("点击数",default=0)
    add_time = models.DateTimeField("添加时间",default=datetime.now,)
    course_org = models.ForeignKey(CourseOrg, on_delete=models.CASCADE, verbose_name="所属机构", null=True, blank=True)

    class Meta:
        verbose_name = "课程"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name
Course类

 

⑤.更新organization下models                     # Teacher新增头像

image = models.ImageField(
        default=‘‘,
        upload_to="teacher/%Y/%m",
        verbose_name="头像",
        max_length=100
)

 

三.课程相关操作

 

3.1 课程列表及详情

 

①.urls.py更新

# 课程url
path("course/", include(course.urls, namespace="course")),

 

②.course下新建urls.py

from django.urls import path,re_path
from .views import CourseListView, CourseDetailView

# 要写上app的名字
app_name = "course"

urlpatterns = [
    path(list/,CourseListView.as_view(),name=course_list),
    # 课程详情
    re_path(course/(?P<course_id>\d+)/, CourseDetailView.as_view(), name="course_detail"),
]

 

③.view.py增加后台逻辑

技术分享图片
from django.shortcuts import render
from django.views.generic import View

from operation.models import UserFavorite
from .models import Course
from pure_pagination import Paginator, EmptyPage, PageNotAnInteger

class CourseListView(View):
    def get(self, request):
        all_courses = Course.objects.all().order_by(-add_time)
        # 热门课程推荐
        hot_courses = Course.objects.all().order_by(-click_nums)[:3]
        # 排序
        sort = request.GET.get(sort, "")
        if sort:
            if sort == "students":
                all_courses = all_courses.order_by("-students")
            elif sort == "hot":
                all_courses = all_courses.order_by("-click_nums")
        # 分页
        try:
            page = request.GET.get(page, 1)
        except PageNotAnInteger:
            page = 1
        p = Paginator(all_courses,2 , request=request)
        courses = p.page(page)
        return render(request, "course-list.html", {
            "all_courses":courses,
            sort: sort,
            hot_courses:hot_courses,

        })

class CourseDetailView(View):
    ‘‘‘课程详情‘‘‘
    def get(self, request, course_id):
        course = Course.objects.get(id=int(course_id))
        # 课程的点击数加1
        course.click_nums += 1
        course.save()
        # 课程标签
        # 通过当前标签,查找数据库中的课程
        has_fav_course = False
        has_fav_org = False

        # 必须是用户已登录我们才需要判断。
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course.id, fav_type=1):
                has_fav_course = True
            if UserFavorite.objects.filter(user=request.user, fav_id=course.course_org.id, fav_type=2):
                has_fav_org = True
        tag = course.tag
        if tag:
            # 需要从1开始不然会推荐自己
            relate_courses = Course.objects.filter(tag=tag)[:2]
        else:
            relate_courses = []
        return  render(request, "course-detail.html", {
            course:course,
            relate_courses:relate_courses,
            "has_fav_course": has_fav_course,
            "has_fav_org": has_fav_org,
        })
course下view.py

 

④.更新models

技术分享图片
class Course(models.Model):
    DEGREE_CHOICES = (
        ("cj", "初级"),
        ("zj", "中级"),
        ("gj", "高级")
    )
    name = models.CharField("课程名",max_length=50)
    desc = models.CharField("课程描述",max_length=300)
    detail = models.TextField("课程详情")
    degree = models.CharField(难度,choices=DEGREE_CHOICES, max_length=2)
    learn_times = models.IntegerField("学习时长(分钟数)",default=0)
    students = models.IntegerField("学习人数",default=0)
    fav_nums = models.IntegerField("收藏人数",default=0)
    image = models.ImageField("封面图",upload_to="courses/%Y/%m",max_length=100)
    click_nums = models.IntegerField("点击数",default=0)
    tag = models.CharField(课程标签,default=‘‘,max_length=10)
    add_time = models.DateTimeField("添加时间",default=datetime.now,)
    course_org = models.ForeignKey(CourseOrg, on_delete=models.CASCADE, verbose_name="所属机构", null=True, blank=True)
    category = models.CharField("课程类别",max_length=20, default="")

    class Meta:
        verbose_name = "课程"
        verbose_name_plural = verbose_name

    def get_zj_nums(self):
        #获取课程的章节数
        return self.lesson_set.all().count()

    def get_learn_users(self):
        #获取这门课程的学习用户
        return self.usercourse_set.all()[:5]

    def __str__(self):
        return self.name
course下models.py
技术分享图片
class CourseOrg(models.Model):
    ORG_CHOICES = (
        ("pxjg", u"培训机构"),
        ("gx", u"高校"),
        ("gr", u"个人"),
    )
    name = models.CharField(机构名称,max_length=50)
    desc = models.TextField(机构描述)
    category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name=u"机构类别", default="pxjg")
    click_nums = models.IntegerField(点击数,default=0)
    fav_nums = models.IntegerField(收藏数,default=0)
    students = models.IntegerField("学习人数",default=0)
    course_nums = models.IntegerField("课程数",default=0)
    image = models.ImageField(logo,upload_to=org/%Y/%m,max_length=100)
    address = models.CharField(机构地址,max_length=150,)
    city = models.ForeignKey(CityDict,verbose_name=所在城市,on_delete=models.CASCADE)
    add_time = models.DateTimeField(default=datetime.now)

    class Meta:
        verbose_name = 课程机构
        verbose_name_plural = verbose_name

    def get_teacher_nums(self):
        #获取机构的教师数
        return self.teacher_set.all().count()

    def __str__(self):
        return self.name
organization下models.py

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

在线教育平台 (二)

原文:https://www.cnblogs.com/JangNara/p/12996322.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!