Django基础核心技术之Model模型的介绍与设计
原创: Yunbo Shi Python Web与Django开发 2018-05-03
Django网络应用开发的5项基础核心技术包括模型(Model)的设计,URL的配置,View(视图)的编写,Template(模板)的设计和Form(表单)的使用。今天小编我就拼了老命来用千字长文给你来介绍下第一项Django核心基础知识之Model的设计吧。想持续了解后续Django Web开发技术请订阅我的公众号【Python与Django大咖之路】。

什么是Model模型?

Model (模型) 简而言之即数据模型。模型不是数据本身(比如数据库里的数据),而是抽象的描述数据的构成和逻辑关系。每个Django model实际上是个类,继承了models.Model。每个Model应该包括属性,关系(比如单对单,单对多和多对多)和方法。当你定义好Model模型后,Django的接口会自动帮你在数据库生成相应的数据表(table)。这样你就不用自己用SQL语言创建表格或在数据库里操作创建表格了,是不是很省心?

我们来看个书与出版社的实际案例。出版社有名字和地址。书有名字,描述和添加日期。当然我们还要利用ForeignKey定义出版社与书单对多的关系,因为一个出版社可以出版很多书。我们定义了如下模型,那你看看代码有问题吗?

models.py
from django.db import models

class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField()

def __str__(self):
return self.name
1
2
class Book(models.Model):
name = models.CharField(max_length=30)
description = models.TextField(blank=True, null=True)
publisher = ForeignKey(Publisher)
add_date = models.DateField()

def __str__(self):
return self.name
1
2
当你运行python manage.py migrate 创建表格的时候你会遇到错误,错误原因如下:

CharField里的max_length选项没有定义

ForeignKey(Publisher)里的on_delete选项有没有定义

所以当你定义Django模型Model的时候,你一定要十分清楚2件事:

这个Field是否有必选项, 比如CharField的max_length和ForeignKey的on_delete选项是必须要设置的。

这个Field是否必需(blank = True or False),是否可以为空 (null = True or False)。这关系到数据的完整性。

其实在上述案例中还有一个隐藏的错误,即TextField(blank = True, null = True)。blank = True 意味这个字段不是必需的,在客户端不是必填选项。null = True意味这个数据库里这个字段可以存储为null空值。但是Django对于空白的CharField和TextField永远不会存为null空值,而是存储空白字符串’’,所以正确的做法是设置default=’’。

下表才是一个比较正确的Django模型(Model)。

models.py
from django.db import models

class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=60)

def __str__(self):
return self.name
1
2
class Book(models.Model):
name = models.CharField(max_length=30)
description = models.TextField(blank=True, default=’’)
publisher = ForeignKey(Publisher, on_delete = models.CASCADE)
add_date = models.DateField()

def __str__(self):
return self.name
1
2
Django Model中字段(Field)的可选项和必选项

字段与选项(必选项为黄色标注)
CharField() 字符字段

max_length = xxx or None

如不是必填项,可设置blank = True和default = ‘’

如果用于username, 想使其唯一,可以设置unique = True

如果有choice选项,可以设置 choices = XXX_CHOICES

TextField() 文本字段

max_length = xxx

如不是必填项,可设置blank = True和default = ‘’

DateField() and DateTimeField() 日期与时间字段

一般建议设置默认日期default date.

For DateField: default=date.today - 先要from datetime import date

For DateTimeField: default=timezone.now - 先要from django.utils import timezone

对于上一次修改日期(last_modified date),可以设置: auto_now=True

EmailField() 邮件字段

如不是必填项,可设置blank = True和default = ‘’

一般Email用于用户名应该是唯一的,建议设置unique = True

IntegerField(), SlugField(), URLField(),BooleanField()

可以设置blank = True or null = True

对于BooleanField一般建议设置defautl = True or False

FileField(upload_to=None, max_length=100) - 文件字段

upload_to = “/some folder/”

max_length = xxxx

ImageField(upload_to=None, height_field=None, width_field=None, max_length=100,)

upload_to = “/some folder/”

其他选项是可选的.

ForeignKey(to, on_delete, **options) - 单对多关系

to必需指向其他模型,比如 Book or ‘self’ .

必需指定on_delete options(删除选项): i.e, “on_delete = models.CASCADE” or “on_delete = models.SET_NULL” .

可以设置"default = xxx" or “null = True” .

如果有必要,可以设置 "limit_choices_to = ",如下面例子。

staff_member = models.ForeignKey( User, on_delete=models.CASCADE, limit_choices_to={‘is_staff’: True}, )

可以设置 “related_name = xxx” 便于反向查询。

ManyToManyField(to, **options) - 多对多关系

to 必需指向其他模型,比如 User or ‘self’ .

设置 "symmetrical = False " if 多对多关系不是对称的

设置 "through = ‘intermediary model’ " 如果需要建立中间模型来搜集更多信息

可以设置 “related_name = xxx” 便于反向查询。

一个复杂点的Django Model模型

我们现在来看一个更复杂点的Django模型。假设我们要开发一个餐厅(restaurant)的在线点评网站,允许用户(user)上传菜肴(dish)的图片并点评餐厅,我们就可以设计如下模型。用户与餐厅,餐厅与菜肴,及用户与菜肴都是单对多的关系。我们可以这样理解:一个用户可以访问点评多个餐厅,一个餐厅有多个菜肴,一个用户可以上传多个菜肴的图片。

models.py
from django.db import models
from django.contrib.auth.models import User
from datetime import date

class Restaurant(models.Model):
name = models.TextField()
address = models.TextField(blank=True, default=’’)
telephone = models.TextField(blank=True, default=’’)
url = models.URLField(blank=True, null=True)
user = models.ForeignKey(User, default=1,on_delete=models.CASCADE)
date = models.DateField(default=date.today)

def __str__(self):
return self.nameclass Dish(models.Model):
name = models.TextField()
description = models.TextField(blank=True, default='')
price = models.DecimalField('USD amount', max_digits=8, decimal_places=2, blank=True, null=True)
user = models.ForeignKey(User, default=1, on_delete=models.CASCADE)
date = models.DateField(default=date.today)
image = models.ImageField(upload_to="myrestaurants", blank=True, null=True)
1
2
3
4
5
6
7
8
Related name “dishes” allows you to use restaurant.dishes.all to access all dishes objects
instead of using restaurant.dish_set.all
restaurant = models.ForeignKey(Restaurant, null=True, related_name='dishes', on_delete=models.CASCADE)

def __str__(self):
return self.name
1
2
3
4
This Abstract Review can be used to create RestaurantReview and DishReview
class Review(models.Model):
RATING_CHOICES = ((1, ‘one’), (2, ‘two’), (3, ‘three’), (4, ‘four’), (5, ‘five’))
rating = models.PositiveSmallIntegerField(‘Rating’, blank=False, default=3, choices=RATING_CHOICES)
comment = models.TextField(blank=True, null=True)
user = models.ForeignKey(User, default=1, on_delete=models.CASCADE)
date = models.DateField(default=date.today)

class Meta:
abstract = True
1
2
class RestaurantReview(Review):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)

def __str__(self):
return "{} review".format(self.restaurant.name)
1
2
你观察到Django模型设计里的细节了吗?

我们的Dish模型里有一个restaurant的字段,建立了一个单对多的关系。我们可以通过dish.restaurant.name直接查询到菜肴所属的餐厅的名字。然而我们Restaurant模型里并没有dish的字段,我们如何根据restaurant查询到某个餐厅的所有菜肴呢?Django非常聪明,可以通过在dish小写后面加上’_set’进行反向查询。我们本来可以直接通过restaurant.dish_set.all的方法来进行查找的,然而这个方法并不直观。为了解决这个问题,我们在dish模型里设置’related_name = dishes", 这样我们就可以直接通过restaurant.dishes.all来反向查询所有菜肴了。注意一但你设置了related name, 你将不能再通过_set方法来反向查询。

restaurant = models.ForeignKey(Restaurant, related_name=‘dishes’, on_delete=models.CASCADE)

第2个细节你需要关注的是Review模型里,我们设置了META选项: Abstract = True。这样一来Django就会认为这个模型是抽象类,而不会在数据库里创建review的数据表。实际上Model自带的META选项还有很多,都非常有用。见下文。

常见的Django Model META类选项

models.py
from django.db import models

class Meta:
# 按Priority降序, order_date升序排列.
get_latest_by = [’-priority’, ‘order_date’]
# 自定义数据库里表格的名字
db_table = ‘music_album’
# 按什么排序
ordering = [‘pub_date’]
# 定义APP的标签
app_label = ‘myapp’
# 声明此类是否为抽象
abstract = True
# 添加授权
permissions = ((“can_deliver_pizzas”, “Can deliver pizzas”),)

Django基础核心技术之Model模型的介绍与设计的更多相关文章

  1. django基础知识之定义模型:

    定义模型 在模型中定义属性,会生成表中的字段 django根据属性的类型确定以下信息: 当前选择的数据库支持字段的类型 渲染管理表单时使用的默认html控件 在管理站点最低限度的验证 django会为 ...

  2. Django 基础 路由系统

    Django框架简介 MVC框架和MTV框架(了解即可) MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图 ...

  3. SQLAlchemy 反向生成 model 模型

    前言 Django 反向生成的 model 模型的命令 :  python manager.py inspectdb SQLAlchemy / Flask-SQLAlchemy则是: pip3 ins ...

  4. Django基础五之Ajax

    Django基础五之Ajax 目录 Django基础五之Ajax 1. Ajax介绍 2. Ajax前后端传值 2.1 方法一HttpResponse直接返回 2.2 方法二使用Json格式返回 2. ...

  5. {Django基础十之Form和ModelForm组件}一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 ModelForm

    Django基础十之Form和ModelForm组件 本节目录 一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 Model ...

  6. Django基础之MTV模型

    一.Django基础 一.Django简介 Django是一个开放源代码的Web应用框架,由Python写成.采用了MVC的软件设计模式,即模型(Model).视图(View)和控制器(Control ...

  7. day 69 Django基础五之django模型层(一)单表操作

    Django基础五之django模型层(一)单表操作   本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现 ...

  8. day 55 Django基础五之django模型层(一)单表操作

      Django基础五之django模型层(一)单表操作   本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它 ...

  9. Django基础四(model和数据库)

    上一篇博文学习了Django的form和template.到目前为止,我们所涉及的内容都是怎么利用Django在浏览器页面上显示内容.WEB开发除了数据的显示之外,还有数据的存储,本文的内容就是如何在 ...

随机推荐

  1. UML——用例图

    用例图是在需求分析阶段开发人员和用户对需求规格达成的某种共识.它描写叙述了待开发系统的功能需求. UML视频使我们对用例图的基本组成元素.属性.粒度等有了理论上的理解,我们还须要自己亲自己主动手画一画 ...

  2. JSP页面怎样导入优酷视频

    我在做的一个项目里面,应客户要求.要导入视频.然后我再考虑,视频是直接放在本地数据库的话,那么肯定会出现数据视频读取反应慢. 那么,就能够把视频先传到优酷上面,然后再直接应用优酷视频上的html代码, ...

  3. appium desktop

    Appium-desktop 下载地址:https://github.com/appium/appium-desktop/releases 一般功能 这些能力跨越多个驱动因素. 仅限Android 这 ...

  4. XML(一)语法

    一.xml语法 1.文档声明 2.元素 3.属性 4.凝视 5.CDATA区.转义字符 6.处理指令 1.文档声明: 用来声明xml的基本属性,用来指挥解析引擎怎样去解析当前xml 通常一个xml都要 ...

  5. Cocos2d-X开发中国象棋《四》设计游戏场景

    设计完開始界面后就要设计游戏界面了 为了理清设计思路先看一张游戏界面效果图 游戏界面设计思路: 1.在窗体上放一张桌子 2.在桌子上放一个棋盘 3.在棋盘右边加入新局button,暂不实现详细的功能 ...

  6. android.app.Fragment与android.support.v4.app.Fragment不一致

    在看法中用到的Fragment在类型转换的时候非常easy出现这样的问题: 对照代码: class MyFragmentPagerAdapter extends FragmentPagerAdapte ...

  7. extern "C" 的含义:实现C++与C及其他语言的混合编程

    C++中extern "C"的设立动机是实现C++与C及其他语言的混合编程.        C++为了支持函数的重载,C++对全局函数的处理方式与C有明显的不同.对于函数void ...

  8. Google's Hybrid Approach to Research

    文档地址:戳我 总结: (i) aims to generate scientific and engineering advances in fields of import to Google, ...

  9. 【高德地图API】SDK v1.1.1 在代码中设置Map中心点Center级别不起作用

    有时候你在初始化地图时不是直接在xaml中设置Map的Center,而是在cs代码中设置Center或者设置SetZoomAndCenter改变中心点和缩放级别.你可能会发现,不起作用. 这边提出的解 ...

  10. JS浮点数精度运算

    一般来讲,我们在项目中必不可少的需要进行各种数值的计算,但是这种计算全部放在服务端会给服务器带来很大的压力,所以势必要客户端来 分担一些计算的压力. 从客户端来说,JavaScript是一门弱类型语言 ...