Django基础核心技术之Model模型的介绍与设计
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”),)
轉載于:https://www.cnblogs.com/ly570/p/10992439.html
總結
以上是生活随笔為你收集整理的Django基础核心技术之Model模型的介绍与设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原生js实现JSON.parse()和J
- 下一篇: 牛客OI测试赛1