python---django中orm的使用(4)字段,參數(on_delete重點)補充,一對多,一對一,多對多


1.索引:

普通索引:加快查找速度

唯一索引:加快查找速度,唯一約束

主鍵索引:加快查找速度,唯一索引,不為空

class UserInfo(models.Model):

    username = models.CharField(
        null=False,     #不允許為空
        db_column='user', #自定義列名,可以修改再數據庫中的列名
        max_length=32,
        db_index=True,  #普通索引,只能加速查找
        # unique=True,    #約束索引,加速查找,唯一約束
        # primary=True,   #主鍵索引,加速查找,唯一約束,不為空
    )
    gender = models.BooleanField(
        default=True    #設置默認值
    )

元類使用:

用於生成聯合索引,以及設置個別參數

    #元類信息
    class Meta:
        # 數據庫中生成的表名稱 默認 app名稱 + 下划線 + 類名
        db_table = "app01_un"
        # 聯合索引
        # index_together = [
        #     ("username", "gender"),
        # ]
        # 聯合唯一索引
        unique_together = (("username", "gender"),)
        #IntegrityError: columns user, gender are not unique
        # admin中顯示的表名稱
        verbose_name = "用戶信息"

2.一對多外鍵建立:

    el = models.ForeignKey(
        to="EmailInfo", #關聯表
        to_field='id',  #關聯列名
db_constraint=True #是否在數據庫該表中創建外鍵約束(外鍵功能查找等依舊存在,但是不具有約束功能) 比如:有約束時,郵箱id1-10,那么在該表中el也會是1-10,但是當false時,該el設置可以是任意,不受關聯表的約束
     limit_choices_to=None, #在Admin或者ModelForm中顯示數據時,提供限制后的數據展示
          --limit_choices_to={'id_gt':5}
          --limit_choices_to=lambda:{'id_gt':5}#或者lambda表達式 )
class EmailInfo(models.Model):
    email = models.EmailField(
        null=False,
        db_index=True,
        unique=True,
    )
外鍵關聯表EmailInfo

添加信息:

    #添加信息
    UserInfo.objects.create(
        username="張三",
        gender=True,
        el_id=1
    )
    UserInfo.objects.create(
        username="李四",
        gender=True,
        el_id=2
    )
  #因為唯一約束,是對姓名,性別一起約束,所以當不同時,是可以進行添加的 UserInfo.objects.create( username
="王五", gender=False, el_id=3 ) UserInfo.objects.create( username="王五", gender=True, el_id=3 ) UserInfo.objects.create( username="趙六", gender=True, el_id=4 ) EmailInfo.objects.create(**{'email': '46412454@qq.com'}) EmailInfo.objects.create(**{'email': '4641245454@qq.com'}) EmailInfo.objects.create(**{'email': '46412fwa454@qq.com'})

對於外鍵,刪除是是默認為級聯刪除,當刪除一個,對應相關數據也會被刪除,所以,我們有時候需要修改這一性質,在創建外鍵是使用on_delete即可

對於on_delete的幾種設置:

def set_test():
    return 4
    el = models.ForeignKey(
        to="EmailInfo", #關聯表
        to_field='id',  #關聯列名
        null=True,
        default=2,
        #刪除自己數據,對於被關聯方,一點影響都沒有

        #on_delete=None, #當關聯的email數據被刪除時候,該數據也會被刪除,不存在
        #on_delete=models.CASCADE, #性質和None一樣是默認刪除
#on_delete
=models.DO_NOTHING, #當關聯的數據被刪除時,自己不受影響,什么事都不做,不會報錯
#on_delete
=models.PROTECT, #關聯保護,因為郵箱數據被用戶表關聯,所以該郵箱不允許被刪除,並且觸發ProtectError #Cannot delete some instances of model 'EmailInfo' because they are referenced through a protected foreign key: 'UserInfo.el'", <QuerySet [<UserInfo: UserInfo object>]>
#on_delete=models.SET_NULL, #刪除關聯數據,自己被設置為null(前提字段需要設置為可空null=True) #對於測試models.SET_NULL時,我們需要先了解,對於數據庫的基本字段設置,像null,max_length這些屬性,我們需要重新去生成數據表, #對於on_delete等Django中的附屬屬性,我們可以動態修改,不需要重新生成數據表,所以如果我們開始並沒有設置null=True(默認false),我們需要去重新生成數據表 #on_delete=models.SET_DEFAULT,#刪除關聯數據后,會將自己的數據設置為默認值,需要設置default屬性
#on_delete
=models.SET(3) #和SET_DEFAULT相似,只不過不需要設置默認值,在SET()中可以直接設置 on_delete=models.SET(set_test) #和SET一樣,只不過值設為了回調函數,需要將函數設為全局,可調用 )

 3.一對一:與一對多外鍵屬性幾乎一致,只是在unique上多加了true。兩種實現:o和o1

class User(models.Model):
    username = models.CharField(
        max_length=32,
        db_index=True,
    )

class Tag(models.Model):
    title = models.CharField(
        max_length=16,
    )

    o = models.OneToOneField(
        to='User',
        to_field='id',
        on_delete=None,
        ###### 對於一對一 ###### # 1. 一對一其實就是 一對多 + 唯一索引
        # 2.當兩個類之間有繼承關系時,默認會創建一個一對一字段 # 如下會在A表中額外增加一個c_ptr_id列且唯一:
    )
    o1 = models.ForeignKey(
        to='User',
        to_field='id',
        on_delete=None,
        unique=True,
    )

4.多對多ManyToManyField

class User(models.Model):
    username = models.CharField(
        max_length=32,
        db_index=True,
    )

    def __str__(self):
        return self.username

class Tag(models.Model):
    title = models.CharField(
        max_length=16,
    )

    # m = models.ManyToManyField(to="User")
    # 使用ManyToManyField只能在第三張表中創建3列數據id(主鍵自增),外鍵1_id,外鍵2_id
    # m = models.ManyToManyField(
    #     to="User",
    #     related_name="tag", #反向查詢是設置的字段名,替換(表名_set)默認是表名_set,這里設置后就可以簡化了
    #     related_query_name="tg",  #反向查詢是用於替換(表名)
    #     limit_choices_to=None,  #在admin中或者modelform中進行限制字段
    #     db_constraint=True   #同外鍵約束一致
    # )

    def __str__(self):
        return self.title

自定義第三張表(查詢方便):

#自定義第三張表
class UserToTag(models.Model):
    nid = models.AutoField(
        primary_key=True
    )

    u = models.ForeignKey(to="User")
    t = models.ForeignKey(to="Tag")

    ctime = models.DateField()

    #ManyToManyField中含有聯合唯一
    class Meta:
        #聯合唯一
        unique_together=[
            ('u', 't'),
        ]

 補充:through,through_fields.

django除了能自動創建多對多的第三張表,同樣也可以自定義創建多對多的第三張表,而且操作和管理擴展等難易程度要比自動創建的好許多。所以,在之后的models表結構中,推薦使用自定義的方式。並且加上through和through_fields

class User(models.Model):
    username = models.CharField(
        max_length=32,
        db_index=True
    )class Tag(models.Model):
    title = models.CharField(
        max_length=32,
        db_index=True,
    )

    members = models.ManyToManyField(    
        User,
        through='UserToTag',
        through_fields=('u','t'), )
class UserToTag(models.Model):
    u = models.ForeignKey(
        User,
        on_delete=models.CASCADE
    )

    t = models.ForeignKey(
        Tag,
        on_delete=models.CASCADE
    )

操作:

    models.UserToTag.objects.create(
        u=models.User.objects.get(id=1),
        t=models.Tag.objects.get(id=2)
    )

其他添加方法看:python---django中orm的使用(1)

5.多對多---自查詢:

class User(models.Model):
    username = models.CharField(
        max_length=32,
        db_index=True
    )
    # 自關聯(互粉操作),反向操作容易亂(各個表對他的反向操作都是User_set),最好加上related_name,以后最好都加上related_name
    # d = models.ManyToManyField("User",related_name='b')

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM