X Tutup
Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

README.md

Tutorial 5 進階 models

下面將會介紹models
Fields
Options
Relationships
class Meta
def __str__(self):

Fields

每個modelsField分別對應到不同的資料庫欄位型態
這裡會介紹以下幾種Fields,沒介紹的應該用不太到,請自行參考官方文件
文字類型:CharFieldTextFieldEmailField
整數類型:IntegerFieldBigIntegerFieldPositiveIntegerFieldPositiveSmallIntegerField
小數類型:FloatFieldFloatField
日期類型:DateFieldDateTimeField
布林類型:BooleanFieldNullBooleanField

文字類型

  1. CharField

name = models.CharField(max_length=255)
字元字串欄位,max_length是必要的參數,Django文件建議上限為255,實測結果為長度取決於資料庫上限。

  1. TextField

description = models.TextField()
為一個文字框輸入欄位,Django文件建議CharField長度超過255則使用此類型,可以加上max_length參數,但只作用在client端,modeldatabase不起作用。

  1. EmailField

email = models.EmailField()
電子郵件欄位,若不給參數,預設參數為max_length=254

整數類型

  1. IntegerField

num = models.IntegerField()
整數類型欄位,值的範圍為-21474836482147483647

  1. BigIntegerField

num = models.BigIntegerField() 64位元整數欄位,值的範圍為-92233720368547758089223372036854775807

  1. PositiveIntegerField

num = models.PositiveIntegerField()
正整數欄位,值的範圍為02147483647

  1. PositiveSmallIntegerField

num = models.PositiveSmallIntegerField()
小正整數欄位,值的範圍為032767

小數類型

  1. FloatField

num = models.FloatField()
浮點數欄位,因為精度問題,在數字計算上可能會有誤差。

  1. DecimalField

models.DecimalField(max_digits=10, decimal_places=3)
十進制欄位,通常使用在計算不可有誤差的地方,如:金額。
需要max_digitsdecimal_places這2個參數。
max_digits表示此欄位允許的最大位數
decimal_places表示使用幾個位數顯示小數部分
12345.67有7位數,小數部分2位數
models.DecimalField(max_digits=7, decimal_places=2)

日期類型

  1. DateField

date = models.DateField()
使用pythondatetime.date為實例來表示年-月-日

  1. DateTimeField

time = models.DateTimeField()
使用pythondatetime.datetime為實例來表示年-月-日 時:分:秒
2個日期類型都有auto_nowauto_now_add2個可選參數,預設皆為False

若設定參數auto_now=True,日期會在資料被新增時自動加入當下的日期時間(新增時指定日期時間無效),新增後只有在每次使用object.save()才會更新日期時間,常常使用在最後編輯的時間。

若設定參數auto_now_add=True,日期會在資料被新增時自動加入當下的日期時間(新增時指定日期時間無效),新增後可隨意修改日期時間,通常用在記錄資料建立的時間。

布林類型

  1. BooleanField

check = models.BooleanField()
只有truefalse的資料型態,預設為false,如果需要接受null,改用NullBooleanField

  1. NullBooleanField

check = models.NullBooleanField()
接受truefalsenull3種資料型態,預設為null,使用此類型,會自動設定null=True參數。

Options

上面介紹的每個Field,除了指定要給的參數為,還有一些參數可供選擇,這裡會介紹以下參數
null
blank
choices
default
help_text
primary_key
unique
verbose_name

null

name = models.CharField(max_length=10, null=False)
若不指定此參數,預設值為null=False,若設定成null=True,此欄位可允許存入null值。

blank

name = models.CharField(max_length=10, blank=False)
若不指定此參數,預設值為blank=False,若設定成blank=True,此欄位可允許存入空白值。

choices

test

default

name = models.CharField(max_length=10, default='value')
設定default參數,可指定此欄位預設值為何
default='低否'表示此Char欄位預設值為低否

help_text

name = models.CHarField(max_length=20, help_text='This is help text.'
當此欄位使用在form表單時,給予輸入的幫助訊息。

primary_key

id = models.PositiveIntegerField(primary_key=False)
primary_key參數指定此欄位為table的主鍵,通常不需額外指定此欄位,Django會自動新增一個AutoField型態的id欄位給table當主鍵。

name = models.CHarField(max_length=10, primary_key=True)
如果自行指定其他欄位為primary_key,此欄位會自動增加null=Falseunique=True這2個參數。

一張table只允許一個primary_key

unique

phone = models.PositiveIntegerField(unique=False)
unique參數預設為False,如果設定unique=True,表示此欄位所存放的值不可與其他欄位重複。

除了OneToOneFieldManyToManyField之外,其他Field皆可使用此參數。

verbose_name

此參數可以給予欄位一個暱稱來顯示,若不指定此參數,Django會將欄位名稱的字首英文字母大寫,並將底線轉為空格。

下面例子會以First name來顯示
first_name = models.CharField(max_length=10)

下面例子會以Lastname來顯示
last_name = models.CHarField(max_length=10, verbose_name='lastname')

下面例子會以NICK_NAME來顯示,使用此方法,必將顯示名稱放在最前端,才可不輸入verbose_name
nick_name = models.CharField('NICK_NAME', max_length=10)

Relationships

Djangomodels也支援了關聯式資料庫的ForeignKeyManyToOneOneToOneManyTOMany

ForeignKey and ManyToOne

relation = models.ForeignKey(relate_model_name, on_delete=models.CASCADE)
Django使用ForeignKey來表示ManyToOne關聯,需要給予2個參數:關聯至哪一個model及當關聯的model刪除時要進行的動作。

假設有2張表,1張記錄城市名稱,1張記錄城市居民,關聯如下圖

graph LR
B[Citizen] --> A[City]
C[Citizen] --> A[City]
D[Citizen] --> A[City]
Loading

城市的model如下

class City(models.Model)
	name = models.CharField(max_length=10)
    
    def __str__(self):
    	return self.name

居民的model如下

class Citizen(models.Model)
	relate_city = models.ForeignKey(City, on_delete=models.CASCADE)
	name = models.CharField(max_length=10)
    age = models.PositiveIntegerField()
    
    def __str__(self):
    	return self.name

Citizenrelate_city欄位使用ForeignKey來表示關聯至哪一個model,第一個參數City代表關聯至City這個model,第二個參數on_delete=models.CASCADE代表當關聯的City被刪除時,Citizen也會一起被刪除。

on_delete這個參數有以下幾種用法:

on_delete=models.CASCADE
刪除City時,同時將所有關聯至CityCitizen刪除

on_delete=models.PROTECT
需先將Citizen全部刪除,才可刪除City

on_delete=models.SET_NULL
City被刪除時,Citizenrelate_city欄位會變成null,需另外設定null=True

on_delete=models.SET_DEFAULT
需另外設定default參數,當所關聯的City被刪除時,自動將此欄位關聯至default指定的關聯表主鍵。

假設今天有下列2張表,Citizenrelate_city設定為relate_city = models.ForeignKey(City, on_delete=models.SET_DEFAULT, default=0)
根據Citizen可得知阿哲住在台北市,阿倫阿燦住在新北市,阿龍阿德阿花住在桃園市。
City| -----|-------- id(pk)|0|1|2 name|台北市|新北市|桃園市

Citizen| ---|--- id(pk)|0|1|2|3|4|5 relate_city|0|1|1|2|2|2 name|阿哲|阿倫|阿燦|阿龍|阿德|阿花 age|58|57|51|54|58|68

如果把City的桃園市刪除,阿龍阿德阿花將無家可歸,還好我們設定了default=0阿龍阿德阿花在桃園市被刪除後,都會搬到台北市居住,變成下表
City| -----|-------- id|0|1 name|台北市|新北市

Citizen| ---|--- id|0|1|2|3|4|5 relate_city|0|1|1|0|0|0 name|阿哲|阿倫|阿燦|阿龍|阿德|阿花 age|58|57|51|54|58|68 注意,因為台北市被指定為default,所以台北市不可被刪除

on_delete=models.SET()
關聯的資料被刪除時,呼叫SET()內的函式,回傳另外一個關聯物件
例如設定relate_city = models.ForeignKey(City, on_delete=models.SET(get_first_city)
並且有一個函式如下


on_delete=models.DO_NOTHING

OneToOne

relation = models.OneToOneField(relate_model_name, on_delete=models.CASCADE)
資料庫中的一對一關係,與ForeignKey加上unique相似,差別在於反向關係時,OneToOne回傳一個物件,而ForeignKey加上unique會回傳queryset

如果CityCitizenForeignKey關係,UserUserProfileOneToOne關係,程式碼如下:

class City(models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return self.name

class Citizen(models.Model):
    relate_city = models.ForeignKey(City, on_delete=models.CASCADE)
    name = models.CharField(max_length=20)
    age = models.PositiveIntegerField()

    def __str__(self):
        return self.name


class User(models.Model):
    uid = models.CharField(max_length=10)

    def __str__(self):
        return self.uid

class UserProfile(models.Model):
    relate_user = models.OneToOneField(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=20)
    age = models.PositiveIntegerField()

    def __str__(self):
        return self.name

command line輸入python manage.py shell進入shell互動模式

>>> from app import models
>>> city = models.City.objects.get(name='Taipei')
>>> citizen = models.Citizen.objects.get(name='ironman')
>>> user = models.User.objects.get(uid='A123456789')
>>> userprofile = models.UserProfile.objects.get(name='superman')
>>> city.citizen_set.all()
<QuerySet [<Citizen: ironman>]>
>>> user.userprofile
<UserProfile: superman>

ManyToMany

To be continue...

class Meta

下方的程式碼會使Testadmin後台以TEST來顯示

class Test(models.Model):
	name = models.CharField(max_length=20)
    
    class Meta:
    	verbose_name = "TEST"
    
    def __str__(self):
    	return self.name

def __str__(self)

class Test(models.Model):
	name = models.CharField(max_length=20)
    
    def __str__(self):
    	return self.name
X Tutup