Django加Vue电商项目实战04 模型创建

前言

学无止境,无止境学。大家好,我是张大鹏,之前在抖音有5万多粉丝,不过现在不拍视频,专心写公众号了。笔者目前是高级Python工程师,之前是全栈工程师,主要擅长Golang和Python开发,对于JavaVue,React也有一些研究。工作之余,喜欢学习和分享,希望能够通过此公众号”张大鹏520″,将自己学到的东西分享给大家,和大家一起交流,一起成长,一起进步。

今天要给大家分享的是《Django加Vue电商项目实战04 模型创建》,这是一个系列的教程,从零基础到项目实战。在本教程中,我会给大家介绍Django的模型创建相关的知识,比如定义一对一关系,一对多关系,多对多关系等。还会配套相关的练习,大家学完以后可以自行通过练习题巩固和加深对知识点的理解。

如果大家需要本教程的PDF电子书或者完整的源码,可以在文末找到获取方式哈。

环境搭建

Docker安装MySQL

拉取MySQL镜像

docker pull mysql

查看镜像,检查是否拉取成功

docker images

建立目录映射

mkdir /data/docker/mysql
mkdir /data/docker/mysql/conf/
mkdir /data/docker/mysql/logs/
mkdir /data/docker/mysql/data/

创建my.cnf配置文件

vim /data/docker/mysql/my.cnf

添加以下内容:

[mysqld]
user=mysql
character-set-server=utf8
default_authentication_plugin=mysql_native_password
secure_file_priv=/var/lib/mysql
expire_logs_days=7
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
max_connections=1000

[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

创建容器,并后台启动

docker run --restart=always --privileged=true -v /data/docker/mysql/data/:/var/lib/mysql -v /data/docker/mysql/logs/:/var/log/mysql -v /data/docker/mysql/conf/:/etc/mysql/conf.d -v /data/docker/mysql/my.cnf:/etc/mysql/my.cnf  -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=root -d mysql
  • -v:主机和容器的目录映射关系,”:”前为主机目录,之后为容器目录
  • –restart=always:当Docker 重启时,容器会自动启动。
  • –privileged=true:容器内的root拥有真正root权限,否则容器内root只是外部普通用户权限

注意:启动mysql报如下错误,那是因为MYSQL新特性secure_file_priv对读写文件的影响。

ERROR: mysqld failed while attempting to check config
command was: "mysqld --verbose --help"

mysqld: Error on realpath() on '/var/lib/mysql-files' (Error 2 - No such file or directory)
2019-09-14T09:52:51.015937Z 0 [ERROR] [MY-010095] [Server] Failed to access directory for --secure-file-priv. Please make sure that directory exists and is accessible by MySQL Server. Supplied value : /var/lib/mysql-files
2019-09-14T09:52:51.018328Z 0 [ERROR] [MY-010119] [Server] Aborting

解决问题:

  • windows下:修改my.ini 在[mysqld]内加入secure_file_priv=/var/lib/mysql
  • Linux下:修改my.cnf 在[mysqld]内加入secure_file_priv=/var/lib/mysql

进入mysql容器

docker exec -it mysql /bin/bash

登陆mysql

mysql -u root -proot

mysql 8 设置允许远程用户访问

use mysql;

#
 更新root - localhost 为 root - %
update user set host = '%' where user = 'root' and host='localhost'; 

#
 设置允许远程用户访问
GRANT ALL ON *.* TO 'root'@'%'; 

#
 刷新权限
flush privileges;

#
 更新用户加密方式,mysql8默认的加密方式为caching_sha2_password 
# 与mysql5的加密方式mysql_native_password 不同
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';

使用Navicat 或者 MySQL Workbench 远程连接mysql,我们在创建容器的时候已经将容器的3306端口和主机的3306端口映射到一起,所以我们应该访问:

host: 127.0.0.1
port: 3306
user: root
password: root

安装依赖

pip install django
pip install mysqlclient

创建项目

# 创建项目
django-admin startproject z05_django_orm

#
 创建静态目录和模板目录
cd z05_django_orm
mkdir static
mkdir templates

#
 创建应用
python manage.py startapp index

配置项目

配置应用:

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

配置模板目录:

TEMPLATES = [
    {
        'BACKEND''django.template.backends.django.DjangoTemplates',
        'DIRS': [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',
            ],
        },
    },
]

配置语言和时区:

LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True

配置静态目录:

STATICFILES_DIRS = [BASE_DIR / 'static']
STATIC_URL = '/static/'
if not DEBUG:
    STATIC_ROOT = BASE_DIR / 'static'

启动测试

在项目目录执行以下命令启动服务:

python manage.py runserver

模型设计

整体设计

所有的模型如下:

from django.db import models
from django.utils import timezone


class UserBaseInfo(models.Model):
    """
    用户基本信息
    """

    id = models.AutoField(verbose_name='编号', primary_key=True)
    username = models.CharField(verbose_name='用户名称', max_length=30)
    password = models.CharField(verbose_name='密码', max_length=20)
    status = models.CharField(verbose_name='状态', max_length=1)
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)

    def __str__(self):
        return self.username

    class Meta:
        managed = True
        verbose_name = '人员基本信息'
        db_table = 'user'


class DepartInfo(models.Model):
    """
    部门信息
    """

    id = models.AutoField(verbose_name='编号', primary_key=True)
    depart_name = models.CharField(verbose_name='部门名称', max_length=30)
    # default=timezone.now:解决时区问题
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)

    def __str__(self):
        return str(self.id)

    class Meta:
        managed = True
        verbose_name = '部门信息'
        db_table = 'depart'


class UserExtraInfo(models.Model):
    """用户扩展信息"""
    id = models.AutoField(verbose_name='编号', primary_key=True)
    username = models.CharField(verbose_name='用户名称', max_length=30)
    true_name = models.CharField(verbose_name='真实姓名', max_length=30)
    sex = models.IntegerField(verbose_name='性别')
    salary = models.DecimalField(verbose_name='薪水', max_digits=8, decimal_places=2)
    age = models.IntegerField(verbose_name='年龄', )
    department = models.CharField(verbose_name='部门', max_length=20)
    status = models.CharField(verbose_name='状态', max_length=1)
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)
    memo = models.TextField(verbose_name='备注', blank=True, null=True)
    # 一对一关联
    user = models.OneToOneField(UserBaseInfo, on_delete=models.CASCADE)

    def __str__(self):
        return str(self.id)

    class Meta:
        managed = True
        verbose_name = '人员扩展信息'
        db_table = 'user_extra'


class CardInfo(models.Model):
    """银行卡信息"""
    id = models.AutoField(verbose_name='编号', primary_key=True)
    card_no = models.CharField(verbose_name='卡号', max_length=30)
    bank = models.CharField(verbose_name='所属银行', max_length=30)
    # 一对多关联
    # on_delete=models.CASCADE:级联删除
    # related_name="user_card":反向关联字段
    user = models.ForeignKey(UserBaseInfo, related_name="user_card", on_delete=models.CASCADE)

    def __str__(self):
        return str(self.id)

    class Meta:
        managed = True
        verbose_name = '用户卡信息'
        db_table = 'card_info'


class SkillInfo(models.Model):
    """技能信息"""
    id = models.AutoField(verbose_name='编号', primary_key=True)
    skill_name = models.CharField(verbose_name='特长', max_length=30)
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)
    # 多对多关联
    user = models.ManyToManyField(UserBaseInfo, db_table="user_skill")

    def __str__(self):
        return str(self.id)

    class Meta:
        managed = True
        verbose_name = '特长信息'
        db_table = 'skill_info'

一对一关系

一对一关系,值得是两张表中的数据存在唯一的对应关系。比如,用户基本信息对应唯一的一条用户扩展信息,用户扩展信息,也同样对应唯一的一条用户基本信息。

示例代码:

class UserBaseInfo(models.Model):
    """
    用户基本信息
    """

    id = models.AutoField(verbose_name='编号', primary_key=True)
    username = models.CharField(verbose_name='用户名称', max_length=30)
    password = models.CharField(verbose_name='密码', max_length=20)
    status = models.CharField(verbose_name='状态', max_length=1)
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)

    def __str__(self):
        return self.username

    class Meta:
        managed = True
        verbose_name = '人员基本信息'
        db_table = 'user'

class UserExtraInfo(models.Model):
    """用户扩展信息"""
    id = models.AutoField(verbose_name='编号', primary_key=True)
    username = models.CharField(verbose_name='用户名称', max_length=30)
    true_name = models.CharField(verbose_name='真实姓名', max_length=30)
    sex = models.IntegerField(verbose_name='性别')
    salary = models.DecimalField(verbose_name='薪水', max_digits=8, decimal_places=2)
    age = models.IntegerField(verbose_name='年龄', )
    department = models.CharField(verbose_name='部门', max_length=20)
    status = models.CharField(verbose_name='状态', max_length=1)
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)
    memo = models.TextField(verbose_name='备注', blank=True, null=True)
    # 一对一关联
    user = models.OneToOneField(UserBaseInfo, on_delete=models.CASCADE)

    def __str__(self):
        return str(self.id)

    class Meta:
        managed = True
        verbose_name = '人员扩展信息'
        db_table = 'user_extra'

一对多关联

一对多关系,即就是常说的外键关系。指的是一张表中的一条数据,可以与另一张表中的多条数据建立关联。比如一个用户可以拥有多张银行卡,但是一张银行卡肯定只属于一个用户。

示例代码:

class UserBaseInfo(models.Model):
    """
    用户基本信息
    """

    id = models.AutoField(verbose_name='编号', primary_key=True)
    username = models.CharField(verbose_name='用户名称', max_length=30)
    password = models.CharField(verbose_name='密码', max_length=20)
    status = models.CharField(verbose_name='状态', max_length=1)
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)

    def __str__(self):
        return self.username

    class Meta:
        managed = True
        verbose_name = '人员基本信息'
        db_table = 'user'

class CardInfo(models.Model):
    """银行卡信息"""
    id = models.AutoField(verbose_name='编号', primary_key=True)
    card_no = models.CharField(verbose_name='卡号', max_length=30)
    bank = models.CharField(verbose_name='所属银行', max_length=30)
    # 一对多关联
    # on_delete=models.CASCADE:级联删除
    # related_name="user_card":反向关联字段
    user = models.ForeignKey(UserBaseInfo, related_name="user_card", on_delete=models.CASCADE)

    def __str__(self):
        return str(self.id)

    class Meta:
        managed = True
        verbose_name = '用户卡信息'
        db_table = 'card_info'

多对多关系

多对多关系,指的是两张表中,数据之间可以同时产生多种关联。比如一个用户可以有多种技能,一种技能可能属于多个用户。多对多关系比较特殊,会单独创建一张关联表,来记录两张表之间的关联关系。

示例代码:

class UserBaseInfo(models.Model):
    """
    用户基本信息
    """

    id = models.AutoField(verbose_name='编号', primary_key=True)
    username = models.CharField(verbose_name='用户名称', max_length=30)
    password = models.CharField(verbose_name='密码', max_length=20)
    status = models.CharField(verbose_name='状态', max_length=1)
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)

    def __str__(self):
        return self.username

    class Meta:
        managed = True
        verbose_name = '人员基本信息'
        db_table = 'user'

class SkillInfo(models.Model):
    """技能信息"""
    id = models.AutoField(verbose_name='编号', primary_key=True)
    skill_name = models.CharField(verbose_name='特长', max_length=30)
    createdate = models.DateTimeField(verbose_name='创建日期', db_column='createDate', default=timezone.now)
    # 多对多关联
    user = models.ManyToManyField(UserBaseInfo, db_table="user_skill")

    def __str__(self):
        return str(self.id)

    class Meta:
        managed = True
        verbose_name = '特长信息'
        db_table = 'skill_info'

配置数据库信息

# 数据库信息
DATABASES = {
    'default': {
        'ENGINE''django.db.backends.mysql',
        'NAME''django_shop',  # 数据库名
        'USER''root',  # 用户名
        'PASSWORD''root',  # 密码
        'HOST''192.168.33.12',  # 主机
        'PORT''3306',
        # 取消外键约束,否则多对多模型迁移报django.db.utils.IntegrityError: (1215, 'Cannot add foreign key constraint')
        'OPTIONS': {
            "init_command""SET foreign_key_checks = 0;",
            'charset''utf8'
        },
    }
}

配置日志

# 配置日志
LOGGING = {
    'version'1,
    'disable_existing_loggers'False,
    # 日志处理器
    'handlers': {
        # 控制台日志处理器
        'console': {
            'level''DEBUG',
            'class''logging.StreamHandler',
        },
    },
    'loggers': {
        # SQL语句输出到控制台
        'django.db.backends': {
            'handlers': ['console'],
            'propagate'True,
            'level''DEBUG',
        },
    }
}

模型迁移

# 创建模型迁移脚本
python manage.py makemigrations

#
 执行迁移
python manage.py migrate

生成SQL语句

执行下面的命令可以将迁移脚本转为SQL语句脚本:

# python manage.py sqlmigrate 应用名 版本 > 目标脚本
python manage.py sqlmigrate index 0001 > 0001.sql

结语

关注我不迷路,欢迎关注我的微信公众号”张大鹏520″,如果您对此文章感兴趣,欢迎点赞收藏,留言评论。

文中所有代码,只需要打赏20元,然后留言评论“已打赏”,即可获取哦。

本文的PDF电子书版,只需要打赏3元,然后留言评论“已打赏”,即可获取哦。

写文章不容易,不喜勿喷哈,如果有想要学编程,学项目,或者在工作中有项目难以单独完成需要提供帮助的同学,欢迎私信我哈。生活不易,想要利用学到的编程知识,业余赚点零花钱。

接项目:网站开发,APP开发,各种管理系统开发。

带徒弟:Python编程教学,Golang编程教学,前端编程教学。

谢谢您!!!


原文始发于微信公众号(张大鹏520):Django加Vue电商项目实战04 模型创建

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/48612.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!