当前位置:Gxlcms > 数据库问题 > Django项目实践3 - Django模型(数据库字段及操作)

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

时间:2021-07-01 10:21:17 帮助过:20人阅读

时间字段

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


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

标签:django   数据库   管理   sql   数据库字段   

人气教程排行