Model模型(上)
Posted bijian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Model模型(上)相关的知识,希望对你有一定的参考价值。
一、什么是Model模型?
Model (模型) 简而言之即数据模型。模型不是数据本身(比如数据库里的数据),而是抽象的描述数据的构成和逻辑关系。每个Django model实际上是个类,继承了models.Model。每个Model应该包括属性,关系(比如单对单,单对多和多对多)和方法。当你定义好Model模型后,Django的接口会自动帮你在数据库生成相应的数据表(table)。
二、Django Model中字段(Field)的可选项和必选项(字段与选项,必选项为加粗)
1、CharField() 字符字段
-
max_length = xxx or None
-
如不是必填项,可设置blank = True和default = ‘‘
-
如果用于username, 想使其唯一,可以设置unique = True
-
如果有choice选项,可以设置 choices = XXX_CHOICES
2、TextField() 文本字段
-
max_length = xxx
-
如不是必填项,可设置blank = True和default = ‘‘
3、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
4、EmailField() 邮件字段
-
如不是必填项,可设置blank = True和default = ‘‘
-
一般Email用于用户名应该是唯一的,建议设置unique = True
5、IntegerField(), SlugField(), URLField(),BooleanField()
-
可以设置blank = True or null = True
-
对于BooleanField一般建议设置defautl = True or False
6、FileField(upload_to=None, max_length=100) - 文件字段
-
upload_to = "/some folder/"
-
max_length = xxxx
7、ImageField(upload_to=None, height_field=None, width_field=None, max_length=100,)
-
upload_to = "/some folder/"
-
其他选项是可选的.
8、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" 便于反向查询。
9、ManyToManyField(to, **options) - 多对多关系
-
to 必需指向其他模型,比如 User or ‘self‘ .
-
设置 "symmetrical = False " if 多对多关系不是对称的
-
设置 "through = ‘intermediary model‘ " 如果需要建立中间模型来搜集更多信息
-
可以设置 "related_name = xxx" 便于反向查询。
三、常见的Django Model META类选项
models.py
from django.db import models # Create your models here. 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"),)
四、举例
1、出版社有名字和地址。书有名字,描述和添加日期。利用ForeignKey定义出版社与书单对多的关系,因为一个出版社可以出版很多书。
from django.db import models # Create your models here. class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=60) def __str__(self): return self.name class Book(models.Model): name = models.CharField(max_length=30) description = models.TextField(blank=True, default=‘‘) publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) add_date = models.DateField() def __str__(self): return self.name
定义Django模型Model的时候注意:
-
这个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=‘‘。
2、(复杂)假设要开发一个餐厅(restaurant)的在线点评网站,允许用户(user)上传菜肴(dish)的图片并点评餐厅,就可以设计如下模型。用户与餐厅,餐厅与菜肴,及用户与菜肴都是单对多的关系。可以这样理解:一个用户可以访问点评多个餐厅,一个餐厅有多个菜肴,一个用户可以上传多个菜肴的图片。
from django.db import models from django.contrib.auth.models import User from datetime import date # Create your models here. 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.name class 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) # 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 # 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 class RestaurantReview(Review): restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE) def __str__(self): return "{} review".format(self.restaurant.name)
注:(1) 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选项还有很多,都非常有用。
以上是关于Model模型(上)的主要内容,如果未能解决你的问题,请参考以下文章
如何将 List<Model> 从 Activity 传递到 Fragment
Cg入门19:Fragment shader - 片段级模型动态变色