Django中models字段含義、用法

Model

一、model基本結構

1.字段名稱、含義


AutoField(Field)
    # int自增列,必須填入參數 primary_key=True

BigAutoField(AutoField)
    # bigint自增列,必須填入參數 primary_key=True

    注:當model中如果沒有自增列,則自動會創建一個列名爲id的列
    from django.db import models

    class UserInfo(models.Model):
        # 自動創建一個列名爲id的且爲自增的整數列
        username = models.CharField(max_length=32)

    class Group(models.Model):
        # 自定義自增列
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)

SmallIntegerField(IntegerField):
    # 小整數 -32768 ~ 32767

PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
    # 正小整數 0 ~ 32767
IntegerField(Field)
    # 整數列(有符號的) -2147483648 ~ 2147483647

PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
    # 正整數 0 ~ 2147483647

BigIntegerField(IntegerField):
    # 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807

自定義無符號整數字段

    class UnsignedIntegerField(models.IntegerField):
        def db_type(self, connection):
            return 'integer UNSIGNED'

    PS: 返回值爲字段在數據庫中的屬性,Django字段默認的值爲:
        'AutoField': 'integer AUTO_INCREMENT',
        'BigAutoField': 'bigint AUTO_INCREMENT',
        'BinaryField': 'longblob',
        'BooleanField': 'bool',
        'CharField': 'varchar(%(max_length)s)',
        'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
        'DateField': 'date',
        'DateTimeField': 'datetime',
        'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
        'DurationField': 'bigint',
        'FileField': 'varchar(%(max_length)s)',
        'FilePathField': 'varchar(%(max_length)s)',
        'FloatField': 'double precision',
        'IntegerField': 'integer',
        'BigIntegerField': 'bigint',
        'IPAddressField': 'char(15)',
        'GenericIPAddressField': 'char(39)',
        'NullBooleanField': 'bool',
        'OneToOneField': 'integer',
        'PositiveIntegerField': 'integer UNSIGNED',
        'PositiveSmallIntegerField': 'smallint UNSIGNED',
        'SlugField': 'varchar(%(max_length)s)',
        'SmallIntegerField': 'smallint',
        'TextField': 'longtext',
        'TimeField': 'time',
        'UUIDField': 'char(32)',

BooleanField(Field)
    # 布爾值類型

NullBooleanField(Field):
    # 可以爲空的布爾值

CharField(Field)
    # 字符類型
    # 必須提供max_length參數, max_length表示字符長度

TextField(Field)
    # 文本類型

EmailField(CharField)# 字符串類型,Django Admin以及ModelForm中提供驗證機制

IPAddressField(Field)
    # 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制

GenericIPAddressField(Field)
    # 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6
    # 參數:
        protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
        unpack_ipv4, 如果指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓刺功能,需要protocol="both"

URLField(CharField)
    # 字符串類型,Django Admin以及ModelForm中提供驗證 URL

SlugField(CharField)
    # 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、連接符(減號)

CommaSeparatedIntegerField(CharField)
    # 字符串類型,格式必須爲逗號分割的數字

UUIDField(Field)
    # 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證

FilePathField(Field)
    # 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能
    # 參數:
            path,                      文件夾路徑
            match=None,                正則匹配
            recursive=False,           遞歸下面的文件夾
            allow_files=True,          允許文件
            allow_folders=False,       允許文件夾

FileField(Field)
    # 字符串,路徑保存在數據庫,文件上傳到指定目錄
    # 參數:
        upload_to = ""      上傳文件的保存路徑
        storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage

ImageField(FileField)
    # 字符串,路徑保存在數據庫,文件上傳到指定目錄
    # 參數:
        upload_to = ""      上傳文件的保存路徑
        storage = None      存儲組件,默認django.core.files.storage.FileSystemStorage
        width_field=None,   上傳圖片的高度保存的數據庫字段名(字符串)
        height_field=None   上傳圖片的寬度保存的數據庫字段名(字符串)

DateTimeField(DateField)
    # 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

DateField(DateTimeCheckMixin, Field)
    # 日期格式      YYYY-MM-DD

TimeField(DateTimeCheckMixin, Field)
    # 時間格式      HH:MM[:ss[.uuuuuu]]

DurationField(Field)
    # 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型

FloatField(Field)
    # 浮點型

DecimalField(Field)
    # 10進制小數
    # 參數:
        max_digits,小數總長度
        decimal_places,小數位長度

BinaryField(Field)
    # 二進制類型

字段

2.參數含義

null                數據庫中字段是否可以爲空
db_column           數據庫中字段的列名
db_tablespace
default             數據庫中字段的默認值
primary_key         數據庫中字段是否爲主鍵
db_index            數據庫中字段是否可以建立索引
unique              數據庫中字段是否可以建立唯一索引
unique_for_date     數據庫中字段【日期】部分是否可以建立唯一索引
unique_for_month    數據庫中字段【月】部分是否可以建立唯一索引
unique_for_year     數據庫中字段【年】部分是否可以建立唯一索引

verbose_name        Admin中顯示的字段名稱
blank               Admin中是否允許用戶輸入爲空
editable            Admin中是否可以編輯
help_text           Admin中該字段的提示信息
choices             Admin中顯示選擇框的內容,用不變動的數據放在內存中從而避免跨表操作
                    如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)

error_messages      自定義錯誤信息(字典類型),從而定製想要顯示的錯誤信息;
                    字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
                    如:{'null': "不能爲空.", 'invalid': '格式錯誤'}

validators          自定義錯誤驗證(列表類型),從而定製想要的驗證規則
                    from django.core.validators import RegexValidator
                    from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
                    MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
                    如:
                        test = models.CharField(
                            max_length=32,
                            error_messages={
                                'c1': '優先錯信息1',
                                'c2': '優先錯信息2',
                                'c3': '優先錯信息3',
                            },
                            validators=[
                                RegexValidator(regex='root_\d+', message='錯誤了', code='c1'),
                                RegexValidator(regex='root_112233\d+', message='又錯誤了', code='c2'),
                                EmailValidator(message='又錯誤了', code='c3'), ]
                        )

3.元信息Meta(干預數據庫建表名等操作)

class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        class Meta:
            # 數據庫中生成的表名稱 默認 app名稱 + 下劃線 + 類名
            db_table = "table_name"

            # 聯合索引
            index_together = [
                ("pub_date", "deadline"),
            ]

            # 聯合唯一索引
            unique_together = (("driver", "restaurant"),)

            # 後臺管理界面,admin中顯示的表名稱
            verbose_name

            # verbose_name加s   (複數顯示)
            verbose_name_plural
        
    更多:https://docs.djangoproject.com/en/1.10/ref/models/options/

4.擴展

  • 鉤子函數,觸發model驗證,錯誤提示
  • form驗證(error_messages不是一定非得定義,框架自帶的信息也足夠判斷。)
1.觸發Model中的驗證和錯誤提示有兩種方式:
    a. Django Admin中的錯誤信息會優先根據Admiin內部的ModelForm錯誤信息提示,如果都成功,纔來檢查Model的字段並顯示指定錯誤信息
    b. 調用Model對象的 "clean_fields" 方法,如:
        # models.py
        class UserInfo(models.Model):
            nid = models.AutoField(primary_key=True)
            username = models.CharField(max_length=32)

            email = models.EmailField(error_messages={'invalid': '格式錯了.'})

        # views.py
        def index(request):
            obj = models.UserInfo(username='11234', email='uu')
            try:
                print(obj.clean_fields())
            except Exception as e:
                print(e)
            return HttpResponse('ok')

       # Model的clean方法是一個鉤子,可用於定製操作,如:上述的異常處理。

2.Admin中修改錯誤提示
    # admin.py
    from django.contrib import admin
    from model_club import models
    from django import forms


    class UserInfoForm(forms.ModelForm):
        username = forms.CharField(error_messages={'required': '用戶名不能爲空.'})
        email = forms.EmailField(error_messages={'invalid': '郵箱格式錯誤.'})
        age = forms.IntegerField(initial=1, error_messages={'required': '請輸入數值.', 'invalid': '年齡必須爲數值.'})

        class Meta:
            model = models.UserInfo
            # fields = ('username',)
            fields = "__all__"


    class UserInfoAdmin(admin.ModelAdmin):
        form = UserInfoForm


    admin.site.register(models.UserInfo, UserInfoAdmin)


二、連表結構 *****

  • 一對多:models.ForeignKey(其他表)
  • 多對多:models.ManyToManyField(其他表)
  • 一對一:models.OneToOneField(其他表)

1.字段以及參數

ForeignKey(ForeignObject) # ForeignObject(RelatedField)
        to,                         # 要進行關聯的表名
        to_field=None,              # 要關聯的表中的字段名稱
        on_delete=None,             # 當刪除關聯表中的數據時,當前表與其關聯的行的行爲,可設置爲如下值:
        # 具體的解釋可見下邊的解釋:
                                        - models.CASCADE,刪除關聯數據,與之關聯也刪除
                                        - models.DO_NOTHING,刪除關聯數據,引發錯誤IntegrityError
                                        - models.PROTECT,刪除關聯數據,引發錯誤ProtectedError
                                        - models.SET_NULL,刪除關聯數據,與之關聯的值設置爲null(前提FK字段需要設置爲可空)
                                        - models.SET_DEFAULT,刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段需要設置默認值)
                                        - models.SET,刪除關聯數據,
                                                      a. 與之關聯的值設置爲指定值,設置:models.SET()
                                                      b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)

                                                        def func():
                                                            return 10

                                                        class MyModel(models.Model):
                                                            user = models.ForeignKey(
                                                                to="User",
                                                                to_field="id"
                                                                on_delete=models.SET(func),)
        related_name=None,          # 反向操作時,使用的字段名,用於代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作時,使用的連接前綴,用於替換【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中顯示關聯數據時,提供的條件:
                                    # 如:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        db_constraint=True          # 是否在數據庫中創建外鍵約束
        parent_link=False           # 在Admin中是否顯示關聯數據


    OneToOneField(ForeignKey)
        to,                         # 要進行關聯的表名
        to_field=None               # 要關聯的表中的字段名稱
        on_delete=None,             # 當刪除關聯表中的數據時,當前表與其關聯的行的行爲

                                    ###### 對於一對一 ######
                                    # 1. 一對一其實就是 一對多 + 唯一索引
                                    # 2.當兩個類之間有繼承關係時,默認會創建一個一對一字段
                                    # 如下會在A表中額外增加一個c_ptr_id列且唯一:
                                            class C(models.Model):
                                                nid = models.AutoField(primary_key=True)
                                                part = models.CharField(max_length=12)

                                            class A(C):
                                                id = models.AutoField(primary_key=True)
                                                code = models.CharField(max_length=1)

    ManyToManyField(RelatedField)
        to,                         # 要進行關聯的表名
        related_name=None,          # 反向操作時,使用的字段名,用於代替 【表名_set】 如: obj.表名_set.all()
        related_query_name=None,    # 反向操作時,使用的連接前綴,用於替換【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
        limit_choices_to=None,      # 在Admin或ModelForm中顯示關聯數據時,提供的條件:
                                    # 如:
                                            - limit_choices_to={'nid__gt': 5}
                                            - limit_choices_to=lambda : {'nid__gt': 5}

                                            from django.db.models import Q
                                            - limit_choices_to=Q(nid__gt=10)
                                            - limit_choices_to=Q(nid=8) | Q(nid__gt=10)
                                            - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
        symmetrical=None,           # 僅用於多對多自關聯時,symmetrical用於指定內部是否創建反向操作的字段
                                    # 做如下操作時,不同的symmetrical會有不同的可選字段
                                        models.BB.objects.filter(...)

                                        # 可選字段有:code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=True)

                                        # 可選字段有: bb, code, id, m1
                                            class BB(models.Model):

                                            code = models.CharField(max_length=12)
                                            m1 = models.ManyToManyField('self',symmetrical=False)

        through=None,               # 自定義第三張表時,使用字段用於指定關係表
        through_fields=None,        # 自定義第三張表時,使用字段用於指定關係表中那些字段做多對多關係表
                                        from django.db import models

                                        class Person(models.Model):
                                            name = models.CharField(max_length=50)

                                        class Group(models.Model):
                                            name = models.CharField(max_length=128)
                                            members = models.ManyToManyField(
                                                Person,
                                                through='Membership',
                                                through_fields=('group', 'person'),
                                            )

                                        class Membership(models.Model):
                                            group = models.ForeignKey(Group, on_delete=models.CASCADE)
                                            person = models.ForeignKey(Person, on_delete=models.CASCADE)
                                            inviter = models.ForeignKey(
                                                Person,
                                                on_delete=models.CASCADE,
                                                related_name="membership_invites",
                                            )
                                            invite_reason = models.CharField(max_length=64)
        db_constraint=True,         # 是否在數據庫中創建外鍵約束
        db_table=None,              # 默認創建第三張表時,數據庫中表的名稱


摘自Stack overflow網友的回答:

This is the behaviour to adopt when the referenced object is deleted. It is not specific to django, this is an SQL standard.

There are 6 possible actions to take when such event occurs:

CASCADE: When the referenced object is deleted, also delete the objects that have references to it (When you remove a blog post for instance, you might want to delete comments as well). SQL equivalent: CASCADE.
PROTECT: Forbid the deletion of the referenced object. To delete it you will have to delete all objects that reference it manually. SQL equivalent: RESTRICT.

SET_NULL: Set the reference to NULL (requires the field to be nullable). For instance, when you delete a User, you might want to keep the comments he posted on blog posts, but say it was posted by an anonymous (or deleted) user. SQL equivalent: SET NULL.

SET_DEFAULT: Set the default value. SQL equivalent: SET DEFAULT.

SET(...): Set a given value. This one is not part of the SQL standard and is entirely handled by Django.

DO_NOTHING: Probably a very bad idea since this would create integrity issues in your database (referencing an object that actually doesn’t exist). SQL equivalent: NO ACTION.

Source: Django documentation

See also the documentation of PostGreSQL for instance.

In most cases, CASCADE is the expected behaviour, but for every ForeignKey, you should always ask yourself what is the expected behaviour in this situation. PROTECT and SET_NULL are often useful. Setting CASCADE where it should not, can potentially delete all your database in cascade, by simply deleting a single user.


三、表的操作(正向查詢按字段,反向查詢按表名)

1.基本操作(增、刪、改、查)

# 增
models.Tb1.objects.create(c1='xx', c2='oo') #增加一條數據,可以接受字典類型數據 **kwargs

obj = models.Tb1(c1='xx', c2='oo')
obj.save()  # 記得調用save方法,保存到數據庫。

# 查
models.Tb1.objects.get(id=123)         # 獲取單條數據,不存在則報錯(不建議)
models.Tb1.objects.all()               # 獲取全部
models.Tb1.objects.filter(name='seven') # 獲取指定條件的數據,返回數據列表,沒有返回空列表[]

# 刪
models.Tb1.objects.filter(name='seven').delete() # 刪除指定條件的數據

# 改
models.Tb1.objects.filter(name='seven').update(gender='0')  # 將指定條件的數據更新,均支持 **kwargs
# obj = models.Tb1.objects.get(id=1)
# obj.c1 = '111'
# obj.save()                                                 # 修改單條數據

2.表操作進階(牛逼的 雙下劃線 __ )

利用 雙下劃線_set 將表之間的操作連接起來

# 獲取個數
models.Tb1.objects.filter(name='seven').count()

# 大於,小於
models.Tb1.objects.filter(id__gt=1)              # 獲取id大於1的值
models.Tb1.objects.filter(id__gte=1)              # 獲取id大於等於1的值
models.Tb1.objects.filter(id__lt=10)             # 獲取id小於10的值
models.Tb1.objects.filter(id__lte=10)             # 獲取id小於10的值
models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 獲取id大於1 且 小於10的值

# in
models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於11、22、33的數據
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

# isnull
Entry.objects.filter(pub_date__isnull=True)

# contains包含
models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
models.Tb1.objects.exclude(name__icontains="ven")

# range範圍
models.Tb1.objects.filter(id__range=[1, 2])   # 範圍bettwen and

# 其他類似
startswith,istartswith, endswith, iendswith,

# order by排序
models.Tb1.objects.filter(name='seven').order_by('id')    # asc正序
models.Tb1.objects.filter(name='seven').order_by('-id')   # desc倒序

# group by
from django.db.models import Count, Min, Max, Sum
models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
等價於SQL語句:SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"

# limit 、offset
models.Tb1.objects.all()[10:20]

# regex正則匹配,iregex 不區分大小寫
Entry.objects.get(title__regex=r'^(An?|The) +')
Entry.objects.get(title__iregex=r'^(an?|the) +')

# date
Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

# year
Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)

# month
Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)

# day
Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)

# week_day
Entry.objects.filter(pub_date__week_day=2)
Entry.objects.filter(pub_date__week_day__gte=2)

# hour
Event.objects.filter(timestamp__hour=23)
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)

# minute
Event.objects.filter(timestamp__minute=29)
Event.objects.filter(time__minute=46)
Event.objects.filter(timestamp__minute__gte=29)

# second
Event.objects.filter(timestamp__second=31)
Event.objects.filter(time__second=2)
Event.objects.filter(timestamp__second__gte=31)
# 例子
get示例:
    # 例:查詢圖書id爲3的圖書信息。
    # 注意這裏有且只有一個纔行,多了或者沒有都會報錯
    BookInfo.objects.get(id=3)

all方法示例:
    # 例:查詢圖書所有信息。
    BookInfo.objects.all()

filter方法示例:
    """
    條件格式:(雙下劃線)
        模型類屬性名__條件名=值
    """
    查詢圖書評論量爲34的圖書的信息:
    a)判等 條件名:exact。
        # 例:查詢編號爲1的圖書。
        BookInfo.objects.get(id=1)
    b)模糊查詢(相當於sql的 like)
        # 例:查詢書名包含'傳'的圖書。contains
        BookInfo.objects.filter(btitle__contains='傳')
        # 例:查詢書名以'部'結尾的圖書 endswith 開頭:startswith
        BookInfo.objects.filter(btitle__endswith='部')
    c)空查詢 isnull
        # 例:查詢書名不爲空的圖書。isnull 
        select * from booktest_bookinfo where btitle is not null;
        BookInfo.objects.filter(btitle__isnull=False)
    d)範圍查詢 in
        # 例:查詢id爲1或3或5的圖書。
        select * from booktest_bookinfo where id in (1,3,5);
        BookInfo.objects.filter(id__in = [1,3,5])
    e)比較查詢 gt(greate than) lt(less  than) gte(equal)大於等於   lte小於等於
        # 例:查詢id大於3的圖書。
        Select * from booktest_bookinfo where id>3;
        BookInfo.objects.filter(id__gt=3)
    f)日期查詢
        # 例:查詢1980年發表的圖書。
        BookInfo.objects.filter(bpub_date__year=1980)
        # 例:查詢1980年1月1日後發表的圖書。
        from datetime import date
        BookInfo.objects.filter(bpub_date__gt=date(1980,1,1))

exclude方法示例:
    # 例:查詢id不爲3的圖書信息。
    BookInfo.objects.exclude(id=3)
    
order_by方法示例:
    作用:進行查詢結果進行排序。默認是升序,在條件里加“-”表示降序
    # 例:查詢所有圖書的信息,按照id從小到大進行排序。
    BookInfo.objects.all().order_by('id')
    # 例:查詢所有圖書的信息,按照id從大到小進行排序。
    BookInfo.objects.all().order_by('-id')
    # 例:把id大於3的圖書信息按閱讀量從大到小排序顯示。
    BookInfo.objects.filter(id__gt=3).order_by('-bread')

3.其他

# extra
#
extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

# F對象
#
from django.db.models import F
models.Tb1.objects.update(num=F('num')+1)


# Q對象
#
# 方式一:
Q(nid__gt=10)
Q(nid=8) | Q(nid__gt=10)
Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
# 方式二:
con = Q()
q1 = Q()
q1.connector = 'OR'
q1.children.append(('id', 1))
q1.children.append(('id', 10))
q1.children.append(('id', 9))
q2 = Q()
q2.connector = 'OR'
q2.children.append(('c1', 1))
q2.children.append(('c1', 10))
q2.children.append(('c1', 9))
con.add(q1, 'AND')
con.add(q2, 'AND')

models.Tb1.objects.filter(con)


# 執行原生SQL
#
from django.db import connection, connections
cursor = connection.cursor()  # cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone()

4.聯表操作(利用 雙下劃線 __ )

  • Model表結構實例
class UserProfile(models.Model):
    user_info = models.OneToOneField('UserInfo')
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)

    def __unicode__(self):
        return self.username


class UserInfo(models.Model):
    user_type_choice = (
        (0, u'普通用戶'),
        (1, u'高級用戶'),
    )
    user_type = models.IntegerField(choices=user_type_choice)
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    address = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name


class UserGroup(models.Model):

    caption = models.CharField(max_length=64)

    user_info = models.ManyToManyField('UserInfo')

    def __unicode__(self):
        return self.caption


class Host(models.Model):
    hostname = models.CharField(max_length=64)
    ip = models.GenericIPAddressField()
    user_group = models.ForeignKey('UserGroup')

    def __unicode__(self):
        return self.hostname

1. 一對一操作

user_info_obj = models.UserInfo.objects.filter(id=1).first()
print(user_info_obj.user_type)
print(user_info_obj.get_user_type_display())
print(user_info_obj.userprofile.password)
 
user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first()
print(user_info_obj.keys())
print(user_info_obj.values())

2.一對多

  • 類似一對一
    • 1、搜索條件使用 __連接
    • 2、獲取值時使用 . 連接

3.多對多

user_info_obj = models.UserInfo.objects.get(name=u'武沛齊')
user_info_objs = models.UserInfo.objects.all()

group_obj = models.UserGroup.objects.get(caption='CEO')
group_objs = models.UserGroup.objects.all()

-------------------------------------------------------------
# 添加數據
group_obj.user_info.add(user_info_obj)
group_obj.user_info.add(*user_info_objs)  # 注意星號

# 刪除數據
group_obj.user_info.remove(user_info_obj)
group_obj.user_info.remove(*user_info_objs)

# 添加數據
user_info_obj.usergroup_set.add(group_obj)
user_info_obj.usergroup_set.add(*group_objs)

# 刪除數據
user_info_obj.usergroup_set.remove(group_obj)
user_info_obj.usergroup_set.remove(*group_objs)

# 獲取數據
print group_obj.user_info.all()
print group_obj.user_info.all().filter(id=1)

# 獲取數據
print user_info_obj.usergroup_set.all()  # __set
print user_info_obj.usergroup_set.all().filter(caption='CEO')
print user_info_obj.usergroup_set.all().filter(caption='DBA')

5.擴展(上傳文件)

  • 自定義文件上傳
def upload_file(request):
    if request.method == "POST":
        obj = request.FILES.get('fafafa')
        f = open(obj.name, 'wb')
        for chunk in obj.chunks():  # chunks函數將收到的數據分塊
            f.write(chunk)
        f.close()
    return render(request, 'file.html')
  • Form上傳文件實例
# Form
class FileForm(forms.Form):
    ExcelFile = forms.FileField()
    
# Model
from django.db import models

class UploadFile(models.Model):
    userid = models.CharField(max_length = 30)
    file = models.FileField(upload_to = './upload/')
    date = models.DateTimeField(auto_now_add=True)
    
# View
def UploadFile(request):
    uf = AssetForm.FileForm(request.POST,request.FILES)
    if uf.is_valid():
            upload = models.UploadFile()
            upload.userid = 1
            upload.file = uf.cleaned_data['ExcelFile']
            upload.save()
            
            print upload.file

6. 批量刪除

  • 一般刪除: models.SyncRecord.objects.filter(create_time__lte=clear_timestamp).delete() 根據過濾出來的數據直接調用刪除
  • 當有page、limit在內時django是不支持進行直接的批量操作的
    • 可以利用子查詢:
    models.SyncRecord.objects.filter(
            pk__in=(models.SyncRecord.objects.order_by('create_time').values_list('pk')[:5])
    ).delete()
    
    # django ORM 利用列表切片來實現sql中的page/limit操作,在利用orm生成sql時,會自動將其轉換爲page/limit
    
    • 但是低版本mysql(如:5.7.2)不支持這種查詢,可轉換爲:
    id_query_set = models.SyncRecord.objects.order_by('create_time')[:clear_count].values_list('id')
    # django獲取到的都是個queryset對象
    clear_id_list = [int(i[0]) for i in id_query_set]
    models.SyncRecord.objects.filter(id__in=clear_id_list).delete()
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章