Django实战:用户、课程与机构模块的模型设计与数据库迁移

键盘旁的猫
键盘旁的猫
发布时间:2026-10-15| 5人浏览过
原创

本文详细讲解Django项目中users、course、organization及operation四个核心APP的模型设计。重点阐述如何配置INSTALLED_APPS、处理Django 2.0+版本中ForeignKey的on_delete参数,以及通过makemigrations和migrate命令完成数据库表结构的生成与同步,解决常见报错并优化项目结构。

Django框架的核心在于其设计模式,本文聚焦于后端数据模型的具体实现。

项目主要包含四个管理模块:users负责用户信息管理,course用于课程资源管理,organization涵盖机构与教师数据管理,operation处理用户交互操作。

接下来将详细说明如何根据各APP的业务需求设计数据模型,并执行数据库表的生成与修改操作。

首先针对users应用进行模型设计。

需要修改users目录下的models.py文件,定义用户信息类。


# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals
from datetime import datetime
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserProfile(AbstractUser):
    # verbose_name:备注
    # blank:是否可以为空
    #
    nick_name = models.CharField(max_length=50,verbose_name=u"昵称",default="")
    birthday = models.DateField(verbose_name=u"生日",blank=True)
    gender = models.CharField(choices=(('male',u'男'),('female',u'女')),default="female",max_length=6)
    address = models.CharField(max_length=100,default=u"")
    mobile = models.CharField(max_length=11,null=True,blank=True)
    image = models.ImageField(upload_to="image/%Y/%m",default=u"image/default.png",max_length=100)
    class Meta:
        verbose_name = u"用户信息"
        verbose_name_plural = verbose_name
    def __unicode__(self):
        return self.username
class EmailVerifyRecord(models.Model):
    code = models.CharField(max_length=20,verbose_name=u"验证码")
    email = models.EmailField(max_length=50,verbose_name=u"邮箱")
    send_type = models.CharField(max_length=10,choices=(("register",u"注册"),("forget",u"找回密码")),)
    send_time = models.DateTimeField(default=datetime.now(),verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"邮箱验证码"
        verbose_name_plural = verbose_name
class Banner(models.Model):
    title = models.CharField(max_length=100,verbose_name=u"标题")
    image = models.ImageField(max_length=100,upload_to="banner/%Y/%m",verbose_name=u"轮播图")
    url = models.URLField(max_length=100,verbose_name=u"访问地址")
    index = models.IntegerField(verbose_name=u"顺序",default=100)
    add_time = models.DateTimeField(default=datetime.now(),verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"轮播图"
        verbose_name_plural = verbose_name

随后修改配置文件setting.py,在INSTALLED_APPS列表中添加'users'应用,并设置AUTH_USER_MODEL = "users.UserProfile"以指定自定义用户模型。


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'users',
]
AUTH_USER_MODEL = "users.UserProfile"

配置完成后,运行命令python manage.py runserver 0.0.0.0:9000启动开发服务器。

若在运行过程中遇到图片处理相关的报错,需执行pip3 install Pillow安装Pillow依赖包以解决。

接着执行python manage.py makemigrations users生成迁移文件,再运行python manage.py migrate users将模型同步至数据库。

若出现users.0001_initial相关的初始化错误,可尝试注释掉配置文件INSTALLED_APPS中的'django.contrib.admin'以排查问题。

随后进行course应用的模型设计。

修改course目录下的models.py,定义课程相关的数据结构。


# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals
from datetime import  datetime
from django.db import models
# Create your models here.
class Course(models.Model):
    name = models.CharField(max_length=50,verbose_name=u"课程名")
    desc = models.CharField(max_length=300,verbose_name=u"课程描述")
    detail = models.TextField(verbose_name=u"课程详情")
    degree = models.CharField(max_length=2,choices=(('cj','初级'),('zj','中级'),('gj','高级')))
    learn_time = models.IntegerField(default=0,verbose_name=u"学习时长")
    students = models.IntegerField(default=0,verbose_name=u"学习人数")
    fav_nums = models.IntegerField(default=0,verbose_name=u"收藏人数")
    image = models.ImageField(max_length=100,verbose_name="封面图片",upload_to="courses/%Y/%m")
    click_nums = models.IntegerField(default=0,verbose_name=u"点击数")
    add_time = models.DateTimeField(default=datetime.now,verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"课程"
        verbose_name_plural = verbose_name
class Lesson(models.Model):
    course = models.ForeignKey(Course,verbose_name=u"课程",on_delete=models.CASCADE)
    name = models.CharField(max_length=100,verbose_name=u"章节名")
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"章节"
        verbose_name_plural = verbose_name
class Video(models.Model):
    lesson = models.ForeignKey(Lesson,verbose_name=u"章节",on_delete=models.CASCADE)
    name = models.CharField(max_length=100, verbose_name=u"视频名")
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"视频"
        verbose_name_plural = verbose_name
class CourseResource(models.Model):
    course = models.ForeignKey(Course, verbose_name=u"课程",on_delete=models.CASCADE)
    name = models.CharField(max_length=100, verbose_name=u"名称")
    download = models.FileField(upload_to="course/recourse/%Y/%m",verbose_name=u"资源文件",
                                max_length=100)
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"课程资源"
        verbose_name_plural = verbose_name

同样需要修改配置文件setting.py,在INSTALLED_APPS中添加'course'应用。


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

再次运行python manage.py runserver 0.0.0.0:9000验证服务是否正常启动。

在此过程中可能会遇到关于外键定义的报错,需要明确其原因。

自Django 2.0版本起,定义外键(ForeignKey)或一对一关系时必须显式指定on_delete参数,旨在防止因删除主表数据导致外键表数据不一致的问题。

若未指定该参数,系统会报错:TypeError: init() missing 1 required positional argument: ‘on_delete'。

因此,所有涉及外键定义的字段都需要进行相应修改。

例如,课程关联字段应写为:course = models.ForeignKey(Course,verbose_name=u"课程",on_delete=models.CASCADE)。

接下来处理organization应用的模型设计。

修改organization目录下的models.py,定义机构与教师信息。


# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals
from datetime import datetime
from django.db import models
# Create your models here.
class CityDict(models.Model):
    name = models.CharField(max_length=20, verbose_name=u"城市名称")
    desc = models.CharField(max_length=200,verbose_name=u"城市描述")
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"城市"
        verbose_name_plural = verbose_name
class CourseOrg(models.Model):
    name = models.CharField(max_length=50,verbose_name=u"机构名称")
    desc = models.TextField(verbose_name=u"机构描述")
    click_nums = models.IntegerField(default=0,verbose_name=u"点击数")
    fav_nums = models.IntegerField(default=0,verbose_name=u"收藏数")
    image = models.ImageField(upload_to="org/%Y/%m",verbose_name=u"封面图",max_length=100)
    address = models.CharField(max_length=150,verbose_name=u"机构地址")
    city = models.ForeignKey(CityDict,verbose_name=u"所在城市",on_delete=models.CASCADE)
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"课程机构"
        verbose_name_plural = verbose_name
class Teacher(models.Model):
    org = models.ForeignKey(CourseOrg,verbose_name=u"所属机构",on_delete=models.CASCADE)
    name = models.CharField(max_length=50, verbose_name=u"教师名称")
    work_years = models.IntegerField(default=0,verbose_name=u"工作年限")
    work_company = models.CharField(max_length=50,verbose_name=u"就职公司")
    work_position = models.CharField(max_length=50,verbose_name=u"公司职位")
    points = models.CharField(max_length=50,verbose_name=u"教学特点")
    click_nums = models.IntegerField(default=0, verbose_name=u"点击数")
    fav_nums = models.IntegerField(default=0, verbose_name=u"收藏数")
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"教师"
        verbose_name_plural = verbose_name

修改配置文件setting.py,在INSTALLED_APPS中添加'organization'应用。


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

最后进行operation应用的模型设计。


# _*_ encoding:utf-8 _*_from __future__ import unicode_literalsfrom datetime import datetimefrom django.db import modelsfrom users.models import UserProfilefrom course.models import Course# Create your models here.class UserAsk(models.Model):    name = models.CharField(max_length=20,verbose_name=u"姓名")    mobile = models.CharField(max_length=11,verbose_name=u"手机")    course_name = models.CharField(max_length=50,verbose_name=u"课程名")    add_time = models.DateTimeField(default=datetime.now,verbose_name=u"添加时间")    class Meta:        verbose_name = u"用户咨询"        verbose_name_plural = verbose_nameclass CourseComments(models.Model):    # 课程评论    user = models.ForeignKey(UserProfile,verbose_name=u"用户",on_delete=models.CASCADE)    course = models.ForeignKey(Course,verbose_name=u"课程",on_delete=models.CASCADE)    comments = models.CharField(max_length=200,verbose_name=u"评论")    add_time = models.DateTimeField(default=datetime.now,verbose_name=u"评论时间")    class Meta:        verbose_name = u"课程评论"        verbose_name_plural = verbose_nameclass UserFavorite(models.Model):    user = models.ForeignKey(UserProfile,verbose_name=u"用户",on_delete=models.CASCADE)    fav_id = models.IntegerField(default=0,verbose_name=u"数据id")    fav_type = models.IntegerField(choices=((1,'课程'),(2,'课程机构'),(3,'讲师')),default=1,                                   verbose_name=u"收藏类型")    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"收藏时间")    class Meta:        verbose_name = u"用户收藏"        verbose_name_plural = verbose_nameclass UserMessage(models.Model):    user = models.ForeignKey(UserProfile, verbose_name=u"接收用户",on_delete=models.CASCADE)    message = models.CharField(max_length=500,verbose_name=u"消息内容")    has_read = models.BooleanField(default=False,verbose_name=u"是否已读")    add_time = models.DateTimeField(default=datetime.now,verbose_name=u"添加时间")    class Meta:        verbose_name = u"用户信息"        verbose_name_plural = verbose_nameclass UserCourse(models.Model):    user = models.ForeignKey(UserProfile, verbose_name=u"用户",on_delete=models.CASCADE)    course = models.ForeignKey(Course, verbose_name=u"课程",on_delete=models.CASCADE)    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")    class Meta:        verbose_name = u"用户课程"        verbose_name_plural = verbose_name

修改配置文件setting.py,在INSTALLED_APPS中添加'operation'应用。


# _*_ encoding:utf-8 _*_
from __future__ import unicode_literals
from datetime import datetime
from django.db import models
from users.models import UserProfile
from course.models import Course
# Create your models here.
class UserAsk(models.Model):
    name = models.CharField(max_length=20,verbose_name=u"姓名")
    mobile = models.CharField(max_length=11,verbose_name=u"手机")
    course_name = models.CharField(max_length=50,verbose_name=u"课程名")
    add_time = models.DateTimeField(default=datetime.now,verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"用户咨询"
        verbose_name_plural = verbose_name
class CourseComments(models.Model):
    # 课程评论
    user = models.ForeignKey(UserProfile,verbose_name=u"用户",on_delete=models.CASCADE)
    course = models.ForeignKey(Course,verbose_name=u"课程",on_delete=models.CASCADE)
    comments = models.CharField(max_length=200,verbose_name=u"评论")
    add_time = models.DateTimeField(default=datetime.now,verbose_name=u"评论时间")
    class Meta:
        verbose_name = u"课程评论"
        verbose_name_plural = verbose_name
class UserFavorite(models.Model):
    user = models.ForeignKey(UserProfile,verbose_name=u"用户",on_delete=models.CASCADE)
    fav_id = models.IntegerField(default=0,verbose_name=u"数据id")
    fav_type = models.IntegerField(choices=((1,'课程'),(2,'课程机构'),(3,'讲师')),default=1,
                                   verbose_name=u"收藏类型")
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"收藏时间")
    class Meta:
        verbose_name = u"用户收藏"
        verbose_name_plural = verbose_name
class UserMessage(models.Model):
    user = models.ForeignKey(UserProfile, verbose_name=u"接收用户",on_delete=models.CASCADE)
    message = models.CharField(max_length=500,verbose_name=u"消息内容")
    has_read = models.BooleanField(default=False,verbose_name=u"是否已读")
    add_time = models.DateTimeField(default=datetime.now,verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"用户信息"
        verbose_name_plural = verbose_name
class UserCourse(models.Model):
    user = models.ForeignKey(UserProfile, verbose_name=u"用户",on_delete=models.CASCADE)
    course = models.ForeignKey(Course, verbose_name=u"课程",on_delete=models.CASCADE)
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    class Meta:
        verbose_name = u"用户课程"
        verbose_name_plural = verbose_name

为了便于管理,将上述4个APP统一移动到apps包目录下。

由于应用数量较多,统一归类到apps目录下有助于提升项目结构的清晰度与管理效率。

同时,需将apps路径写入配置文件setting.py中,以确保Python能正确识别并导入各模块,防止包导入失败。


import os
import sys
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,os.path.join(BASE_DIR,'apps'))

完成路径配置后,依次执行python manage.py makemigrations和python manage.py migrate命令,正式生成并更新数据库表结构。

最后运行python manage.py runserver 0.0.0.0:9000启动服务,确保所有模块正常加载。

本文对Django多应用模型设计及数据库迁移流程进行了总结。

希望本文内容能为您提供帮助,欢迎持续关注本站获取更多技术分享。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。