一、前言
二、需求分析
三、初始化环境1、新建工程首先,打开cmd,cd到存放django项目的文件夹,创建一个新工程(也可以用虚拟环境virtualenv): django-admin startproject MxOnline2 2、创建app创建好工程之后就是配置整个工程的目录结构,先创建四个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', ] 3、配置目录结构新建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') 4、其它配置:语言和时区 LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' 5、数据库配置# 配置数据库库,使用PostgreSQL DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mxonline2', 'USER': 'postgres', 'PASSWORD': 'MAQING', 'HOST': '127.0.0.1', 'PORT': '5432', } } 打开pgAdmin4,新建数据库mxonline2。 四、模型设计Model整个项目配置完之后,就要开始着手设计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可以查看当前表的字段和数据信息。 五、Admin后台管理系统使用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也能用了,下面就开始把前端页面构建起来了。 |
|
来自: 宁静致远oj1kn5 > 《待分类》