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()
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章