实现需要了解一下什么是模型,上一节已经建立过一个在models.py里的模型了,模型在django中是一个类,通过ORM是指对象关系模型,使用模型的好处是不需要自己去写原生的sql语句,django会根据你的数据库生成对应的sql并生成响应的表,因此可移植性高。下面是一个简单的例子。
在app/models.py写入内容如下
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
在pycharm中执行迁移
python manage.py makemigrations
python manage.py migrate
数据库中查询
mysql> show tables;
+----------------------------+
| Tables_in_web |
+----------------------------+
| app_person |
| app_user |
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
12 rows in set (0.00 sec)
mysql> describe app_person;
+------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| first_name | varchar(30) | NO | | NULL | |
| last_name | varchar(30) | NO | | NULL | |
+------------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
生成了一个表 app_person,查看表的字段,是由三个字段,id first_name last_name,这里后两个字段是我们自己创建的,第一个字段是自动生成的表示主键,因此如果我们不特殊指定主键会自动生成一个名为id的主键,自动创建的字段如果不特殊指定名字为创建类的字段名,当然我们也可以指定字段名。下面来介绍。
from django.db import models
class Person(models.Model):
first_name = models.CharField(db_column='first',max_length=30)
last_name = models.CharField(db_column='last',max_length=30)
mysql> describe app_person;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| first | varchar(30) | NO | | NULL | |
| last | varchar(30) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
null
blank
default
primary_key
unique
可指定null=true表示可以不插入值是与数据有关的,blank=true表示可以在验证表单时表单为空,但是插入数据必须有值。
例子:
class Person(models.Model):
first_name = models.CharField(db_column='first',max_length=30,null=True)
last_name = models.CharField(db_column='last',max_length=30,blank=True)
mysql> describe app_person;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| first | varchar(30) | YES | | NULL | |
| last | varchar(30) | NO | | NULL | |
mysql> insert into app_person(last) values('sun');
Query OK, 1 row affected (0.01 sec)
可以看到first可以不插入值,
default字段可以指定一个字段的默认值,有了默认值如果不插入字段可以使用默认的值而不会出错。
primary_key=True表示指定一个字段为主键,自己指定主键后,django便不会自动生成主键,指定
id = models.AutoField(primary_key=True)和django默认生成的时一样的
unique指定一个字段为唯一的,如果插入重复的值会报错
三种关系模型:
一对一
多对一
多对多
一对一:这种关系模型很常用,比如在当想要扩充一个表但是不想修改一个表结构时可以创建一个新的表,使用一对一的关系关联起来,这种关系可以一对一的将表关联起来,下面是一个例子,有两个表用户表和电话号码表,假设一个人有一个电话号码,一个电话只能属于一个人。
为了防止数据库表重名将web数据库和migrations下的迁移记录删除,重新创建。
from django.db import models
# Create your models here.
class Phone_Number(models.Model):
number=models.CharField(max_length=11)
register_data=models.DateTimeField(auto_now_add=True)
class User(models.Model):
username=models.CharField(max_length=20)
address=models.CharField(max_length=100)
phone=models.OneToOneField(Phone_Number,on_delete=models.CASCADE)
执行迁移
现在介绍一个工具django的shell工具
在命令行里输入python manage.py shell便可进入django的shell环境。然后将模型里面的类导入
(venv) C:\Users\Administrator\PycharmProjects\webproject\web>python manage.py shell
Python 3.8.3 (tags/v3.8.3:6f8c832, May 13 2020, 22:20:19) [MSC v.1925 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from app.models import Phone_Number,User 导入类
>>> phone=Phone_Number() 创建一个phone类对象
>>> user=User() 创建一个user类对象
>>> phone.number='1324456763' 给对象赋值
>>> phone.save() 将phone对象的内容更新到数据库 这一步才会将phone更新到数据库
>>> user.username='sun'
>>> user.address='china'
>>> user.phone=phone
>>> user.save()
>>>
来看看我们的数据库
mysql> select * from app_user;
+----+----------+---------+----------+
| id | username | address | phone_id |
+----+----------+---------+----------+
| 1 | sun | china | 1 |
+----+----------+---------+----------+
1 row in set (0.00 sec)
mysql> describe app_user;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| username | varchar(20) | NO | | NULL | |
| address | varchar(100) | NO | | NULL | |
| phone_id | int | NO | UNI | NULL | |
+----------+--------------+------+-----+---------+----------------+
mysql> select * from app_phone_number;
+----+------------+----------------------------+
| id | number | register_data |
+----+------------+----------------------------+
| 1 | 1324456763 | 2020-05-30 02:28:49.513789 |
+----+------------+----------------------------+
1 row in set (0.00 sec)
看app_user表结构 phone_id是我们创建的一对一关系的外键 约束时unique的 因此当我们再次绑定一个数据会报错
mysql> insert into app_user(username,address,phone_id) values('zhang','china',1);
ERROR 1062 (23000): Duplicate entry '1' for key 'app_user.phone_id'
多对一:多对一关系比较常用,下面举一个例子,班级学生,一个班级有多个学生,每个学生只属于一个班级
class Class(models.Model):
num=models.CharField(max_length=10)
count=models.IntegerField()
class Student(models.Model):
name = models.CharField(max_length=10)
age = models.IntegerField()
clsss = models.ForeignKey(Class,on_delete=models.CASCADE)
多对多:
class Student(models.Model):
name = models.CharField(max_length=10)
age = models.IntegerField()
clsss = models.ForeignKey(Class,on_delete=models.CASCADE)
class Course(models.Model):
name = models.CharField(max_length=20)
grade_point = models.IntegerField()
class SC(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE, related_name='student')
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='course')
grade = models.IntegerField()