http://blog.csdn.net/pipisorry/article/details/45725953
Django数据库字段类型(Field types)
它是一个根据 ID 自增长的 IntegerField 字段。通常,你不必直接使用该字段。如果你没在别的字段上指定主键,Django 就会自动添加主键字段。详见 自增主键字段(Automatic primary key fields)。
一个布尔值(true/false)字段。Django 的管理后台用checkbox来表现该字段类型。
MySQL 用户请注意:
布尔字段在 MySQL 中被存储为 TINYINT 列。它的值只能是 0 或 1 (其他大多数据库都有适用的 BOOLEAN 类型)。所以仅在使用 MySQL 的情况下,从数据库中检索 BooleanField 并保存为 model 的属性,这时属性值是 1 或是 0 ,而不是 True 或 False 。正常情况下,这不会引起问题,因为 Python 保证令 1 == True 和 0 == False 都是有效的。只是在你编写类似 obj isTrue 语句时,如果 obj 正是 model 的一个布尔属性值,那你就要留心注意了。因为在使用 mysql 数据库时,"is" 操作是无效的。在这种场合下,使用相等判断更好(使用 "==")。
Django 的管理后台用 <input type="text"> (单行输入框) 来表示这种字段。
CharField 有一个必须传入的参数,字段的最大字符数。它作用于数据库层级和 Django 的数据验证层级。
注意:如果你正在编写的应用要求满足多种数据库,那么你就要注意不同数据库对 max_length 有不同的限制。详见 数据库 (database backend notes) 。
MySQL 用户请注意:
如果你使用 MySQLdb 1.2.2 和 utf8_bin 字符集(非默认设置),有几点注意事项要格外留意。详见 MySQL 数据库 (MySQL database notes) 。
它用来存放以逗号间隔的整数序列。和 CharField 一样,必须为它提供 max_length 参数。而且要注意不同数据库对 max_length 的限制。
时间字段
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)DateField
该字段利用 Python 的 datetime.date 实例来表示日期。下面是它额外的可选参数:
Django 管理后台使用一个带有 Javascript 日历的 <input type="text"> 来表示该字段,它带有一个当前日期的快捷选择。那个 JavaScript 日历总是以星期天做为一个星期的第一天。
该字段利用 datetime.datetime 实例表示日期和时间。该字段所按受的参数和 DateField 一样。
Django 的管理后台使用两个 <input type="text"> 分别表示日期和时间,同样也带有 JavaScript 快捷选项。
该字段使用 Python 的 datetime.time 实例来表示时间。它和 DateField 接受同样的自动填充的参数。Django 管理后台使用一个带 Javascript 快捷链接 的 <input type="text"> 表示该字段。
它是使用 Decimal 实例表示固定精度的十进制数的字段。它有两个必须的参数:
例如,要存储的数字最大值是999,而带有两个小数位,你可以使用:
models.DecimalField(..., max_digits=5, decimal_places=2)
要存储大约是十亿级且带有10个小数位的数字,就这样写:
models.DecimalField(..., max_digits=19, decimal_places=10)
Django 管理后台使用 <input type="text"> (单行输入框) 表示该字段。
文件上传字段
注意:该字段不支持 primary_key 和 unique 参数,否则会抛出 TypeError 异常。
它有一个必须的参数:FileField.upload_to
用于保存文件的本地文件系统。它根据 MEDIA_ROOT 设置确定该文件的 url 属性。
该路径可以包含 时间格式串 (strftime formatting),可以在上传文件的时候替换成当时日期/时间(这样,就不会出现在上传文件把某个目录塞满的情况了)。
该参数也可以是一个可调用项,比如是一个函式,可以调用函式获得包含文件名的上传路径。这个可调用项必须要接受两个参数,并且返回一个保存文件用的 Unix-Style 的路径(用 / 斜杠)。两个参数分别是:
参数 | 描述 |
---|---|
instance | 定义了当前 FileField 的 model 实例。更准确地说,就是以该文件为附件的 model 实例。 大多数情况下,在保存该文件时, model 实例对象还并没有保存到数据库,这是因为它很有可能使用默认的 AutoField,而此时它还没有从数据库中获得主键值。(用法见oteam的http://oteam.cn/2008/10/4/dynamic-upload-paths-in-django/) |
filename | 上传文件的原始名称。在生成最终路径的时候,有可能会用到它。 |
还有一个可选的参数:
负责保存和获取文件的对象。详见 Managing files。
Django 管理后台使用 <input type="file"> (一个文件上传的部件) 来表示这个对象。
在 model 中使用 FileField 或 ImageField (稍后提到) 要按照以下的步骤:
例如,假设你的 MEDIA_ROOT 被设为 '/home/media',upload_to 被设为 'photos/%Y/%m/%d'。 upload_to 中的 '%Y/%m/%d' 是一个 时间格式字符串 (strftime formatting); '%Y' 是四位的年分,'%m' 是两位的月分, '%d' 是两位的日子。如果你在2007年01月15号上传了一个文件,那么这个文件就保存在 /home/media/photos/2007/01/15 目录下。
如果你想得到上传文件的本地文件名称,文件网址,或是文件的大小,你可以使用 name, url 和 size 属性;详见 管理文件 (Managing files)。
注意:在上传文件时,要警惕保存文件的位置和文件的类型,这么做的原因是为了避免安全漏洞。对每一个上传文件都要验证,这样你才能确保上传的文件是你想要的文件。举个例子,如果你盲目地让别人上传文件,而没有对上传文件进行验证,如果保存文件的目录处于 web 服务器的根目录下,万一有人上传了一个 CGI 或是 PHP 脚本,然后通过访问脚本网址来运行上传的脚本,那可就太危险了。千万不要让这样的事情发生!
默认情况下,FileField 实例在数据库中的对应列是 varchar(100) ,和其他字段一样,你可以利用 max_length 参数改变字段的最大长度。
它是一个 CharField ,它用来选择文件系统下某个目录里面的某些文件。它有三个专有的参数,只有第一个参数是必须的:
当然,这三个参数可以同时使用。
前面已经提到了 match 只匹配文件名称,而不是文件路径。所以下面这个例子:
FilePathField(path="/home/images", match="foo.*", recursive=True)
将匹配 /home/images/foo.gif ,而不匹配 /home/images/foo/bar.gif。这是因为 match 只匹配文件名 (foo.gif 和 bar.gif).
默认情况下, FilePathField 实例在数据库中的对应列是s varchar(100) 。和其他字段一样,你可以利用 max_length 参数改变字段的最大升序。
该字段在 Python 中使用by a float 实例来表示一个浮点数。
Django 管理后台用 <input type="text"> (一个单行输入框) 表示该字段。
和 FileField 一样,只是会验证上传对象是不是一个合法的图象文件。它有两个可选参数:
除了那些在 FileField 中有效的参数之外, ImageField 还可以使用 File.height and File.width 两个属性。详见管理文件 (Managing files)(但并没有找到这两个参数的介绍)。使用该字段要求安装 Python Imaging Library(PIL).
这部分是在 Django 1.0 中新增的: 在新版本中新加了 max_length 参数。默认情况下, ImageField 实例对应着数据库中的 created as varchar(100) 列。和其他字段一样,你可以使用 max_length 参数来改变字段的最大长度。
整数字段。Django 管理后台用 <input type="text"> (一个单行输入框) 表示该字段。
以字符串形式(比如 192.0.2.30)表示 IP 地址字段。Django 管理后台使用 <input type="text"> (一个单行输入框) 表示该字段。
与 BooleanField 相似,但多了一个 NULL 选项。建议用该字段代替使用 null=True 选项的 BooleanField 。Django 管理后台使用 <select> 选择框来表示该字段,选择框有三个选项,分别是 "Unknown", "Yes" 和 "No" 。
Slug 是一个新闻术语,是指某个事件的短标签。它只能由字母,数字,下划线或连字符组成。通赏情况下,它被用做网址的一部分。
和 CharField 类似,你可以指定 max_length (要注意数据库兼容性和本节提到的 max_length )。如果没有指定 max_length ,Django 会默认字段长度为50。该字段会自动设置 Field.db_index to True。基于其他字段的值来自动填充 Slug 字段是很有用的。你可以在 Django 的管理后台中使用 prepopulated_fields 来做到这一点。
文本字段TextField
大文本字段。Django 的管理后台使用 <textarea> (一个多行文本框) 表示该字段。
MySQL 用户请注意:如果你正在使用 MySQLdb 1.2.1p2 和 utf8_bin 字符集(非默认设置),有几点注意事项要格外留意,详见 MySQL database notes 。
TextField中输入换行出现问题:
1. 在TextField中输入带换行的文字,存到数据库后发现是\r\n。但是我的django是在linux上运行的,其他程序都是默认换行是\n的。我如何指定TextField中输入的换行是\n而不是两个?
方法1. 使用模版内部内置的filter: linebreaks
Replaces line breaks in plain text with appropriate HTML; a single newline becomes an HTML line break (<br />) and a new line followed by a blank line becomes a paragraph break (</p>).
{% for news in newss %} <p>{{ news.content|linebreaks }}</p>方法2. 修改model代码
suggest you to override the save method of your model,replacing new line characters to the preferred format:
class MyModel(models.Model):
body_text = models.TextField()
...
def save(self):
self.body_text = self.body_text.replace("\r\n", "\n")
self.body_text = self.body_text.replace("\r", "\n")
super(MyModel, self).save()
[http://markmail.org/message/pro4hiqv3s6v6eb6]
方法3. template rendering 自动 escape HTML tag,需要关掉,比如 |safe 试试
[Django的TextField怎么才能处理空格和回车换行?]
[http://markmail.org/message/ovti7o33qfonsj3c]
Django 管理后台使用 <input type="text"> (一个单行输入框) 表示该字段。
和所有 CharField 子类一样,URLField 接受可选的 max_length 参数,该参数默认值是200。
这是一个根据给定的 schema 验证所输文本是否是合法 XML 的 TextField 字段。它有一个必需的参数:
[Model 字段参考 (Model field reference)]
[Model field reference]
[DjangoModels模块]
http://blog.csdn.net/pipisorry/article/details/45725953
Django数据库字段选项(Field options)
下列参数对所有字段类型都是有效的,同时这些参数也是可选的。
如果为 True ,Django 就会将空值(empty)存储为数据库中的 NULL 。默认值是 False。
要注意空字符串(empty string)总是被存储为空字符串,而不是 NULL。 null=True 只对非字符串字段有意义,比如整数(integer),布尔值(boolean),日期(dates)。如果你允许表单提交空值,无论是哪种字段,你还要再设置 blank=True ,这是因为 null 仅仅影响数据库存储 (详见 blank)。
除非你有很充分的理由,否则不要在字符串字段(比如CharField 和 TextField)上使用 null 。在字符串字段上声明 null=True ,就意味着有两种意义的空值:NULL,和空字符串(empty string)。大多数情况下,存在两种空值是多余的。Django 按惯例是使用空字符串,而非 NULL 。
注意:在使用 Oracle 数据库时,null=True 选项将被强加到有可能是空值的字符串字段,而且会在数据库中保存 NULL ,来表示空字符串。
要注意该选项与 null 不同。 null 纯粹是数据库范畴的概念,而 blank 是数据验证范畴的。如果某个字段声明了 blank=True,那么 Django 的管理后台就允许该字段填写空值;否则,如果声明为 blank=False,该字段就是必填的。
class Foo(models.Model):
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
MEDIA_CHOICES = (
('Audio', (
('vinyl', 'Vinyl'),
('cd', 'CD'),
)
),
('Video', (
('vhs', 'VHS Tape'),
('dvd', 'DVD'),
)
),
('unknown', 'Unknown'),
)
每个元组中的第一个元素会用做组的命名。第二个元素是一个可迭代的二元组,每个二元组都包含一个一个值和一个易于理解的描述。分组选项可以和未分组选项组合在一个单独的列表当中(比如上例中的 unknown 项)。
Djanog 会对设置了 choices 的字段添加一个方法。这个方法根据该字段的当前值获取它易于理解的描述。详见数据库 API 文档中的 get_FOO_display() 。
最后注意一点,choices 可以是任何可迭代的对象,并不仅仅只是列表或是元组。这意味着你可以构造动态的 choices ,不过你最好通过 ForeignKey 使用一张适合的数据表来构造动态 choices。毕竟 choices 适用于变动不大的静态数据。
该字段在数据库中所使用的列名称。如果没有声明,Django 就会以该字段的名称做为列名。
列名称可以是 SQL 保留字,也可以包含不允许出现在 Python 变量名的特殊字符,比如连字符。这是因为 Django 会在幕后给列名和表名加上引号。
如果为 True,运行 django-admin.py sqlindexes <sqlindexes> 会为该字段输出一条 CREATE INDEX 语句。
如果该字段是索引字段,db_tablespace 就表示该索引所在的数据库表空间的名称。如果项目配置文件中设定了 DEFAULT_INDEX_TABLESPACE ,那么默认值就是配置项的值;如果你指定了该 model 中 Meta 内嵌类的 db_tablespace ,那么默认值就是 Meta 中 db_tablespace 的值。如果数据库不支持表空间,就会忽略该选项。
该字段的默认值。它可以是一个值,也可以是一个可调用的对象(这里称之为对象C)。若是后者,那么每次创建一个新对象时,对象C都将被调用。
如果为 False ,那么在 Django 管理后台中就不会编辑该字段;同样,在 Django 自动生成的表单中也不会编辑该字段。默认值是 True 。
附加的提示信息。在管理后台编辑该对象的表单中,它显示在该字段下面。即使你的对象无须在后台管理,对于文档化也是很用的。
注意,在管理后台显示该提示信息时,并不会对其转义。所以你可以在 help_text 中包含 HTML 。例如:
help_text="Please use the following format: <em>YYYY-MM-DD</em>."
你也可以使用纯文本,还可以用 django.utils.html.escape() 转义任何 HTML 字符。
如果为 True,那么该字段就是 model 的主键。
如果你没有指定任何一个字段的 primary_key=True ,Django 就会自动添加一个 IntegerField 做为主键字段。所以除非你想重写默认的主键行为,否则没必要在任何字段上设置primary_key=True 。详见 自增主键字段 (Automatic primary key fields) 。
primary_key=True 意味着 null=False 和 unique=True 。一个对象只能有一个主键。
如果为 True,该字段值就必须是全表唯一的。
它同时作用于数据库层级以及 Django 的管理后台和表单层级。如果你保存 model 时,某个 unique 字段的值是重复的,那么 save() 方法就会抛出 django.db.IntegrityError 异常。
这个选项在所有的字段上都是可用的,除了 ManyToManyField 和 FileField 以外。
如果要求在某个日期内,该字段值在数据表中是唯一的(就不存在时期和字段值都相同的记录),那就可以将 unique_for_date 设置为某个 DateField 或 DateTimeField 的名称。
例如,假设你有一个声明了 unique_for_date="pub_date" 的 title 字段,那么 Django 就不会允许出现 title 和 pub_date 相同的两条记录。
它作用于 Django 的管理后台和表单层级,而非数据库层级。
该字段易于理解的名称。如果没有提供自述名,Django 会根据字段的属性名自动创建自述名--就是将属性名称中的空格替换成下划线。详见 字段的自述名(Verbose field names).
http://blog.csdn.net/pipisorry/article/details/45725953
模型元编程——元属性
class People(models.Model): name = models.CharField(max_length=150, verbose_name='姓名') #... ... class Meta: abstract = True db_table = 'People'Note:
1. Meta中设置abstract = Ture后,类People就是一个抽象类,不会在数据库中建立表?,并且也不能添加到admin后台管理中
2. Meta中设置db_talbe = ‘People’后,类People在数据库中建表后,表名为‘People'而不是默认的appname_people
Django站点管理(后台管理员)-自定义管理工具-自定义模块表现
http://blog.csdn.net/pipisorry/article/details/45725953
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:
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的模型不只是为对象定义了数据库表的结构,还定义了对象的行为。
插入和更新数据
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:
我们很少会一次性从数据库中取出所有的数据;通常都只针对一部分数据进行操作。 在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>]
在 name 和 contains 之间有双下划线。和Python一样,Django也使用双下划线来表明会进行一些魔术般的操作。这里,contains部分会被Django翻译成LIKE语句:
SELECT id, name, address, city, state_province, country, website FROM books_publisher WHERE name LIKE '%press%';
其他的一些查找类型有:icontains(大小写无关的LIKE),startswith和endswith, 还有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查询就是 WHERE 和ORDERBY 的组合:
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()
模型继承
django中的继承有三类;
1.抽象继承
2.多表继承
3.proxy model(代理模型)
抽象继承
第1种情况表示你的父类仅仅是包含了多个子类的相同的字段,是为了重用,不会建表,我们只需要在抽象父类的Meta中设置abstract=True就行。
class Base(models.Model): ''' 基类 ''' # title = models.CharField(max_length=150, default='') title = models.CharField(max_length=150, null=True) content = models.TextField(null=True) time_stamp = models.DateTimeField(auto_now_add=True, default=timezone.now()) link = models.URLField(blank=True, verbose_name='url_link') class Meta: abstract = TrueNote:如果在抽象父类和子类中出现相同的字段名字,django会引发异常。
对于内联的Meta类的继承,一般的,父类的Meta类的属性会继承给子类,子类也可以在自己的Meta中重写或者拓展父类的Meta,拓展的话主要是继承父类的Meta:
在抽象类中使用关系(如外键,多对多关系,一对一关系)时候,肯定会设置related_name,但是子类继承抽象父类的时候,由于父类中的字段会继承给子类,则具有related_name的字段会被多个子类共享的。这样每一个子类的related_name就都一样了,其他模型通过related_name就不能找到正确的子类。
所以要正确设置related_name,related_name中必须包含%(app_label)s 和 %(class)s。如
%(app_label)s表示小写形式的,当前模型所在的,并且已经安装的app的名字
%(class)s表示小写形式的,当前子类的类名字。
在common/models.py,有
多表继承
其中父类也是一个django模型,并且也会创建一个数据表,多表继承是django中隐式的一对一关系。例如
Restaurant和Place的关系,可以这么说:一个Restaurant一定是一个Place,而一个Place不一定是Restaurant
多表继承中,一般,父类的Meta属性不会继承到子类中,但是,ordering和 get_latest_by是继承的,如果子类不想继承父类的ordering的Meta,则可以手动显式的指定ordering=[]或者任何自己想要的值
多表继承的时候,是隐式的在父类和子类之间建立一个一对一关系,所以有时候,父类与其他类的关系会从父类下移到子类中。如果有多个子类,且子类不在关系中显式地指定related_name字段,django会引发验证错误
所以,继承父类,一旦子类中有关系,就加上related_name吧
django自动在子类和非抽象父类之间创建一个一对一关系,如果你想控制由子类连接回父类的属性的名字,你可以创建一个一对一关系,然后设置parent_link=True
代理模型
在多表继承中,子类模型会创建一个数据表来存储不在父类模型中的额外字段,但是,如果我们只想改变某个模型的行为方法,而不是添加额外的字段,我们就可以使用
proxy model。代理model(proxy model)会继承父类的属性,并且只是添加一些对属性的操作的自定义方法而已。
这里,MyPerson没有多创建数据表,MyPerson也是对Person的数据表进行操作,一般的,我们可以把MyPerson当做Person来使用,只是在do_something这个方法略有不同,比如
代理模型和原模型的区别如下面:
OrderPerson返回的queryset自然是Person的,这是当然的。我们不能要求django返回OrderedPerson类的queryset,因为OrderedPerson只是代理而已,又不是真实的数据库表类。
注意的是,proxy model不能继承于抽象类,这是因为代理model是操作连接数据库的,也不能多重继承~因为你多重继承了,代理model就不知道去哪个父类找属性了
如果不指定代理 model 的 manage ,则代理 model 会自动继承父类的 manage 。我们也可以手动设置代理 model 的 manage ,这样,代理模型和父类模型的manage就分开了为代理模型添加manage有两种方法:
一是直接在代理模型中直接指定manage
[django学习记录-模型继承]
from:http://blog.csdn.net/pipisorry/article/details/45725953