Django+xadmin 打造线上教育平台


一、开发环境搭建

1、开发环境:

  • python:3.6
  • Django:2.0.2

后台管理:

  xadmin

2、虚拟环境及项目相关安装:

  •  virtualenv安装及虚拟环境搭建
  • pycharm、Navicat、python的安装

环境搭建不再累述,详情参参考:https://www.cnblogs.com/Eric15/articles/9517232.html 

 

3、项目简介

 系统功能概况:

  • 系统具有完整的用户登录注册以及找回密码功能,拥有完整个人中心。
  • 个人中心: 修改头像,修改密码,修改邮箱,可以看到我的课程以及我的收藏。可以删除收藏,我的消息。
  • 导航栏: 公开课,授课讲师,授课机构,全局搜索。
  • 点击公开课–> 课程列表,排序-搜索。热门课程推荐,课程的分页。
  • 点击课程–> 课程详情页中对课程进行收藏,取消收藏。富文本展示课程内容。
  • 点击开始学习–> 课程的章节信息,课程的评论信息。课程资源的下载链接。
  • 点击授课讲师–>授课讲师列表页,对讲师进行人气排序以及分页,右边有讲师排行榜。
  • 点击讲师的详情页面–> 对讲师进行收藏和分享,以及讲师的全部课程。
  • 导航栏: 授课机构有分页,排序筛选功能。
  • 机构列表页右侧有快速提交我要学习的表单。
  • 点击机构–> 左侧:机构首页,机构课程,机构介绍,机构讲师。
  • 后台管理系统可以切换主题。左侧每一个功能都有列表显示, 增删改查,筛选功能。
  • 课程列表页可以对不同字段进行排序。选择多条记录进行删除操作。
  • 课程列表页:过滤器->选择字段范围等,搜索,导出csv,xml,json。
  • 课程新增页面上传图片,富文本的编辑。时间选择,添加章节,添加课程资源。
  • 日志记录:记录后台人员的操作

 

 


二、新建项目:MxOnline

示例:

1)首先打开终端,创建虚拟环境:

 mkvirtualenv mxonline

 

2)djangoTest虚拟环境中安装django版本:

 pip install django==2.0.2

3)打开pycharm,新建python-django项目

 


  三、数据库更换

 pycharm新建项目,默认用的是自带ORM数据库(sqlite),将其改成使用mysql数据库

1)setting.py中更改数据库配置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'MxOnline',        #数据库名字
        'USER': 'root',          #账号
        'PASSWORD': '******',    #密码
        'HOST': '127.0.0.1',     #IP
        'PORT': '3306',          #端口
    }
}

2)Navicat新建数据库:

  

3)虚拟环境下安装MySQLclient:

一般直接安装:pip install mysqlclient ,

但有可能报错:Failed building wheel for mysqlclient

 此时,需要用另一种方式安装:

  1. 访问:https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted ,找到mysqlclient相关
  2. 下载:mysqlclient‑1.3.13‑cp36‑cp36m‑win_amd64.whl ,我的是win 64位  python3.6的,故下载这个
  3. 进入上述文件所在的地方,在终端虚拟环境中安装:pip install mysqlclient‑1.3.13‑cp36‑cp36m‑win_amd64.whl  ,即可 

  四、model设计

 1、生成四个app:users 、 course 、 organization 、 operation

python manage.py startapp users  # 用户信息

python manage.py startapp course  # 课程信息

python manage.py startapp organization  # 讲师及授课机构相关

python manage.py startapp operation  # 用户管理操作

 在项目MxOnline中新建apps包,用于放app,将上述四个app放进apps内

2、再创建一个extra_apps包 ,表示存放的是第三方的源码包

3、在setting中配置:

import sys

sys.path.insert(0,os.path.join(BASE_DIR,'apps'))
sys.path.insert(0,os.path.join(BASE_DIR, 'extra_apps'))

4、将4个app注册到 INSTALLED_APPS中:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users',
    'course',
    'organization',
    'operation',
]

 

另外需要创建静态文件夹:

  • static:用于存放静态文件,css、js等等
  • media:用户上传文件及图片路径

 setting中配置静态文件路径:

# 静态文件路径
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static'),
    ]

# 设置上传文件的路径
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')

此时,项目中文件情况:

 

现在开始,设计四个app的表结构:

1、users中的models.py表:

from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.
class UserProfile(AbstractUser):

    gender_choices = (
        ('male',''),
        ('female','')
    )

    nick_name = models.CharField('昵称',max_length=32 ,default='')
    birthday = models.DateField('生日',null=True,blank=True)
    gender = models.CharField('性别',max_length=5,choices=gender_choices,default='female')
    adress = models.CharField('地址',max_length=100,default='')
    mobile = models.CharField('手机号',max_length=11,null=True,blank=True)
    image = models.ImageField(upload_to='image/%Y%m',default='image/default.png',max_length=100)
   email = models.EmailField('邮箱',blank=True,unique=True) # 重写email,加上'唯一'标识 ,原因在于django中AbstractUser的email字段没设置唯一,容易造成多个用户邮箱相同
class Meta: verbose_name = '用户信息' verbose_name_plural = verbose_name def __str__(self): return self.username

表中用到ImageField,该字段需要用到pillow库,我们需要安装它:

报错:

  

pip install pillow  # 安装pillow

 UserProfile继承于django自带的 AbstractUser,需要重新配置 AUTH_USER_MODEL的重载:

AUTH_USER_MODEL = 'users.UserProfile'

 在users/models.py中继续添加 EmailVerifyRecord(邮箱验证)类、Banner(轮播图)类:

class EmailVerifyRecord(models.Model):
    """邮箱验证"""
    send_choices = (
        ('register','注册'),
        ('forget','找回密码'),
        ('update_email','修改邮箱')
    )

    code = models.CharField('验证码',max_length=10)
    email = models.EmailField('邮箱',max_length=50)
    send_type = models.CharField(choices=send_choices,max_length=30)
    send_time = models.DateTimeField(default=datetime.now)

    class Meta:
        verbose_name = '邮箱验证码'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.code

class Banner(models.Model):
    """轮播图"""

    title = models.CharField('标题',max_length=100)
    image = models.ImageField('轮播图',upload_to='banner/%Y%m',max_length=100)
    url = models.URLField('访问地址',max_length=200)
    index = models.IntegerField('顺序',default=100)
    add_time = models.DateTimeField('添加时间',default=datetime.now)

    class Meta:
        verbose_name = '轮播图'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.title
View Code

 

2、course/views.py表设计:

from django.db import models
from datetime import datetime

# Create your models here.

class Course(models.Model):
    '''课程'''
    DEGREE_CHOICES = (
        ("cj", "初级"),
        ("zj", "中级"),
        ("gj", "高级"),
    )
    name = models.CharField("课程名",max_length=50)
    desc = models.CharField("课程描述",max_length=300)
    detail = models.TextField("课程详情")
    # detail = UEditorField(verbose_name=u'课程详情', width=600, height=300, imagePath="courses/ueditor/",
    #                       filePath="courses/ueditor/", default='')


    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)
    is_banner = models.BooleanField('是否轮播',default=False)
    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="")
    # teacher = models.ForeignKey(Teacher,verbose_name='讲师',null=True,blank=True,on_delete=models.CASCADE)
    youneed_know = models.CharField('课程须知',max_length=300,default='')
    teacher_tell = models.CharField('老师告诉你',max_length=300,default='')

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

    def __str__(self):
        return self.name


class Lesson(models.Model):
    '''课程章节'''
    course = models.ForeignKey(Course,verbose_name='课程',on_delete=models.CASCADE)
    name = models.CharField("章节名",max_length=100)
    add_time = models.DateTimeField("添加时间",default=datetime.now)

    class Meta:
        verbose_name = "章节"
        verbose_name_plural = verbose_name
        unique_together = ('course','name')

    def __str__(self):
        return "%s第%s章"% (self.course,self.name)


class Video(models.Model):
    '''章节视频'''
    lesson = models.ForeignKey(Lesson, verbose_name="章节",on_delete=models.CASCADE)
    name = models.CharField("视频名",max_length=100)
    # url = models.CharField('访问地址',default='',max_length=200)
    # learn_times = models.IntegerField("学习时长(分钟数)", default=0)
    add_time = models.DateTimeField("添加时间", default=datetime.now)

    class Meta:
        verbose_name = "视频"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name
    
    
class CourseResource(models.Model):
    """课程资源"""
    course = models.ForeignKey(Course, verbose_name="课程",on_delete=models.CASCADE)
    name = models.CharField("名称",max_length=100)
    download = models.FileField("资源文件",upload_to="course/resource/%Y/%m",max_length=100)
    add_time = models.DateTimeField("添加时间", default=datetime.now)

    class Meta:
        verbose_name = "课程资源"
        verbose_name_plural = verbose_name
        
    def __str__(self):
        return self.name
View Code

 

3、organization/views.py表设计:

from datetime import datetime

from django.db import models


class CityDict(models.Model):
    """城市"""
    name = models.CharField('城市',max_length=20)
    desc = models.CharField('描述',max_length=200)
    add_time = models.DateTimeField(default=datetime.now)

    class Meta:
        verbose_name = '城市'
        verbose_name_plural= verbose_name

    def __str__(self):
        return self.name

class CourseOrg(models.Model):
    """培训机构"""
    ORG_CHOICES = (
        ("pxjg", "培训机构"),
        ("gx", "高校"),
        ("gr", "个人"),
    )
    name = models.CharField('机构名称',max_length=50)
    desc = models.TextField('机构描述')
    category = models.CharField(max_length=20, choices=ORG_CHOICES, verbose_name="机构类别", default="mx")
    click_nums = models.IntegerField('点击数',default=0)
    tag = models.CharField('机构标签',max_length=10,default='全国知名')
    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


class Teacher(models.Model):
    """课程讲师"""
    org = models.ForeignKey(CourseOrg,verbose_name='所属机构',on_delete=models.CASCADE)
    name = models.CharField('教师名',max_length=50)
    work_years = models.IntegerField('工作年限',default=0)
    work_company = models.CharField('就职公司',max_length=50)
    work_position = models.CharField('公司职位',max_length=50)
    points = models.CharField('教学特点',max_length=50)
    click_nums = models.IntegerField('点击数',default=0)
    fav_nums = models.IntegerField('收藏数',default=0)
    # teacher_age = models.IntegerField('年龄',default=25)
    image = models.ImageField(
        default='',
        upload_to="teacher/%Y/%m",
        verbose_name="头像",
        max_length=100)
    add_time = models.DateTimeField(default=datetime.now)

    class Meta:
        verbose_name = '教师'
        verbose_name_plural = verbose_name

    def __str__(self):
        return "[{0}]的教师: {1}".format(self.org, self.name)

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

 

4、operation/views.py表设计:

from datetime import datetime

from django.db import models

from course.models import Course
from users.models import UserProfile


class UserAsk(models.Model):
    '''用户咨询'''
    name = models.CharField('姓名',max_length=20)
    mobile = models.CharField('手机',max_length=11)
    course_name = models.CharField('课程名',max_length=50)
    add_time = models.DateTimeField('添加时间',default=datetime.now)

    class Meta:
        verbose_name = '用户咨询'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class CourseComments(models.Model):
    '''课程评论'''
    user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE)
    course = models.ForeignKey(Course,verbose_name='课程',on_delete=models.CASCADE)
    comments = models.CharField('评论',max_length=200)
    add_time = models.DateTimeField('添加时间', default=datetime.now)

    class Meta:
        verbose_name = '课程评论'
        verbose_name_plural = verbose_name


class UserFavorite(models.Model):
    '''用户收藏'''
    FAV_TYPE = (
        (1,'课程'),
        (2,'课程机构'),
        (3,'讲师')
    )

    user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE)
    fav_id = models.IntegerField('数据id',default=0)
    fav_type = models.IntegerField(verbose_name='收藏类型',choices=FAV_TYPE,default=1)
    add_time = models.DateTimeField('添加时间', default=datetime.now)

    class Meta:
        verbose_name = '用户收藏'
        verbose_name_plural = verbose_name


class UserMessage(models.Model):
    user = models.IntegerField('接收用户',default=0)
    message = models.CharField('消息内容',max_length=500)
    has_read = models.BooleanField('是否已读',default=False)
    add_time = models.DateTimeField('添加时间', default=datetime.now)

    class Meta:
        verbose_name = '用户消息'
        verbose_name_plural = verbose_name


class UserCourse(models.Model):
    '''用户课程'''
    user = models.ForeignKey(UserProfile,verbose_name='用户',on_delete=models.CASCADE)
    course = models.ForeignKey(Course,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.course.name

至此,4个app的表设计即完成了,目前没考虑到的,之后再补上


五、通过xadmin快速搭建后台管理系统

5.1、xadmin安装和配置

 1、xadmin安装:两种方式安装

1)虚拟环境下,直接:pip install xadmin  ,会连xadmin依赖的包也都安装好

2)源码安装(推荐):

 GitHub上有很多开源项资源,如果想获取某个资源,可以到GitHub上找:https://github.com/

 从GitHub上下载xadmin,然后复制放到项目中。本项目将xadmin放到extra_apps包中,

 从源码下载直接复制到项目中的方式,需要自己安装xadmin依赖包:https://github.com/sshwsfc/xadmin

  • django
  • django-crispy-forms
  • django-reversion
  • django-formtools
  • django-import-export
  • future
  • httplib2
  • six
  • xlwt         
  • xlsxwriter   # xlwt跟xlsxwriter,不是依赖包,主要用来做ex文件导出,使xadmin功能更加强大些
pip install django-crispy-forms django-reversion django-formtools future httplib2 six django-import-export  # 多个依赖包一起安装

pip install xlwt xlsxwriter

 

2、xadmin的配置:

 1)在在setting.py中的INSTALLED_APPS中注册:

INSTALLED_APPS = [
    …
    'xadmin',    #新增
    'crispy_forms',  #新增
]

  2)在url.py中进行路由配置:

# urls.py

from django.urls import path

import xadmin

urlpatterns = [
    path('xadmin/', xadmin.site.urls),
]

 

3、app注册后,更新表mk生成数据:

python manage.py makemigrations

python manage.py migrate

 

4、创建超级管理员,访问后台:http://127.0.0.1:8000/xadmin

python manage.py createsuperuser

此时,页面效果:xadmin成功引人使用!



 


 5.2、app中model的注册

 1)在users下面创建adminx.py,代码如下:

# users/adminx.py

import xadmin

from .models import EmailVerifyRecord

#xadmin中这里是继承object,不再是继承admin
class EmailVerifyRecordAdmin(object):
    pass

xadmin.site.register(EmailVerifyRecord,EmailVerifyRecordAdmin)

 

2)完善功能,增加显示字段、过滤、搜索等

# users/adminx.py

import xadmin

from .models import EmailVerifyRecord

#xadmin中这里是继承object,不再是继承admin
class EmailVerifyRecordAdmin(object):
    # 显示的列
    list_display = ['code', 'email', 'send_type', 'send_time']
    # 搜索的字段,不要添加时间搜索
    search_fields = ['code', 'email', 'send_type']
    # 过滤
    list_filter = ['code', 'email', 'send_type', 'send_time']

xadmin.site.register(EmailVerifyRecord,EmailVerifyRecordAdmin)

 

将剩余三个 app也进行上述操作,最终代码:

1)users/adminx.py:

import xadmin

from .models import EmailVerifyRecord,Banner


#xadmin中这里是继承object,不再是继承admin
class EmailVerifyRecordAdmin(object):
    # 显示的列
    list_display = ['code', 'email', 'send_type', 'send_time']
    # 搜索的字段
    search_fields = ['code', 'email', 'send_type']
    # 过滤
    list_filter = ['code', 'email', 'send_type', 'send_time']


class BannerAdmin(object):
    list_display = ['title', 'image', 'url','index', 'add_time']
    search_fields = ['title', 'image', 'url','index']
    list_filter = ['title', 'image', 'url','index', 'add_time']


xadmin.site.register(EmailVerifyRecord,EmailVerifyRecordAdmin)
xadmin.site.register(Banner,BannerAdmin)
users/adminx.py

 

2)course/adminx.py:

# course/adminx.py

import xadmin

from .models import Course, Lesson, Video, CourseResource


# Course的admin管理器
class CourseAdmin(object):
    '''课程'''

    list_display = [ 'name','desc','detail','degree','learn_times','students']
    search_fields = ['name', 'desc', 'detail', 'degree', 'students']
    list_filter = [ 'name','desc','detail','degree','learn_times','students']


class LessonAdmin(object):
    '''章节'''

    list_display = ['course', 'name', 'add_time']
    search_fields = ['course', 'name']
    #这里course__name是根据课程名称过滤
    list_filter = ['course__name', 'name', 'add_time']


class VideoAdmin(object):
    '''视频'''

    list_display = ['lesson', 'name', 'add_time']
    search_fields = ['lesson', 'name']
    list_filter = ['lesson', 'name', 'add_time']


class CourseResourceAdmin(object):
    '''课程资源'''

    list_display = ['course', 'name', 'download', 'add_time']
    search_fields = ['course', 'name', 'download']
    list_filter = ['course__name', 'name', 'download', 'add_time']


# 将管理器与model进行注册关联
xadmin.site.register(Course, CourseAdmin)
xadmin.site.register(Lesson, LessonAdmin)
xadmin.site.register(Video, VideoAdmin)
xadmin.site.register(CourseResource, CourseResourceAdmin)
course/adminx.py

 

 3)organization/adminx.py:

# organization/adminx.py

import xadmin

from .models import CityDict, CourseOrg, Teacher


class CityDictAdmin(object):
    '''城市'''

    list_display = ['name', 'desc', 'add_time']
    search_fields = ['name', 'desc']
    list_filter = ['name', 'desc', 'add_time']


class CourseOrgAdmin(object):
    '''机构'''

    list_display = ['name', 'desc', 'click_nums', 'fav_nums','add_time' ]
    search_fields = ['name', 'desc', 'click_nums', 'fav_nums']
    list_filter = ['name', 'desc', 'click_nums', 'fav_nums','city__name','address','add_time']


class TeacherAdmin(object):
    '''老师'''

    list_display = [ 'name','org', 'work_years', 'work_company','add_time']
    search_fields = ['org', 'name', 'work_years', 'work_company']
    list_filter = ['org__name', 'name', 'work_years', 'work_company','click_nums', 'fav_nums', 'add_time']


xadmin.site.register(CityDict, CityDictAdmin)
xadmin.site.register(CourseOrg, CourseOrgAdmin)
xadmin.site.register(Teacher, TeacherAdmin)
organization/adminx.py

 

4)operation/adminx.py:

# operation/adminx.py

import xadmin

from .models import UserAsk, UserCourse, UserMessage, CourseComments, UserFavorite


class UserAskAdmin(object):
    '''用户表单我要学习'''

    list_display = ['name', 'mobile', 'course_name', 'add_time']
    search_fields = ['name', 'mobile', 'course_name']
    list_filter = ['name', 'mobile', 'course_name', 'add_time']


#
class UserCourseAdmin(object):
    '''用户课程学习'''

    list_display = ['user', 'course', 'add_time']
    search_fields = ['user', 'course']
    list_filter = ['user', 'course', 'add_time']



class UserMessageAdmin(object):
    '''用户消息后台'''

    list_display = ['user', 'message', 'has_read', 'add_time']
    search_fields = ['user', 'message', 'has_read']
    list_filter = ['user', 'message', 'has_read', 'add_time']



class CourseCommentsAdmin(object):
    '''用户评论后台'''

    list_display = ['user', 'course', 'comments', 'add_time']
    search_fields = ['user', 'course', 'comments']
    list_filter = ['user', 'course', 'comments', 'add_time']



class UserFavoriteAdmin(object):
    '''用户收藏后台'''

    list_display = ['user', 'fav_id', 'fav_type', 'add_time']
    search_fields = ['user', 'fav_id', 'fav_type']
    list_filter = ['user', 'fav_id', 'fav_type', 'add_time']


# 将后台管理器与models进行关联注册。
xadmin.site.register(UserAsk, UserAskAdmin)
xadmin.site.register(UserCourse, UserCourseAdmin)
xadmin.site.register(UserMessage, UserMessageAdmin)
xadmin.site.register(CourseComments, CourseCommentsAdmin)
xadmin.site.register(UserFavorite, UserFavoriteAdmin)
operation/adminx.py

 

5.3、xadmin的全局配置 (全局配置,放在users下的adminx.py文件中)

 1)主题功能:

from xadmin import views

# 创建xadmin的最基本管理器配置,并与view绑定
class BaseSetting(object):
    # 开启主题功能
    enable_themes = True
    use_bootswatch = True

# 将基本配置管理与view绑定
xadmin.site.register(views.BaseAdminView,BaseSetting)

 

 2)全局配置:

  1. 系统标题
  2. footer信息
  3. 菜单收起/展开
# 全局修改,固定写法
class GlobalSettings(object):
    # 修改title
    site_title = '在线教育后台管理系统'
    # 修改footer
    site_footer = '在线教育网'
    # 菜单可收起/展开
    menu_style = 'accordion'

# 将title和footer信息进行注册
xadmin.site.register(views.CommAdminView,GlobalSettings)

 

3)将app名称从英文改为中文:

 第一步,在各app下的apps.py中,比如users/apps.py 添加:

verbose_name = '用户'
from django.apps import AppConfig


class UsersConfig(AppConfig):
    name = 'users'
    verbose_name = '用户'  # 新增

 

  第二步,有两种方式:

  1、在同app下的init.py文件中,如users/__init__.py中添加下面一行代码,即可实现app名称中文化

  default_app_config = 'users.apps.UsersConfig'

  

  2、直接在setting中的INSTALLED_APPS中配置,即可实现app名称中文化

INSTALLED_APPS = [
    ……
    'apps.users.apps.UsersConfig',
    'apps.organization.apps.OrganizationConfig',
    'apps.operation.apps.OperationConfig',
    'apps.course.apps.CourseConfig',
    # 'users',
    # 'operation',
    # 'organization',
    # 'course',
    ……
]

  

未来的你,会感谢现在努力的你!
posted on 2018-08-30 01:15  Eric_nan  阅读(329)  评论(0编辑  收藏  举报