一、前言
二、需求分析
三、初始化環(huán)境1、新建工程首先,打開cmd,cd到存放django項目的文件夾,創(chuàng)建一個新工程(也可以用虛擬環(huán)境virtualenv): django-admin startproject MxOnline2 2、創(chuàng)建app創(chuàng)建好工程之后就是配置整個工程的目錄結構,先創(chuàng)建四個app: python manage.py startapp users python manage.py startapp course python manage.py startapp organization python manage.py startapp operation 然后,在同級目錄下創(chuàng)建一個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文件夾用于存放靜態(tài)文件,css/js/img等; 新建templates文件夾用于存放html文件; 新建media文件夾用于存放后臺上傳的圖片、視頻等文件。 配置settings static、templates和media雖然創(chuàng)建好了,但是django還無法找到,所以必須在settings中配置。 注意: STATIC_URL的作用是映射靜態(tài)文件的url,只在templates中引用的時候用到,其用法與MEDIA_URL相同。 STATICFILES_DIRS的作用是由于我們在app之外設置了其它的static目錄。由于django在運行某個app的html時會默認查找這個app下的’static‘目錄,所以在app之外的static需要我們自己配置。這個用法在DEBUG=TRUE時生效,F(xiàn)ALSE時django則不會代管靜態(tài)文件,所以,在部署時會用到STATIC_ROOT。STATICFILES_DIRS的用法與TEMPLATES_DIRS相同。 # 配置靜態(tài)文件路徑
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、其它配置:語言和時區(qū) LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai' 5、數(shù)據(jù)庫配置# 配置數(shù)據(jù)庫庫,使用PostgreSQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mxonline2',
'USER': 'postgres',
'PASSWORD': 'MAQING',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}打開pgAdmin4,新建數(shù)據(jù)庫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中時,顯示的是當前數(shù)據(jù)表的名稱。
2、max_length為最大字符長度,由于CharField在數(shù)據(jù)庫中對應為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代表數(shù)據(jù)庫可以為空,blank代表后臺表單數(shù)據(jù)填寫時可以留白。
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="點擊數(shù)", default=0)
learn_nums = models.IntegerField(verbose_name="學習人數(shù)", default=0)
fav_nums = models.IntegerField(verbose_name="收藏數(shù)", default=0)
course_nums = models.IntegerField(verbose_name="課程數(shù)", 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="點擊數(shù)", default=0)
fav_nums = models.IntegerField(verbose_name="收藏數(shù)", 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="課程時長(分鐘數(shù))", default=0)
click_nums = models.IntegerField(verbose_name="點擊數(shù)", default=0)
learn_nums = models.IntegerField(verbose_name="學習人數(shù)", default=0)
fav_nums = models.IntegerField(verbose_name="收藏數(shù)", 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="章節(jié)名", max_length=20)
add_time = models.DateTimeField(verbose_name="添加時間", default=datetime.now)
class Meta:
verbose_name = "章節(jié)"
verbose_name_plural = verbose_name
def __str__(self):
return '《{0}》課程的章節(jié) >> {1}'.format(self.course, self.name)
class Video(models.Model):
lesson = models.ForeignKey(Lesson, verbose_name="所屬章節(jié)", 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="視頻時長(分鐘數(shù))", 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}》章節(jié)的視頻 >> {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則發(fā)送給所有用戶,否則就是用戶的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參數(shù),導入我們復寫后的模型 AUTH_USER_MODEL = 'users.UserProfile' 然后運行migrate,將寫好的數(shù)據(jù)遷移到數(shù)據(jù)庫中: python manage.py makemigrations python manage.py migrate 這時,打開pgAdmin4,就會發(fā)現(xiàn)創(chuàng)建了24張table,其中除了我們剛剛創(chuàng)建的15張之外,還有系統(tǒng)自動生成的,包括遷移記錄,會話等等。 另外,右擊某張表,選擇View/All Rows可以查看當前表的字段和數(shù)據(jù)信息。 五、Admin后臺管理系統(tǒng)使用django自帶的Admin之前先創(chuàng)建一個超級管理員賬戶: 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是一個外鍵,所以過濾的時候根據(jù)課程名稱過濾,即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關聯(lián)注冊
admin.site.register(Course, CourseAdmin)
admin.site.register(Lesson, LessonAdmin)
admin.site.register(Video, VideoAdmin)
admin.site.register(CourseResource, CourseResourceAdmin)常用幾個功能: list_display:設置修改頁面顯示哪些字段 search_fields:設置搜索框搜索數(shù)據(jù) list_filter:設置右側篩選欄 fieldsets:設置頁面布局 設置好后的頁面: 后臺首頁: 課程Table頁: 修改課程詳情頁: 這里只是實現(xiàn)簡單的功能,django的admin功能非常強大,待后續(xù)完善。 基本的結構搭建好了,模型有了,admin也能用了,下面就開始把前端頁面構建起來了。 |
|
|
來自: 寧靜致遠oj1kn5 > 《待分類》