作者:SimonDM,转行求职中
写作目的:无他,但求手熟尔
首先,打开cmd,cd到存放django项目的文件夹,创建一个新工程(也可以用虚拟环境virtualenv):
django-admin startproject MxOnline2
创建好工程之后就是配置整个工程的目录结构,先创建四个app:
python manage.py startapp users
python manage.py startapp course
python manage.py startapp organization
python manage.py startapp operation
然后,在同级目录下创建一个package,名为apps,用于存放上述四个app。将四个app剪切到apps中,右击apps -> Mark Directory as -> Sources Root。当django在根目录下找不到app时会去apps中去寻找,但此时pycharm知道这么做,而django不知道,所以还要到settings中配置。
import os
import sys
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
# 将四个app放到一个apps包中之后,由于找不到路径,配置此项。插入第0是希望先搜索apps目录下的文件
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
之后,在INSTALLED_APPS中注册四个app
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/img等;
新建templates文件夹用于存放html文件;
新建media文件夹用于存放后台上传的图片、视频等文件。
配置settings
static、templates和media虽然创建好了,但是django还无法找到,所以必须在settings中配置。
注意:
STATIC_URL的作用是映射静态文件的url,只在templates中引用的时候用到,其用法与MEDIA_URL相同。
STATICFILES_DIRS的作用是由于我们在app之外设置了其它的static目录。由于django在运行某个app的html时会默认查找这个app下的’static‘目录,所以在app之外的static需要我们自己配置。这个用法在DEBUG=TRUE时生效,FALSE时django则不会代管静态文件,所以,在部署时会用到STATIC_ROOT。STATICFILES_DIRS的用法与TEMPLATES_DIRS相同。
# 配置静态文件路径
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
# 配置templates路径
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# 配置上传的媒体路径
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
语言和时区
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
# 配置数据库库,使用PostgreSQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mxonline2',
'USER': 'postgres',
'PASSWORD': 'MAQING',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
打开pgAdmin4,新建数据库mxonline2。
整个项目配置完之后,就要开始着手设计Model。
from django.db import models
from datetime import datetime
# Create your models here.
'''
points:
1、verbose_name的作用是给予对象一个人类可读的名字,”A human-readable name for the object“。
用于table中某个字段时,在admin后台会显示verbose_name,用于Meta中时,显示的是当前数据表的名称。
2、max_length为最大字符长度,由于CharField在数据库中对应为varchar,最大长度为255,
所以这里设置的最大值也不能超过255,否则,用TextField代替。max_length的计算方法:len("字符串")=3。
3、ImageField继承自FileField,用于上传文件,其中的upload_to属性,用于指定上传文件的目录,该目录会在MEDIA_ROOT下自动生成。
如使用upload_to='uploads/%Y/%m/%d/',文件会上传到MEDIA_ROOT/uploads/2015/01/30中,
/%Y/%m/%d/为strftime()格式化的xxxx年xx月xx日。
4、null=True和blank=True通常一起使用,null代表数据库可以为空,blank代表后台表单数据填写时可以留白。
5、choices用于选择框,在使用前应该在class中定义一个可迭代对象,[(A, B), (A, B) ...],每个元组中第一个
元素代表实际值,第二个是人类可读名称,类似于verbose_name。
'''
class City(models.Model):
name = models.CharField(verbose_name="城市", max_length=20)
desc = models.CharField(verbose_name="描述", max_length=255)
add_time = models.DateTimeField(verbose_name="添加时间", 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(verbose_name="机构名称", max_length=20)
desc = models.TextField(verbose_name="机构描述")
category = models.CharField(verbose_name="机构类别", max_length=20, choices=ORG_CHOICES, default='pxjg')
tag = models.CharField(verbose_name="机构标签", max_length=20, default="全国知名")
image = models.ImageField(verbose_name="封面图", upload_to='org/%Y/%m')
address = models.CharField(verbose_name="机构地址", max_length=200)
city = models.ForeignKey(City, verbose_name="所在城市", on_delete=models.CASCADE)
click_nums = models.IntegerField(verbose_name="点击数", default=0)
learn_nums = models.IntegerField(verbose_name="学习人数", default=0)
fav_nums = models.IntegerField(verbose_name="收藏数", default=0)
course_nums = models.IntegerField(verbose_name="课程数", default=0)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "课程机构"
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class Teacher(models.Model):
org = models.ForeignKey(CourseOrg, verbose_name="所属机构", on_delete=models.CASCADE)
name = models.CharField(verbose_name="姓名", max_length=20)
age = models.IntegerField(verbose_name="年龄", default=0)
image = models.ImageField(verbose_name="头像", upload_to='teacher/%Y/%m', default='', null=True, blank=True)
work_year = models.IntegerField(verbose_name="工作年限", default=0)
work_company = models.CharField(verbose_name="就职公司", max_length=50)
work_position = models.CharField(verbose_name="工作岗位", max_length=50)
points = models.CharField(verbose_name="教学特点", max_length=50)
click_nums = models.IntegerField(verbose_name="点击数", default=0)
fav_nums = models.IntegerField(verbose_name="收藏数", default=0)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "教师"
verbose_name_plural = verbose_name
def __str__(self):
return self.name
from django.db import models
from datetime import datetime
from organization.models import CourseOrg, Teacher
# Create your models here.
class Course(models.Model):
DEGREE_CHOICES = (
('cj', '初级'),
('zj', '中级'),
('gj', '高级'),
)
course_org = models.ForeignKey(CourseOrg, verbose_name="所属机构", on_delete=models.CASCADE)
teacher = models.ForeignKey(Teacher, verbose_name="授课教师", on_delete=models.CASCADE)
name = models.CharField(verbose_name="名称", max_length=20)
desc = models.CharField(verbose_name="课程描述", max_length=255)
detail = models.TextField(verbose_name="课程详情")
image = models.ImageField(verbose_name="封面图", upload_to='course/%Y/%m')
degree = models.CharField(verbose_name="难度", choices=DEGREE_CHOICES, max_length=2, default='cj')
is_banner = models.BooleanField(verbose_name="是否轮播", default=False)
learn_times = models.IntegerField(verbose_name="课程时长(分钟数)", default=0)
click_nums = models.IntegerField(verbose_name="点击数", default=0)
learn_nums = models.IntegerField(verbose_name="学习人数", default=0)
fav_nums = models.IntegerField(verbose_name="收藏数", default=0)
category = models.CharField(verbose_name="分类", max_length=20)
tag = models.CharField(verbose_name="标签", max_length=20)
you_need_know = models.CharField(verbose_name="课程须知", max_length=255, default="本课程需要静心阅读")
teacher_tell = models.CharField(verbose_name="老师告诉你", max_length=255, default="好好学习,天天向上")
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
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(verbose_name="章节名", max_length=20)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "章节"
verbose_name_plural = verbose_name
def __str__(self):
return '《{0}》课程的章节 >> {1}'.format(self.course, self.name)
class Video(models.Model):
lesson = models.ForeignKey(Lesson, verbose_name="所属章节", on_delete=models.CASCADE)
name = models.CharField(verbose_name="视频名", max_length=20)
# 这里的视频地址是否可以替换为一个FileField?
url = models.URLField(verbose_name="视频地址", max_length=200, default='')
learn_times = models.IntegerField(verbose_name="视频时长(分钟数)", default=0)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "视频"
verbose_name_plural = verbose_name
def __str__(self):
return '《{0}》章节的视频 >> {1}'.format(self.lesson, self.name)
class CourseResource(models.Model):
course = models.ForeignKey(Course, verbose_name="所属课程", on_delete=models.CASCADE)
name = models.CharField(verbose_name="资源名", max_length=20)
resource = models.FileField(verbose_name="资源文件", upload_to='course/resource/%Y%m')
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "课程资源"
verbose_name_plural = verbose_name
def __str__(self):
return self.name
from django.db import models
from datetime import datetime
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserProfile(AbstractUser):
GENDER_CHOICES = (
('male', '男'),
('female', '女'),
)
nick_name = models.CharField(verbose_name="昵称", max_length=20)
birthday = models.DateField(verbose_name="生日", null=True, blank=True)
gender = models.CharField(verbose_name="性别", choices=GENDER_CHOICES, max_length=6, default='male')
address = models.CharField(verbose_name="地址", max_length=100, default='')
mobile = models.CharField(verbose_name="手机号", max_length=11, null=True, blank=True)
image = models.ImageField(verbose_name="头像", upload_to='image/%Y/%m', default='')
class Meta:
verbose_name = "用户信息"
verbose_name_plural = verbose_name
def __str__(self):
return self.username
class EmailVerifyRecord(models.Model):
VERIFY_RECORD_CHOICES = (
('register', '注册'),
('forget', '找回密码'),
('update_email', '修改邮箱'),
)
code = models.CharField(verbose_name="验证码", max_length=20)
email = models.EmailField(verbose_name="邮箱", max_length=100)
send_type = models.CharField(verbose_name="验证码类型", choices=VERIFY_RECORD_CHOICES, max_length=20)
send_time = models.DateTimeField(verbose_name="", default=datetime.now)
class Meta:
verbose_name = "邮箱验证码"
verbose_name_plural = verbose_name
def __str__(self):
return '{0}({1})'.format(self.code, self.email)
class Banner(models.Model):
title = models.CharField(verbose_name="标题", max_length=100)
image = models.ImageField(verbose_name="轮播图", upload_to='banner/%Y/%m')
url = models.URLField(verbose_name="访问地址", max_length=200)
index = models.IntegerField(verbose_name="顺序", default=100)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "轮播图"
verbose_name_plural = verbose_name
def __str__(self):
return '{0}(位于第{1}位)'.format(self.title, self.index)
from django.db import models
from datetime import datetime
from course.models import Course
from users.models import UserProfile
# Create your models here.
class UserAsk(models.Model):
name = models.CharField(verbose_name="姓名", max_length=20)
mobile = models.CharField(verbose_name="手机号", max_length=11)
course_name = models.CharField(verbose_name="课程名", max_length=50)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "用户咨询"
verbose_name_plural = verbose_name
def __str__(self):
return '用户:{0} 的手机号:{1}'.format(self.name, self.mobile)
class CourseComment(models.Model):
course = models.ForeignKey(Course, verbose_name="评论课程", on_delete=models.CASCADE)
user = models.ForeignKey(UserProfile, verbose_name="评论用户", on_delete=models.CASCADE)
comment = models.CharField(verbose_name="评论内容", max_length=255)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "课程评论"
verbose_name_plural = verbose_name
def __str__(self):
return '用户({0})对于《{1}》的评论'.format(self.user, self.course)
class UserFavorite(models.Model):
TYPE_CHOICES = (
(1, '机构'),
(2, '课程'),
(3, '教师'),
)
user = models.ForeignKey(UserProfile, verbose_name="用户", on_delete=models.CASCADE)
fav_type = models.IntegerField(verbose_name="收藏类型", choices=TYPE_CHOICES, default=1)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "用户收藏"
verbose_name_plural = verbose_name
def __str__(self):
return '用户({0})收藏了{1}'.format(self.user, self.fav_type)
class UserMessage(models.Model):
# 为0则发送给所有用户,否则就是用户的id
user = models.IntegerField(verbose_name="用户", default=0)
message = models.CharField(verbose_name="消息内容", max_length=255)
has_read = models.BooleanField(verbose_name="是否已读", default=False)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "用户消息"
verbose_name_plural = verbose_name
def __str__(self):
return '用户({0})接收了消息:{1}'.format(self.user, self.message)
class UserCourse(models.Model):
course = models.ForeignKey(Course, verbose_name="课程", on_delete=models.CASCADE)
user = models.ForeignKey(UserProfile, verbose_name="用户", on_delete=models.CASCADE)
add_time = models.DateTimeField(verbose_name="添加时间", default=datetime.now)
class Meta:
verbose_name = "用户课程"
verbose_name_plural = verbose_name
def __str__(self):
return '用户({0})学习了《{1}》'.format(self.user, self.course)
这里需要注意的是,django为我们提供了User表,功能包括:id、password、is_superuser、is_active、email等。如果我们需要扩展可以复写AbsractUser模型,之后,需要在settings中告诉django我们新的用户模型:
# 由于复写了user模型,我们需要重载AUTH_USER_MODEL参数,导入我们复写后的模型
AUTH_USER_MODEL = 'users.UserProfile'
然后运行migrate,将写好的数据迁移到数据库中:
python manage.py makemigrations
python manage.py migrate
这时,打开pgAdmin4,就会发现创建了24张table,其中除了我们刚刚创建的15张之外,还有系统自动生成的,包括迁移记录,会话等等。
另外,右击某张表,选择View/All Rows可以查看当前表的字段和数据信息。
使用django自带的Admin之前先创建一个超级管理员账户:
E:\DjangoProjects\MxOnline2>python manage.py createsuperuse
Username: simondm
Email address: 352830021@qq.com
Password:
Password (again):
Superuser created successfully.
然后,在每个app下的admin.py中注册并定制admin后台模型:
from django.contrib import admin
from .models import Course, Lesson, Video, CourseResource
# Register your models here.
# 在admin后台注册模型,并且定制后台
class CourseAdmin(admin.ModelAdmin):
# 设置fieldsets 控制管理“添加”和 “更改” 页面的布局,顺便可以给这些字段排序
fieldsets = (
(None, {
'fields': ('name', 'desc', 'tag', 'is_banner', ('course_org', 'teacher'), 'degree', 'learn_times', ('click_nums', 'learn_nums', 'fav_nums'), 'category')
}),
('其它选项', {
'fields': ('detail', 'image', 'you_need_know', 'teacher_tell', 'add_time')
}),
)
# 指定修改页面上显示的字段,如果不指定,则只显示__str__()指定的那一列。
list_display = ('name', 'desc', 'course_org', 'teacher', 'is_banner', 'colored_degree', 'learn_times', 'learn_nums')
search_fields = ('name', 'desc', 'detail', 'degree', 'learn_nums')
list_filter = ('name', 'desc', 'detail', 'degree', 'learn_times', 'learn_nums')
class LessonAdmin(admin.ModelAdmin):
list_display = ('course', 'name', 'add_time')
search_fields = ('course', 'name')
# 由于course是一个外键,所以过滤的时候根据课程名称过滤,即course.name
list_filter = ('course__name', 'name', 'add_time')
class VideoAdmin(admin.ModelAdmin):
list_display = ('lesson', 'name', 'add_time')
search_fields = ('lesson', 'name')
list_filter = ('lesson', 'name', 'add_time')
class CourseResourceAdmin(admin.ModelAdmin):
list_display = ('course', 'name', 'resource', 'add_time')
search_fields = ('course', 'name', 'resource')
list_filter = ('course__name', 'name', 'resource', 'add_time')
# models与admin关联注册
admin.site.register(Course, CourseAdmin)
admin.site.register(Lesson, LessonAdmin)
admin.site.register(Video, VideoAdmin)
admin.site.register(CourseResource, CourseResourceAdmin)
常用几个功能:
list_display:设置修改页面显示哪些字段
search_fields:设置搜索框搜索数据
list_filter:设置右侧筛选栏
fieldsets:设置页面布局
设置好后的页面:
后台首页:
课程Table页:
修改课程详情页:
这里只是实现简单的功能,django的admin功能非常强大,待后续完善。
基本的结构搭建好了,模型有了,admin也能用了,下面就开始把前端页面构建起来了。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。