Django项目实践3 - Django模型(数据库字段及操作)

http://blog.csdn.net/pipisorry/article/details/45725953

数据库字段

时间字段

DateTimeField和DateField和TimeField存储的内容分别对应着datetime(),date(),time()三个对象。

auto_now=Ture,字段保存时会自动保存当前时间,但要注意每次对其实例执行save()的时候都会将当前时间保存,也就是不能再手动给它存非当前时间的值。

auto_now_add=True,字段在实例第一次保存的时候会保存当前时间,不管你在这里是否对其赋值。但是之后的save()是可以手动赋值的。也就是新实例化一个model,想手动存其他时间,就需要对该实例save()之后赋值然后再save()。

Note:两者默认值都为False。

Django自动添加当前日期时间到数据库

models.DateTimeField(auto_now_add=True)

[所有的字段类型和模型语法选项-Database API Reference]

Django上进行数据库操作

Django自动为建立的模型提供了高级的Python API,来进行数据库操作

测试数据库的python API

E:\mine\python_workspace\VoteSite>python manage.py shell
...
>>> from books.models import Publisher
>>> Publisher.objects.all()
[]
>>> p1 = Publisher(name=‘Apress‘, address=‘2855 Telegraph Avenue‘, city=‘Berkeley‘, state_province=‘CA‘, country=‘U.S.A.‘, website=‘http://www.apress.com/‘)
>>> p1.save()
>>> p2 = Publisher(name="O‘Reilly", address=‘10 Fawcett St.‘, city=‘Cambridge‘, state_province=‘MA‘, country=‘U.S.A.‘, website=‘http://www.oreilly.com/‘)
>>> p2.save()
>>> Publisher.objects.all()
[<Publisher: Publisher object>, <Publisher: Publisher object>]
>>>

Note:

1. 通过调用该对象的 save() 方法,将对象保存到数据库中。 Django 会在后台执行一条INSERT 语句。当你使用Django modle API创建对象时Django并未将对象保存至数据库内,除非你调用`` save()`` 方法。

2. 使用`` Publisher.objects`` 属性从数据库取出出版商的信息,这个属性可以认为是包含出版商的记录集。 这个属性有许多方法, 这里先介绍调用`` Publisher.objects.all()`` 方法获取数据库中`` Publisher`` 类的所有对象。这个操作的幕后,Django执行了一条SQL `` SELECT`` 语句。

3. 如果需要一步完成对象的创建与存储至数据库,就使用`` objects.create()`` 方法。 下面的例子与之前的例子等价:

p1 = Publisher.objects.create(name=‘Apress‘, address=‘2855 Telegraph Avenue‘, city=‘Berkeley‘, state_province=‘CA‘, country=‘U.S.A.‘, website=‘http://www.apress.com/‘)
p2 = Publisher.objects.create(name="O‘Reilly", address=‘10 Fawcett St.‘, city=‘Cambridge‘, state_province=‘MA‘, country=‘U.S.A.‘, website=‘http://www.oreilly.com/‘)
Publisher.objects.all()

4. 如果你有用到后面要讲到的admin管理界面,会发现save()之后admin会自动更新列表。如果在管理界面删除某个p3, 那就相当于没有这个操作:p3 = Publisher(name="O‘yy", address=‘10 Fawcett St.‘, city=‘Cambridge‘, state_province=‘MA‘, country=‘U.S.A.‘, website=‘http://www.oreilly.com/‘),Publisher.objects.all()也会从3个p变成两个p.

添加模块的字符串表现

当我们打印整个Publisher.objects.all()列表时,我们没有得到想要的有用信息,无法把````对象区分开来

解决这个问题,只需要为Publisher 对象添加一个方法__unicode__(){python3换成__str__()!!!} 。__unicode__()
方法告诉Python如何将对象以unicode的方式显示出来。 为以上三个模型添加__unicode__()方法后,就可以看到效果了:

from django.db import models

class Publisher(models.Model):
    ‘‘‘
    出版商有名称,地址,所在城市、省,国家,网站
    ‘‘‘
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    def __str__(self):
        return self.name

class Author(models.Model):
    ‘‘‘
    作者有姓,有名及email地址
    ‘‘‘
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()

    def __str__(self):
        return u‘%s %s‘ % (self.first_name, self.last_name)

class Book(models.Model):
    ‘‘‘
    书籍有书名和出版日期
    ‘‘‘
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()

    def __str__(self):
        return self.title

Note:

1.__unicode__() 方法可以进行任何处理来返回对一个对象的字符串表示。

2. 对__unicode__()的唯一要求就是它要返回一个unicode对象 如果`` __unicode__()`` 方法未返回一个Unicode对象,而返回比如说一个整型数字,那么Python将抛出一个`` TypeError`` 错误,并提示:”coercing to Unicode: need string or buffer, int found” 。

3. Django 在其内部的各个方面都使用到了 Unicode 对象。 模型 对象中,检索匹配方面的操作使用的是 Unicode 对象,视图 函数之间的交互使用的是 Unicode 对象,模板的渲染也是用的 Unicode 对象。 通常,我们不必担心编码是否正确,后台会处理的很好。[字符编码ASCII,Unicode和UTF-8]

为了让我们的修改生效,先退出Python Shell,然后再次运行
python manage.py
shell
进入:

from books.models import Publisher
Publisher.objects.all()
[<Publisher: Apress>, <Publisher: O‘Reilly>]

Note:

1. 确保你的每一个模型里都包含 __unicode__() 方法,这不只是为了交互时方便,也是因为 Django会在其他一些地方用__unicode__() 来显示对象。

2.  __unicode__() 也是一个很好的例子来演示我们怎么添加行为 到模型里。 Django的模型不只是为对象定义了数据库表的结构,还定义了对象的行为。

插入和更新数据

在SQL里,这大致可以转换成这样:

INSERT INTO books_publisher
    (name, address, city, state_province, country, website)
VALUES
    (‘Apress‘, ‘2855 Telegraph Ave.‘, ‘Berkeley‘, ‘CA‘, ‘U.S.A.‘, ‘http://www.apress.com/‘);

因为 Publisher 模型有一个自动增加的主键id ,所以第一次调用save() 还多做了一件事: 计算这个主键的值并把它赋值给这个对象实例:

>>> p.id
52    # this will differ based on your own data

接下来再调用 save() 将不会创建新的记录,而只是修改记录内容(也就是 执行UPDATE SQL语句,而不是INSERT
语句):

>>> p.name = ‘Apress Publishing‘
>>> p.save()

前面执行的 save() 相当于下面的SQL语句:

UPDATE books_publisher SET
    name = ‘Apress Publishing‘,
    address = ‘2855 Telegraph Ave.‘,
    city = ‘Berkeley‘,
    state_province = ‘CA‘,
    country = ‘U.S.A.‘,
    website = ‘http://www.apress.com‘
WHERE id = 52;

Note:并不是只更新修改过的那个字段,所有的字段都会被更新。这个操作有可能引起竞态条件,这取决于你的应用程序。 参阅下面讲到的[只更改某一指定的列]

UPDATE books_publisher SET
    name = ‘Apress Publishing‘
WHERE id=52;

选择对象

对于 Web 应用程序来说,更多的时候是在检索查询数据库。从一个给定的模型中取出所有记录:

>>> Publisher.objects.all()
[<Publisher: Apress>, <Publisher: O‘Reilly>]

这相当于这个SQL语句:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher;

Note:

1. Django在选择所有数据时并没有使用 SELECT* ,而是显式列出了所有字段。SELECT* 会更慢,而且最重要的是列出所有字段遵循了Python 界的一个信条: 明言胜于暗示。

2. objects属性。 它被称为管理器。 目前,我们只需了解管理器管理着所有针对数据包含、还有最重要的数据查询的表格级操作。所有的模型都自动拥有一个objects 管理器;你可以在想要查找数据时使用它。

3. all() 方法。这个方法返回返回数据库中所有的记录。 尽管这个对象 看起来 象一个列表(list),它实际是一个 QuerySet 对象, 这个对象是数据库中一些记录的集合。 [详细描述QuerySet]

数据过滤

我们很少会一次性从数据库中取出所有的数据;通常都只针对一部分数据进行操作。 在Django API中,我们可以使用`` filter()`` 方法对数据进行过滤:

>>> Publisher.objects.filter(name=‘Apress‘)
[<Publisher: Apress>]

filter() 根据关键字参数来转换成WHERE SQL语句。相当于:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = ‘Apress‘;

你可以传递多个参数到 filter() 来缩小选取范围:

>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
[<Publisher: Apress>]

多个参数会被转换成 AND SQL从句:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE country = ‘U.S.A.‘
AND state_province = ‘CA‘;

Note:SQL缺省的= 操作符是精确匹配的, 其他类型的查找也可以使用:

>>> Publisher.objects.filter(name__contains="press")
[<Publisher: Apress>]

namecontains 之间有双下划线。和Python一样,Django也使用双下划线来表明会进行一些魔术般的操作。这里,contains部分会被Django翻译成LIKE语句:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name LIKE ‘%press%‘;

其他的一些查找类型有:icontains(大小写无关的LIKE),startswithendswith,
还有range(SQLBETWEEN查询)。[详细描述所有的查找类型]

获取单个对象

上面的例子中`` filter()`` 函数返回一个记录集。获取单个的对象get()方法

>>> Publisher.objects.get(name="Apress")
<Publisher: Apress>

这样,就返回了单个对象,而不是列表(更准确的说,QuerySet)。 所以,如果结果是多个对象,会导致抛出异常;如果查询没有返回结果也会抛出异常,这个DoesNotExist 异常 是 Publisher 这个 model 类的一个属性,即Publisher.DoesNotExist

在你的应用中,你可以捕获并处理这个异常,像这样:

try:
    p = Publisher.objects.get(name=‘Apress‘)
except Publisher.DoesNotExist:
    print "Apress isn‘t in the database yet."
else:
    print "Apress is in the database."

数据排序

在运行前面的例子中返回的结果是无序的。 Django 应用中,使用
order_by()
这个方法根据某字段的值对检索结果排序。

>>> Publisher.objects.order_by("name")
[<Publisher: Apress>, <Publisher: O‘Reilly>]

跟以前的 all() 例子差不多,SQL语句里多了指定排序的部分:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
ORDER BY name;

我们可以对任意字段进行排序:

>>> Publisher.objects.order_by("address")
[<Publisher: O‘Reilly>, <Publisher: Apress>]

>>> Publisher.objects.order_by("state_province")
[<Publisher: Apress>, <Publisher: O‘Reilly>]

如果需要以多个字段为标准进行排序(第二个字段会在第一个字段的值相同的情况下被使用到),使用多个参数就可以了,如下:

>>> Publisher.objects.order_by("state_province", "address")
 [<Publisher: Apress>, <Publisher: O‘Reilly>]

我们还可以指定逆向排序,在前面加一个减号 - 前缀:

>>> Publisher.objects.order_by("-name")
[<Publisher: O‘Reilly>, <Publisher: Apress>]

但是每次都要用 order_by() 显得有点啰嗦。 大多数时间你通常只会对某些 字段进行排序。

Django指定模型的缺省排序方式:

class Publisher(models.Model):
    ‘‘‘
    出版商有名称,地址,所在城市、省,国家,网站
    ‘‘‘
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    def __str__(self):
        return self.name

    class Meta:
        ordering = [‘name‘]

Note:

1. classMeta,内嵌于Publisher 这个类的定义中。你可以在任意一个 模型类中使用Meta
类,来设置一些与特定模型相关的选项。 [Meta 中所有可选项的完整参考]。

2. 如果你设置了这个选项,那么除非你检索时特意额外地使用了order_by(),否则,当你使用 Django 的数据库 API 去检索时,Publisher对象的相关返回值默认地都会按name
字段排序。

连锁查询

通常我们需要同时进行过滤和排序查询的操作。 “链式”形式:

>>> Publisher.objects.filter(country="U.S.A.").order_by("-name")
[<Publisher: O‘Reilly>, <Publisher: Apress>]

转换成SQL查询就是 WHEREORDERBY 的组合:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE country = ‘U.S.A‘
ORDER BY name DESC;

限制返回的数据

另一个常用的需求就是取出固定数目的记录。 可以使用标准的Python列表裁剪语句:

>>> Publisher.objects.order_by(‘name‘)[0]
<Publisher: Apress>

这相当于:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
ORDER BY name
LIMIT 1;

类似的,你可以用Python的range-slicing语法来取出数据的特定子集:

>>> Publisher.objects.order_by(‘name‘)[0:2]

这个例子返回两个对象,等同于以下的SQL语句:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
ORDER BY name
OFFSET 0 LIMIT 2;

Note: 不支持Python的负索引(negative slicing),但是我们可以使用其他的方法。 稍微修改 order_by() 语句来实现:

>>> Publisher.objects.order_by(‘-name‘)[0]

更改某一指定的列-update()方法

save()方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。例如说我们现在想要将Apress Publisher的名称由原来的”Apress”更改为”Apress Publishing”。若使用save()方法,如:

>>> p = Publisher.objects.get(name=‘Apress‘)
>>> p.name = ‘Apress Publishing‘
>>> p.save()

这等同于如下SQL语句:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = ‘Apress‘;

UPDATE books_publisher SET
    name = ‘Apress Publishing‘,
    address = ‘2855 Telegraph Ave.‘,
    city = ‘Berkeley‘,
    state_province = ‘CA‘,
    country = ‘U.S.A.‘,
    website = ‘http://www.apress.com‘
WHERE id = 52;

在这个例子里我们可以看到Django的save()方法更新了不仅仅是name列的值,还有更新了所有的列。 若name以外的列有可能会被其他的进程所改动的情况下,只更改name列显然是更加明智的。

我们可以调用结果集(QuerySet)对象的update()方法:

>>> Publisher.objects.filter(id=52).update(name=‘Apress Publishing‘)

与之等同的SQL语句变得更高效,并且不会引起竞态条件。

UPDATE books_publisher
SET name = ‘Apress Publishing‘
WHERE id = 52;

更新多个对象

update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录。

以下将所有Publisher的country字段值由’U.S.A’更改为’USA’:

>>> Publisher.objects.all().update(country=‘USA‘)
2

update()方法会返回一个整型数值,表示受影响的记录条数。

删除对象

删除数据库中的对象只需调用该对象的delete()方法:

# 删除id=1的数据
test1 = Test.objects.get(id=1)
test1.delete()

# 另外一种方式
# Test.objects.filter(id=1).delete() 

同样我们可以在结果集上调用delete()方法同时删除所有记录

>>> Publisher.objects.all().delete()
>>> Publisher.objects.all()
[]

删除数据时要谨慎! 为了预防误删除掉某一个表内的所有数据,Django要求在删除表内所有数据时显示使用all()。而一旦使用all()方法,所有数据将会被删除:

>>> Publisher.objects.all().delete()

如果只需要删除部分的数据,就不需要调用all()方法。

>>> Publisher.objects.filter(country=‘USA‘).delete()

from:http://blog.csdn.net/pipisorry/article/details/45725953

时间: 2024-10-03 22:42:07

Django项目实践3 - Django模型(数据库字段及操作)的相关文章

Django项目实践3 - Django模型

http://blog.csdn.net/pipisorry/article/details/45061579 上篇:Django项目实践2 - Django模板 Django 模型 {数据和逻辑能够彻底地分开} Django 对各种数据库提供了很好的支持,包括:PostgreSQL.MySQL.SQLite.Oracle.Django 为这些数据库提供了统一的调用API. 1.在 Django 中使用 MySQL MySQL 是 Web 应用中最常用的数据库.下面将以 Mysql 作为实例进行

Django项目实践4 - Django网站管理(后台管理员)

http://blog.csdn.net/pipisorry/article/details/45079751 上篇:Django项目实践3 - Django模型 Introduction 对于某一类站点, 管理界面 是基础设施中很重要的一部分. 这是以网页和有限的可信任管理者为基础的界面,它能够让你加入,编辑和删除站点内容. 常见的样例: 你能够用这个界面公布博客,后台的站点管理者用它来润色读者提交的内容,你的客户用你给他们建立的界面工具更新新闻并公布在站点上.这些都是使用管理界面的样例. 创

Django项目实践2 - Django模板

http://blog.csdn.net/pipisorry/article/details/45061511 上篇:Django项目实践1 - 创建Django项目 Django模板 {视图和模板对逻辑和显示进行了分隔} 上面是使用 django.http.HttpResponse() 来输出"Hello World!".该方式将数据与视图混合在一起,不符合Django的MVC思想.或者HTML被直接硬编码在 Python 代码之中. html = "<html>

Django项目实践2 - Django模板(常用语法规则)

http://blog.csdn.net/pipisorry/article/details/45727309 模板中常用的语法规则 {最新版本的Django语法可能有改变,不支持的操作可能支持了.[HTML教程 - 基本元素/标签及属性]} Django 模板标签 if/else 标签 1. 基本语法格式如下: {% if condition %} ... display {% endif %} 或者: {% if condition1 %} ... display 1 {% elif con

Django中的app及mysql数据库篇(ORM操作)

Django常见命令 在Django的使用过程中需要使用命令让Django进行一些操作,例如创建Django项目.启动Django程序.创建新的APP.数据库迁移等. 创建Django项目 一把我们都新建一个文件夹来存放项目文件,切换到这个目录下,启动命令行工具.创建一个名为mysite的Django项目: django-admin startproject mysite 创建好项目之后,可以查看当前目录下多出一个名为mysite的文件夹,mysite的文件夹目录结构如下: mysite/ ma

win10启动django项目报错 Django RuntimeError: maximum recursion depth exceeded

错误:Django RuntimeError: maximum recursion depth exceeded 原因出自Python\Lib\fuctools.py 把 convert = {    '__lt__': [('__gt__', lambda self, other: other < self),                ('__le__', lambda self, other: not other < self),                ('__ge__', 

猫猫学iOS 之微博项目实战(9)微博模型之时间相关重要操作,判断刚刚,昨天,今年等等

猫猫分享,必须精品 原创文章,欢迎转载.转载请注明:翟乃玉的博客 地址:http://blog.csdn.net/u013357243 一:效果 --因为本人黑苹果,系统时间乱跳 时间显示的不准,但是代码没有问题 二:实现代码 /** 1.今年 1> 今天 * 1分内: 刚刚 * 1分~59分内:xx分钟前 * 大于60分钟:xx小时前 2> 昨天 * 昨天 xx:xx 3> 其他 * xx-xx xx:xx 2.非今年 1> xxxx-xx-xx xx:xx */ - (NSSt

Django基础五之django模型层(二)多表操作

目录 一 创建模型 关于db_column和verbose_name 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询(基于join实现的) 进阶练习(连续跨表) 五 聚合查询.分组查询.F查询和Q查询 查询练习 F查询与Q查询 F查询 Q查询 六 ORM执行原生sql语句(了解) 执行原生查询 直接执行自定义SQL 七 Python脚本中调用Django环境(django外部脚本使用models) 八 补充多个app配置models 本节目录 一 创建模型 表和表之间的关系

Web框架之Django_02基本操作(Django项目启动配置、数据库连接、orm、增删改查)

摘要: Django项目简单现实过程 pycharm连接数据库 Django之orm简单操作增删改查 一.新建Django项目.配置.设置: 新建Django项目:(为了熟悉Django操作,暂时全部用cmd形式来实现,很多地方需要手动添加)项目目录D:\Django: >>管理员权限打开cmd,通过cmd命令进入项目目录 >>django-admin startproject my_Dproject (创建项目) >>cd my_Dproject (进入项目文件夹)