typhoonpython 2019-11-03
操作系统:windows 10
Python: 3.7.1
Django: 2.0.6
浏览原始的前端页面,从页面上进行模块划分,抽象出APP,分析各个APP,初步抽取出APP模型和模型字段,从页面上分析整个项目模板的继承关系。

Django项目我们可以通过用命令的方式创建,也可以直接使用Pycharm创建,为了方便直接使用Pycharm创建
django-admin startproject GuLiEdu
打开Pycharm,创建项目,选择Django

python manage.py startapp users # 如果在创建项目时候创建,就不用重复创建 python manage.py startapp courses python manage.py startapp orgs python manage.py startapp operations
将我们刚才创建的app注册到Django中,在INSTALLED_APPS中添加我们创建的app名称

DATABASES = {
‘default‘: {
‘ENGINE‘: ‘django.db.backends.mysql‘,
‘NAME‘: ‘guliedu‘, # 需要去数据库创建
‘USER‘: ‘root‘,
‘PASSWORD‘: ‘123456‘,
‘HOST‘: ‘127.0.0.1‘,
‘PORT‘: 3306
}
}LANGUAGE_CODE = ‘zh-hans‘ TIME_ZONE = ‘Asia/Shanghai‘ USE_I18N = True USE_L10N = True USE_TZ = False
STATIC_URL = ‘/static/‘
STATICFILES_DIRS = [
os.path.join(BASE_DIR, ‘static‘)
]MEDIA_URL = ‘/static/media/‘ MEDIA_ROOT = os.path.join(BASE_DIR, ‘static/media‘)
分别在四个app中建立urls.py文件,并做简单配置
from django.urls import path app_name = app名称 urlpatterns = [ ]
在GuLiEdu目录下的urls中配置分发
from django.urls import path, include
urlpatterns = [
path(‘admin/‘, admin.site.urls),
path(‘users/‘, include(‘users.urls‘, namespace=‘users‘)),
path(‘courses/‘, include(‘courses.urls‘, namespace=‘courses‘)),
path(‘orgs/‘, include(‘orgs.urls‘, namespace=‘orgs‘)),
path(‘operations/‘, include(‘operations.urls‘, namespace=‘operations‘)),
]from django.db import models
from django.contrib.auth.models import AbstractUser
from datetime import datetime
# Create your models here.
class UserProfile(AbstractUser):
image = models.ImageField(upload_to=‘user/‘, max_length=200, verbose_name=‘用户头像‘, null=True, blank=True)
nick_name = models.CharField(max_length=20, verbose_name=‘用户昵称‘, null=True, blank=True)
birthday = models.DateTimeField(verbose_name=‘用户生日‘, null=True, blank=True)
gender = models.CharField(choices=((‘girl‘, ‘女‘), (‘boy‘, ‘男‘)), max_length=10, verbose_name=‘用户性别‘, default=‘girl‘)
address = models.CharField(max_length=200, verbose_name=‘用户地址‘, null=True, blank=True)
phone = models.CharField(max_length=11, verbose_name=‘用户手机‘, null=True, blank=True)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.username
class Meta:
verbose_name = ‘用户信息‘
verbose_name_plural = verbose_name
class BannerInfo(models.Model):
image = models.ImageField(upload_to=‘banner/‘, verbose_name=‘轮播图片‘, max_length=200)
url = models.URLField(default=‘http://www.atguigu.com‘, max_length=200, verbose_name=‘图片链接‘)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return str(self.image)
class Meta:
verbose_name = ‘轮播图信息‘
verbose_name_plural = verbose_name
class EmailVerify(models.Model):
code = models.CharField(max_length=20, verbose_name=‘邮箱验证码‘)
email = models.EmailField(max_length=200, verbose_name=‘验证码邮箱‘)
send_type = models.IntegerField(choices=((1, ‘register‘), (2, ‘forget‘), (3, ‘change‘)), verbose_name=‘验证码类型‘)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return str(self.code)
class Meta:
verbose_name = ‘邮箱验证码‘
verbose_name_plural = verbose_nameusers/model
用户表的设计,通过继承扩展Django内部auth模块自带的user表,生成我们自己的用户UserProfile表。注意:当使用继承后,需要在settings配置用户默认模型为自己创建的这个表,要不还是内部的user表settings设置如下:
AUTH_USER_MODEL = ‘users.UserProfile‘
from django.db import models
from datetime import datetime
# Create your models here.
class CityInfo(models.Model):
name = models.CharField(max_length=20, verbose_name=‘城市名称‘)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘城市信息‘
verbose_name_plural = verbose_name
class OrgInfo(models.Model):
image = models.ImageField(upload_to=‘org/‘, max_length=200, verbose_name=‘机构封面‘)
name = models.CharField(max_length=20, verbose_name=‘机构名称‘)
course_num = models.IntegerField(default=0, verbose_name=‘课程数‘)
study_num = models.IntegerField(default=0, verbose_name=‘学习人数‘)
address = models.CharField(max_length=200, verbose_name=‘机构地址‘)
desc = models.CharField(max_length=200, verbose_name=‘机构简介‘)
detail = models.TextField(verbose_name=‘机构详情‘)
love_num = models.IntegerField(default=0, verbose_name=‘收藏数‘)
click_num = models.IntegerField(default=0, verbose_name=‘访问量‘)
category = models.CharField(choices=((‘pxjg‘, ‘培训机构‘), (‘gx‘, ‘高校‘), (‘gr‘, ‘个人‘)), max_length=10, verbose_name=‘机构类别‘)
cityinfo = models.ForeignKey(CityInfo, verbose_name=‘所在城市‘, on_delete=models.CASCADE)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘机构信息‘
verbose_name_plural = verbose_name
class TeacherInfo(models.Model):
image = models.ImageField(upload_to=‘teacher/‘, max_length=200, verbose_name=‘讲师头像‘)
name = models.CharField(max_length=20, verbose_name=‘讲师姓名‘)
work_year = models.CharField(default=3, max_length=5, verbose_name=‘工作年限‘)
work_position = models.CharField(max_length=20, verbose_name=‘工作职位‘)
work_style = models.CharField(max_length=20, verbose_name=‘教学特点‘)
work_company = models.ForeignKey(OrgInfo, verbose_name=‘所属机构‘, on_delete=models.CASCADE)
age = models.IntegerField(default=30, verbose_name=‘讲师年龄‘)
gender = models.CharField(choices=((‘boy‘, ‘男‘), (‘girl‘, ‘女‘)), max_length=10, verbose_name=‘讲师性别‘, default=‘girl‘)
love_num = models.IntegerField(default=0, verbose_name=‘收藏数‘)
click_num = models.IntegerField(default=0, verbose_name=‘访问量‘)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘讲师信息‘
verbose_name_plural = verbose_nameorgs/models
from django.db import models
from datetime import datetime
# Create your models here.
from orgs.models import OrgInfo, TeacherInfo
class CourseInfo(models.Model):
image = models.ImageField(upload_to=‘course/‘, max_length=200, verbose_name=‘课程封面‘)
name = models.CharField(max_length=20, verbose_name=‘课程名称‘)
study_time = models.IntegerField(default=0, verbose_name=‘学习时长‘)
study_num = models.IntegerField(default=0, verbose_name=‘学习人数‘)
level = models.CharField(choices=((‘cj‘, ‘初级‘), (‘zj‘, ‘中级‘), (‘gj‘, ‘高级‘)), max_length=10, default=‘cj‘, verbose_name=‘课程难度‘)
love_num = models.IntegerField(default=0, verbose_name=‘收藏数‘)
click_num = models.IntegerField(default=0, verbose_name=‘访问量‘)
desc = models.CharField(max_length=200, verbose_name=‘课程简介‘)
detail = models.TextField(verbose_name=‘课程详情‘)
category = models.CharField(choices=((‘qd‘, ‘前端开发‘), (‘hd‘, ‘后端开发‘)), max_length=10, verbose_name=‘课程类别‘)
course_notice = models.CharField(max_length=200, verbose_name=‘课程公告‘)
course_need = models.CharField(max_length=100, verbose_name=‘课程须知‘)
teacher_tell = models.CharField(max_length=100, verbose_name=‘老师教导‘)
orginfo = models.ForeignKey(OrgInfo, verbose_name=‘所属机构‘, on_delete=models.CASCADE)
teacherinfo = models.ForeignKey(TeacherInfo, verbose_name=‘所属讲师‘, on_delete=models.CASCADE)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘课程表‘
verbose_name_plural = verbose_name
class LessonInfo(models.Model):
name = models.CharField(max_length=50, verbose_name=‘章节名称‘)
courseinfo = models.ForeignKey(CourseInfo, verbose_name=‘所属课程‘, on_delete=models.CASCADE)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘章节信息‘
verbose_name_plural = verbose_name
class VideoInfo(models.Model):
name = models.CharField(max_length=50, verbose_name=‘视频名称‘)
study_time = models.IntegerField(default=0, verbose_name=‘视频时长‘)
url = models.URLField(default=‘http://www.atguigu.com‘, verbose_name=‘视频链接‘, max_length=200)
lessoninfo = models.ForeignKey(LessonInfo, verbose_name=‘所属章节‘, on_delete=models.CASCADE)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘视频信息‘
verbose_name_plural = verbose_name
class SourceInfo(models.Model):
name = models.CharField(max_length=50, verbose_name=‘视频名称‘)
down_load = models.FileField(upload_to=‘source/‘, max_length=200, verbose_name=‘下载路径‘)
courseinfo = models.ForeignKey(CourseInfo, verbose_name=‘所属课程‘, on_delete=models.CASCADE)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘资源信息‘
verbose_name_plural = verbose_namecourses/models
在settings文件中,添加图片处理器,为了在课程列表中前面加上MEDIA_URL
‘django.template.context_processors.media‘, # 添加图片处理器,为了在课程列表中前面加上MEDIA_URL

from django.db import models
from datetime import datetime
from courses.models import CourseInfo
from users.models import UserProfile
# Create your models here.
class UserAsk(models.Model):
name = models.CharField(max_length=30, verbose_name=‘姓名‘)
phone = models.CharField(max_length=11, verbose_name=‘手机‘)
course = models.CharField(max_length=20, verbose_name=‘课程‘)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.name
class Meta:
verbose_name = ‘咨询信息‘
verbose_name_plural = verbose_name
class UserLove(models.Model):
love_man = models.ForeignKey(UserProfile, verbose_name=‘收藏用户‘, on_delete=models.CASCADE)
love_id = models.IntegerField(verbose_name=‘收藏ID‘) # 可以是机构,课程,老师
love_type = models.IntegerField(choices=((1, ‘org‘), (2, ‘course‘), (3, ‘teacher‘)), verbose_name=‘收藏类别‘)
love_status = models.BooleanField(default=False, verbose_name=‘收藏状态‘)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.love_man.username
class Meta:
verbose_name = ‘收藏信息‘
verbose_name_plural = verbose_name
class UserCourse(models.Model):
study_man = models.ForeignKey(UserProfile, verbose_name=‘学习用户‘, on_delete=models.CASCADE)
study_course = models.ForeignKey(CourseInfo, verbose_name=‘学习课程‘, on_delete=models.CASCADE)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.study_man
class Meta:
unique_together = (‘study_man‘, ‘study_course‘) # 联合唯一
verbose_name = ‘用户学习信息‘
verbose_name_plural = verbose_name
class UserComment(models.Model):
comment_man = models.ForeignKey(UserProfile, verbose_name=‘评论用户‘, on_delete=models.CASCADE)
comment_course = models.ForeignKey(CourseInfo, verbose_name=‘评论课程‘, on_delete=models.CASCADE)
comment_content = models.CharField(max_length=300, verbose_name=‘评论内容‘)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.comment_content
class Meta:
verbose_name = ‘用户课程信息‘
verbose_name_plural = verbose_name
class UserMessage(models.Model):
message_man = models.IntegerField(default=0, verbose_name=‘消息用户‘) # 如果id为0,系统消息
message_content = models.CharField(max_length=200, verbose_name=‘消息内容‘)
message_status = models.BooleanField(default=False, verbose_name=‘消息状态‘)
add_time = models.DateTimeField(default=datetime.now, verbose_name=‘添加时间‘)
def __str__(self):
return self.message_content
class Meta:
verbose_name = ‘用户消息‘
verbose_name_plural = verbose_nameoperations/models
根目录下创建apps包,将四个app分别拖入包中,不要选“Search for references”

如果选择,搜索还是从原始路径去搜索。
在apps上右键Mark为sourceRoot。
设置settings文件,为其加上python环境变量。
import os # 代表系统环境 import sys # 代表python环境 # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 将我们自己定义的包加入到Python搜寻环境变量当中 sys.path.insert(0, os.path.join(BASE_DIR, ‘Apps‘))
python manage.py makemigrations python manage.py migrate
http://sshwsfc.github.io/xadmin/ xadmin的官网
xadmin是一个Django的管理后台实现,使用了更加灵活的架构设计及Bootstrap UI框架, 目的是替换现有的admin,国人开发,有许多新的特性。详情参考上面xadmin官方网站。
在xadmin官方网站上我们可以看到xadmin的介绍,并且我们也可以发现xadmin的源码被托管在GitHub上,因此,我们可以去GitHub轻松获取到xadmin源码进行安装。

点击如图所示按钮后,我们可以通过git clone的方式或者直接选择下载zip的方式可以获取到xadmin的源码下载包。
a、 复制xadmin文件夹到我们的项目根目录当中
b、 创建extra_apps放置第三方的app,将xadmin移动到我们这个extra_apps下
c、 将extra_apps mark为root_source
d、 将extra_apps在setting当中配置好搜索路径
sys.path.insert(0, os.path.join(BASE_DIR, ‘extra_apps‘))
e、 依赖包装完之后,再去install当中添加上app
f、将xadmin和crispy_forms添加到我们的installed_apps
g、在总路由urls.py中将我们本来的admin注释掉改为我们xadmin
import xadmin
from django.urls import path, include
urlpatterns = [
path(‘xadmin/‘, xadmin.site.urls),
path(‘users/‘, include(‘users.urls‘, namespace=‘users‘)),
path(‘courses/‘, include(‘courses.urls‘, namespace=‘courses‘)),
path(‘orgs/‘, include(‘orgs.urls‘, namespace=‘orgs‘)),
path(‘operations/‘, include(‘operations.urls‘, namespace=‘operations‘)),
]h、再次执行迁移同步,目的是为了生成xadmin所依赖的表
i、创建超级管理员,去验证xadmin是否安装成功
python manage.py createsuperuser

在相应的app当中创建adminx.py文件,导入xadmin以及models中的模型,下面以users示例
import xadmin
from .models import BannerInfo, EmailVerifyCode
class BannerInfoXadmin(object):
list_display = [‘image‘, ‘url‘, ‘add_time‘] # 显示
search_fields = [‘image‘, ‘url‘] # 搜索框
list_filter = [‘image‘, ‘url‘] # 过滤器
class EmailVerifyCodeXadmin(object):
list_display = [‘code‘, ‘email‘, ‘send_type‘, ‘add_time‘]
xadmin.site.register(BannerInfo, BannerInfoXadmin) # 注册
xadmin.site.register(EmailVerifyCode, EmailVerifyCodeXadmin)
如上图所示,左侧显示了轮播图信息以及邮箱验证码两个模型,在轮播图信息中,我们添加了过滤器以及搜索框。
另外三个app方法与users类似。
import xadmin
from .models import CityInfo,OrgInfo,TeacherInfo
class CityInfoXadmin(object):
list_display = [‘name‘, ‘add_time‘]
class OrgInfoXadmin(object):
list_display = [‘image‘, ‘name‘, ‘course_num‘, ‘study_num‘, ‘love_num‘, ‘click_num‘,‘category‘, ‘cityinfo‘]
class TeacherInfoXadmin(object):
list_display = [‘image‘, ‘name‘, ‘work_year‘, ‘work_position‘, ‘work_style‘, ‘work_company‘, ‘age‘, ‘gender‘,
‘love_num‘, ‘click_num‘]
xadmin.site.register(CityInfo, CityInfoXadmin)
xadmin.site.register(OrgInfo, OrgInfoXadmin)
xadmin.site.register(TeacherInfo, TeacherInfoXadmin)orgs/xadmin.py
import xadmin
from .models import *
class CourseInfoXadmin(object):
list_display = [‘image‘,‘name‘,‘study_num‘,‘level‘,‘love_num‘,‘category‘,‘orginfo‘,‘teacherinfo‘]
class LessonInfoXadmin(object):
list_display = [‘name‘, ‘courseinfo‘, ‘add_time‘]
class VideoInfoXadmin(object):
list_display = [‘name‘, ‘study_time‘, ‘url‘, ‘lessoninfo‘]
class SourceInfoXadmin(object):
list_display = [‘name‘, ‘down_load‘, ‘courseinfo‘, ‘add_time‘]
xadmin.site.register(CourseInfo,CourseInfoXadmin)
xadmin.site.register(LessonInfo,LessonInfoXadmin)
xadmin.site.register(VideoInfo,VideoInfoXadmin)
xadmin.site.register(SourceInfo,SourceInfoXadmin)course/adminx.py
import xadmin
from .models import *
class UserAskXadmin(object):
list_display = [‘name‘, ‘phone‘, ‘course‘, ‘add_time‘]
class UserLoveXadmin(object):
list_display = [‘love_man‘, ‘love_id‘, ‘love_type‘, ‘love_status‘, ‘add_time‘]
class UserCourseXadmin(object):
list_display = [‘study_man‘, ‘study_course‘, ‘add_time‘]
class UserCommentXadmin(object):
list_display = [‘comment_man‘, ‘comment_course‘, ‘comment_content‘, ‘add_time‘]
class UserMessageXadmin(object):
list_display = [‘message_man‘, ‘message_content‘, ‘message_status‘, ‘add_time‘]
xadmin.site.register(UserAsk, UserAskXadmin)
xadmin.site.register(UserCourse, UserCourseXadmin)
xadmin.site.register(UserComment, UserCommentXadmin)
xadmin.site.register(UserMessage, UserMessageXadmin)operations/adminx.py
方法一:在app当中apps.py文件当中,最下面添加verbose_name=’自定义名字’
方法二: 在app当中的__init__文件当中添加配置
default_app_config = "orgs.apps.OrgsConfig"
说明:可以在installed_apps中安装应用的时候,按照users自动安装的方式去做安装,那么这个__init__文件中的配置也可以省略这里演示将在settings文件中,修改app注册安装方式,然后采用方法一修改字段
INSTALLED_APPS = [
‘django.contrib.admin‘,
‘django.contrib.auth‘,
‘django.contrib.contenttypes‘,
‘django.contrib.sessions‘,
‘django.contrib.messages‘,
‘django.contrib.staticfiles‘,
‘users.apps.UsersConfig‘,
‘courses.apps.CoursesConfig‘,
‘orgs.apps.OrgsConfig‘,
‘operations.apps.OperationsConfig‘,
‘xadmin‘,
‘crispy_forms‘
]所有的配置都放在users/adminx.py中
# 配置xadmin主题,注册的时候要用到专用的view去注册
class BaseXadminSetting(object):
enable_themes = True # 主题
use_bootswatch = True # 自带主题
xadmin.site.register(views.BaseAdminView, BaseXadminSetting) # 注册主题class GlobalXadminSetting(object): # 标题和底部公司名称
site_title = ‘Egon人生无限‘
site_footer = ‘小姑娘快过来,让我摸一下屁股‘
menu_style = ‘accordion‘ # 菜单收起
xadmin.site.register(views.CommAdminView, GlobalXadminSetting) # 注册标题和底部公司名称import xadmin
from .models import BannerInfo, EmailVerifyCode
from xadmin import views
# 配置xadmin主题,注册的时候要用到专用的view去注册
class BaseXadminSetting(object):
enable_themes = True # 主题
use_bootswatch = True # 自带主题
class GlobalXadminSetting(object): # 标题和底部公司名称
site_title = ‘Egon人生无限‘
site_footer = ‘小姑娘快过来,让我摸一下屁股‘
menu_style = ‘accordion‘ # 列表菜单收起
class BannerInfoXadmin(object):
list_display = [‘image‘, ‘url‘, ‘add_time‘] # 显示
search_fields = [‘image‘, ‘url‘] # 搜索框
list_filter = [‘image‘, ‘url‘] # 过滤器
class EmailVerifyCodeXadmin(object):
list_display = [‘code‘, ‘email‘, ‘send_type‘, ‘add_time‘]
xadmin.site.register(views.BaseAdminView, BaseXadminSetting) # 注册主题
xadmin.site.register(views.CommAdminView, GlobalXadminSetting) # 注册标题和底部公司名称
xadmin.site.register(BannerInfo, BannerInfoXadmin)
xadmin.site.register(EmailVerifyCode, EmailVerifyCodeXadmin)adminx.py完整代码
