Django CRUD操作

Django 中使用ORM模型来定义数据库。模型一般是个Python类,类中的属性对应数据库表中的列。 下面是一些增删改查操作记录。

models.py 文件中定义的表结构

# coding=utf-8
from __future__ import unicode_literals

from django.db import models
# django 自带的认证模块的表类
from django.contrib.auth.models import User
# Create your models here.


class Host(models.Model):   # 主机表
    # 定义表的字段, 不主动定义主键时,django会自动创建id主键,并建立索引。
    hostname = models.CharField(max_length=64, unique=True)
    ip_addr = models.GenericIPAddressField(unique=True)
    port = models.IntegerField(default=22)
    # 可以选择机器的系统,展示给用户的是数组中第二个元素,存在数据库中的是第一个元素。
    system_type_choices = (
        ('linux', "Centos"),
        ('win32', "Windows 7")
    )
    system_type = models.CharField(choices=system_type_choices, max_length=32)
    # 定义主机是否上线,布尔型
    enabled = models.BooleanField(default=True)
    # 创建记录时间,自动添加
    create_date = models.DateTimeField(auto_now_add=True)
    # 上线时间
    online_date = models.DateTimeField()
    # 主机和组之间是多对多的关系
    groups = models.ManyToManyField('HostGroup')
    # idc机房,外键,并且是一对多的关系
    idc = models.ForeignKey('IDC')

    def __unicode__(self):
        return self.hostname


class IDC(models.Model):    # IDC机房
    name = models.CharField(max_length=64, unique=True)

    def __unicode__(self):
        return self.name


class HostGroup(models.Model):  # 主机组
    name = models.CharField(max_length=64, unique=True)

    def __unicode__(self):
        return self.name


class UserProfile(models.Model):
    # 使user 一对一的映射 django提供的User
    user = models.OneToOneField(User)
    name = models.CharField(max_length=64, unique=True)
    host_groups = models.ManyToManyField('HostGroup', blank=True, null=True)
    hosts = models.ManyToManyField('Host', blank=True, null=True)

    def __unicode__(self):
        return self.name

使用Djangoshell来操作。

$ python manage.py shell

# 导入
In [1]: from app import models

# 查找
In [2]: models.Host.objects.all()
Out[2]: <QuerySet [<Host: dev-sate>, <Host: pro-sate>, <Host: release-sate>, <Host: sateText2>]>

In [3]: models.IDC.objects.all()
Out[3]: <QuerySet [<IDC: 上海>, <IDC: 北京>]>

# 过滤,filter返回一个列表
In [8]: models.Host.objects.filter(ip_addr='192.168.0.1')
Out[8]: <QuerySet [<Host: dev-sate>]>

# id__lt=1 表示过滤id值小于1的项
In [13]: models.Host.objects.filter(id__lt=1)
Out[13]: <QuerySet []>

# id__gt=1 表示过滤id值大于1的项
In [14]: models.Host.objects.filter(id__gt=1)
Out[14]: <QuerySet [<Host: pro-sate>, <Host: release-sate>, <Host: sateText2>]>

# 多条件过滤,
# hostname__contains(包含,双下划线),包含 sate 的主机名
In [12]: models.Host.objects.filter(system_type='linux', hostname__contains='sate')
Out[12]: <QuerySet [<Host: dev-sate>, <Host: pro-sate>, <Host: sateText2>]>


# 精确查找,get,只能有一个结果,如果有多个,则报错。
In [11]: models.Host.objects.get(system_type='linux', hostname__contains='pro')
Out[11]: <Host: pro-sate>

# 其他的一些查询用法(未使用上述模型)
# 查看 Django queryset 执行的 SQL 
In [1]: print str(Author.objects.all().query)
SELECT "blog_author"."id", "blog_author"."name", "blog_author"."qq", "blog_author"."addr", "blog_author"."email" FROM "blog_author"
### 简化一下,就是:SELECT id, name, qq, addr, email FROM blog_author;

# values_list 获取元组形式结果
In [6]: authors = Author.objects.values_list('name', 'qq')

In [7]: authors
Out[7]: <QuerySet [(u'WeizhongTu', u'336643078'), (u'twz915', u'915792575'), (u'wangdachui', u'353506297'), (u'xiaoming', u'004466315')]>

# values 获取字典形式的结果
In [13]: Author.objects.values('name', 'qq')
Out[13]: <QuerySet [{'qq': u'336643078', 'name': u'WeizhongTu'}, {'qq': u'915792575', 'name': u'twz915'}, {'qq': u'353506297', 'name': u'wangdachui'}, {'qq': u'004466315', 'name': u'xiaoming'}]>

### values_list 和 values 返回的并不是真正的 列表 或 字典,也是 queryset,他们也是 lazy evaluation 的(惰性评估,通俗地说,就是用的时候才真正的去数据库查)

多表查询

首先Djangoadmin控制台增加一个用户sate

# 从 UserProfile 查到用户名为 sate 的用户,并实例化
In [57]: a = models.UserProfile.objects.get(name = 'sate')

# UserProfile表中的hosts字段跟Host表是多对多的关系,可以根据该关系查询到该用户所对应
#Host表中的各个机器的信息(如 host.hostname, host.ip_addr等)
In [60]: a.hosts.select_related()
Out[60]: <QuerySet [<Host: sateText2>]>

In [20]: h = a.hosts.select_related()[0]

In [22]: h.hostname
Out[22]: u'sateText2'

In [23]: h.ip_addr
Out[23]: u'192.168.0.4'

In [24]: h.create_date
Out[24]: datetime.datetime(2016, 12, 2, 7, 49, 51, 137731, tzinfo=<UTC>)

# 多表查询 a 中的关联的 host_groups,同上。
In [62]: a.host_groups.select_related()
Out[62]: <QuerySet [<HostGroup: dev>, <HostGroup: product>]>
# 可以使用循环依次读出处理,但我们这里使用直接赋值,更清晰。
In [29]: g = a.host_groups.select_related()[0]  # 选取 dev 组

###  现在我们想获取dev组中的各个机器的信息,就需要获取到Host表中的信息,但和之前有所不
#同,Host的groups字段对HostGroup表是多对多的,而不是HostGroup的某个字段对Host表是多
#对多,所以如下操作。
In [33]: g.host_set.select_related()
Out[33]: <QuerySet [<Host: dev-sate>, <Host: sateText2>]>

# 同理,UserProfile 表的host_groups 对HostGroup也是多对多的。可以进行如下查询。
In [34]: g.userprofile_set.select_related()
Out[34]: <QuerySet [<UserProfile: sate>]>

在前端的多表查询

上边的查询,都可以在前端的 html页面中实现。

{{ request.user.userprofile.hosts.select_related }}
    <ul>
        <!-- 查找登录用户所属的组 -->
        {% for group in request.user.userprofile.host_groups.select_related %}
        <li>{{ group.name }}</li>
            <ul>
            <!-- 通过组查找组内机器信息 -->
            {% for host in  group.host_set.select_related  %}
                <li>
                {{ host.hostname }} ===> {{ host.ip_addr }} ===> {{ host.idc.name }}
                </li>
            {% endfor %}
            </ul>
        {% endfor %}
    </ul>

查询过滤

# 并没有使用上边的Model模型。 只是

#get是用来获取一个对象的,如果需要获取满足条件的一些人,就要用到filter
Person.objects.filter(name="abc") # 等于Person.objects.filter(name__exact="abc") 名称严格等于 "abc" 的人

Person.objects.filter(name__iexact="abc") # 名称为 abc 但是不区分大小写,可以找到 ABC, Abc, aBC,这些都符合条件

Person.objects.filter(name__contains="abc") # 名称中包含 "abc"的人

Person.objects.filter(name__icontains="abc") #名称中包含 "abc",且abc不区分大小写

Person.objects.filter(name__regex="^abc") # 正则表达式查询

Person.objects.filter(name__iregex="^abc")# 正则表达式不区分大小写

# filter是找出满足条件的,当然也有排除符合某条件的
Person.objects.exclude(name__contains="WZ") # 排除包含 WZ 的Person对象

Person.objects.filter(name__contains="abc").exclude(age=23) # 找出名称含有abc, 但是排除年龄是23岁的

# 增加一条Host的新纪录。online_date 是时间类型,所以要导入datetime模块,生成时间。
In [15]: import datetime
# 添加一条记录,需要注意的是 idc 是个外键,如果直接知道所属idc的id,可以使用 'idc_id = 1'的方式来添加记录。
In [18]: models.Host.objects.create(
    ...: hostname = 'NewHost',
    ...: ip_addr = '192.168.0.6',
    ...: port = 22,
    ...: system_type = 'linux',
    ...: idc = models.IDC.objects.get(name='北京'),   # 或使用 idc_id = 1 的方式来设定
    ...: online_date = datetime.datetime.now())
/Users/zheng/VirtualEnv/just_python2/lib/python2.7/site-packages/django/db/models/fields/__init__.py:1430: RuntimeWarning: DateTimeField Host.online_date received a naive datetime (2016-12-05 09:21:41.926206) while time zone support is active.
  RuntimeWarning)
Out[18]: <Host: NewHost>
# 上边有warning信息,是因为时区的原因。此时生成的日期,并不是当前时区的时间。
# 现在还有问题是 有个多对多的 groups 字段不能用上边方式定义,使用如下方法定义
In [19]: new = models.Host.objects.get(hostname='newhost')
# 现在为他添加所有的组,先查出所有组
In [25]: all_groups = models.HostGroup.objects.all()
In [26]: all_groups
Out[26]: <QuerySet [<HostGroup: dev>, <HostGroup: product>]>
# 为 new 添加查出来的组,方式为 new.groups.add(1,2)
In [30]: new.groups.add(*[i.id for i in all_groups])
# 然后再Django的admin后台页面查看,会发现改机器已经属于所有组。

# 如果要删除该机器的所属组,可以使用remove 替换 add
In [31]: new.groups.remove(*[i.id for i in all_groups])


### 上边方法比较麻烦,可以使用如下方法
# 先实例化
In [33]: h = models.Host(
    ...: hostname = 'NewHost2',
    ...: ip_addr = '192.168.0.7',
    ...: port = 33,
    ...: system_type='linux',
    ...: idc_id=1,
    ...: online_date=datetime.datetime.now())
# 写入数据库
In [35]: h.save()
# 添加 groups 的多对多的关系
In [36]: all_groups = models.HostGroup.objects.all()
In [37]: h.groups.add(*[i.id for i in all_groups])

### 指定修改
In [39]: gai = models.Host.objects.get(hostname='Newhost')
In [41]: gai.hostname = 'NewHost1'
In [43]: gai.save()

### 批量修改
# 全部修改
In [45]: models.Host.objects.all().update(port=2000)
Out[45]: 6L
# 过滤修改
In [47]: models.Host.objects.filter(system_type='linux').update(port=22, system_type='win32')
Out[47]: 5L

### 指定删除
In [50]: gai = models.Host.objects.get(hostname='Newhost1')

In [51]: gai.delete()
Out[51]:
(3L,{u'app01.Host': 1L, u'app01.Host_groups': 2L, u'app01.UserProfile_hosts': 0L})

### 批量删除
In [53]: models.Host.objects.filter(port=2000).delete()
Out[53]:
(3L,
 {u'app01.Host': 1L, u'app01.Host_groups': 1L, u'app01.UserProfile_hosts': 1L})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容