django关于modles

1.ORM

对象-关系映射(OBJECT/RELATIONALMAPPING,简称ORM),是随着面向对象的软件开发方法发展而产生的。用来把对象模型表示的对象映射到基于S Q L 的关系模型数据库结构中去。这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的 SQ L 语句打交道,只需简单的操作实体对象的属性和方法 。O R M 技术是在对象和关系之间提供了一条桥梁,前台的对象型数据和数据库中的关系型的数据通过这个桥梁来相互转化。

ORM即object relational mapping, 对象关系映射, 是利用面向对象的方式来操作数据库,一个类就代表一张表,通过调用类的实例的属性和方法就可以对数据库中的内容进行操作;

2.Field(字段)
django中的ORM使用Field类向表中添加字段;
共有以下几种类型;
(1)AutoField

class AutoField(**options)
An IntegerField that automatically increments according to available IDs. You usually won’t need to use this
directly; a primary key field will automatically be added to your model if you don’t specify otherwise. See Automatic
primary key fields.

By default, Django gives each model the following field:
id = models.AutoField(primary_key=True)
This is an auto-incrementing primary key.
If you’d like to specify a custom primary key, just specify primary_key=True on one of your fields. If Django
sees you’ve explicitly set Field.primary_key, it won’t add the automatic id column.
Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically
added).

可以根据可用ID自增的IntegerField, 你一般不会直接使用它,当你的类中没有定义主键时会自动添加字段:
id = models.AutoField(primary_key=True)
如果不想自动添加该字段,那就需要显式的指定主键字段(设定primary_key=True);

(2)BinaryField

class BinaryField(max_length=None, **options)
A field to store raw binary data. It can be assigned bytes, bytearray, or memoryview.
By default, BinaryField sets editable to False, in which case it can’t be included in a ModelForm.
Older versions don’t allow setting editable to True.

BinaryField has one extra optional argument:
BinaryField.max_length
The maximum length (in characters) of the field. The maximum length is enforced in Django’s validation using
MaxLengthValidator.

存储原始二进制数据的字段,可以赋值的类型为bytes, bytearray, or memoryview;默认情况下该字段设置为不可编辑的, 在这种情况下不能包含在ModelForm中;

有一个可选参数max_length,指定数据的最大长度, 在django中需要强制指定;

Although you might think about storing files in the database, consider that it is bad design in 99% of the cases. This
field is not a replacement for proper static files handling.
使用此字段存储文件并不是一个好的选择, 它不能替代正确的静态文件处理;

(3)BooleanField

class BooleanField(**options)
A true/false field.
The default form widget for this field is CheckboxInput, or NullBooleanSelect if null=True.
The default value of BooleanField is None when Field.default isn’t defined.
In older versions, this field doesn’t permit null=True, so you have to use NullBooleanField instead. Using the latter is now discouraged as it’s likely to be deprecated in a future version of Django.

存储true/false的字段;
当dafault参数未定义时,该字段默认值为None;

(4)CharField

class CharField(max_length=None, **options)
A string field, for small- to large-sized strings.
For large amounts of text, use TextField.
The default form widget for this field is a TextInput.
CharField has one extra required argument:
CharField.max_length
The maximum length (in characters) of the field. The max_length is enforced at the database level and in
Django’s validation using MaxLengthValidator.

存储字符串的字段, 字符串的大小从small到large;
如果要存储更大的字符串,那么应该使用TextField;
该字段有一个额外的必须参数max_length:最大长度,按字符计算;

Note: If you are writing an application that must be portable to multiple database backends, you should be aware that
there are restrictions on max_length for some backends. Refer to the database backend notes for details.
注意:如果你正在写一个可移植到多个数据库后端的应用, 你应该意识到有些后端对最大长度是有限制的;

(5)DateField

class DateField(auto_now=False, auto_now_add=False, **options)
A date, represented in Python by a datetime.date instance. Has a few extra, optional arguments:

日期字段,在python中以datetime.date实例表示;有两个额外可选参数:

1)DateField.auto_now
Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. Note that the current date is always used; it’s not just a default value that you can override.
The field is only automatically updated when calling Model.save(). The field isn’t updated when making updates to other fields in other ways such as QuerySet.update(), though you can specify a custom value for the field in an update like that.

auto_now参数:如果该参数设为True,那么在对象每次保存时都会自动将该字段更新为现在的时间; 在需要使用 "最后一次更改"的情况下非常有用; 但需要注意的是, 它总是使用现在的日期,而不只是可以覆盖的默认值, 只有在对象调用save()方法时才会自动更新, 使用update()方法并不会自动更新,即使你可以用该方法为其指定一个日期;

2)DateField.auto_now_add
Automatically set the field to now when the object is first created. Useful for creation of timestamps. Note that the current date is always used; it’s not just a default value that you can override. So even if you set a value for this field when creating the object, it will be ignored. If you want to be able to modify this field, set the following instead of auto_now_add=True:
• For DateField: default=date.today - from datetime.date.today()
• For DateTimeField: default=timezone.now - from django.utils.timezone.now()

auto_now_add参数: 当对象被创建时自动添加当前日期, 用在需要创建日期的场景; 注意:**它总是使用当前日期, 而不只是可以覆盖的默认值,即使你在创建时自己指定日期,它也会无视,直接使用现在的日期. **如果你想修改该字段,需要设置如下:
• For DateField: default=date.today - from datetime.date.today()
• For DateTimeField: default=timezone.now - from django.utils.timezone.now()

The default form widget for this field is a TextInput. The admin adds a JavaScript calendar, and a shortcut for
“Today”. Includes an additional invalid_date error message key.
The options auto_now_add, auto_now, and default are mutually exclusive. Any combination of these options
will result in an error.
选项auto_now_add,auto_now和default是互斥的。 这些选项的任意组合会导致错误。

Note: As currently implemented, setting auto_now or auto_now_add to True will cause the field to have editable=False and blank=True set.
在当前的实现中,设置以上两个参数会导致参数editable=False 和blank=True.

Note: The auto_now and auto_now_add options will always use the date in the default timezone at the moment of creation or update. If you need something different, you may want to consider simply using your own callable default or overriding save() instead of using auto_now or auto_now_add; or using a DateTimeField instead of a DateField and deciding how to handle the conversion from datetime to date at display time.
以上两个参数使用的是默认时区的时间, 如果你想展示不同时区的时间,那就需要自定义或者覆盖save()方法了. 或者使用DateTimeField字段,并处理datetime到date的转换;

(6)DateTimeField

class DateTimeField(auto_now=False, auto_now_add=False, **options)
A date and time, represented in Python by a datetime.datetime instance. Takes the same extra arguments as DateField.
The default form widget for this field is a single TextInput. The admin uses two separate TextInput widgets with JavaScript shortcuts.

日期时间字段, 参数和DateField相同;

(7)DecimalField

class DecimalField(max_digits=None, decimal_places=None, **options)
A fixed-precision decimal number, represented in Python by a Decimal instance. It validates the input using DecimalValidator.
Has two required arguments:

存储固定精度十进制小数,在python中以decimal实例显示;有两个参数:

1)DecimalField.max_digits
The maximum number of digits allowed in the number. Note that this number must be greater than or equal to decimal_places.
小数的总位数,必须大于等于decimal_places参数;

2)DecimalField.decimal_places
The number of decimal places to store with the number.
小数位数

The default form widget for this field is a NumberInput when localize is False or TextInput otherwise.

(8)FloatField

class FloatField(**options)
A floating-point number represented in Python by a float instance.
The default form widget for this field is a NumberInput when localize is False or TextInput otherwise.

浮点数字段,在python中以浮点数对象的形式呈现;

FloatField vs. DecimalField
The FloatField class is sometimes mixed up with the DecimalField class. Although they both represent real numbers, they represent those numbers differently. FloatField uses Python’s float type internally, while
DecimalField uses Python’s Decimal type. For information on the difference between the two, see Python’s documentation for the decimal module.
FloatField和DecimalField: 都用来表示实数, 但在内部FloatField使用python的float类型,而后者使用python的decimal类型;

(9)FileField

class FileField(upload_to=None, max_length=100, **options)
A file-upload field.
Note: The primary_key argument isn’t supported and will raise an error if used. Has two optional arguments:

用于存储上传文件的字段;需要注意的是主键不能设置在该字段上;

1)FileField.upload_to
This attribute provides a way of setting the upload directory and file name, and can be set in two ways. In both cases, the value is passed to the Storage.save() method.
If you specify a string value, it may contain strftime() formatting, which will be replaced by the date/time of the file upload (so that uploaded files don’t fill up the given directory). For example:

class MyModel(models.Model):
#file will be uploaded to MEDIA_ROOT/uploads
upload = models.FileField(upload_to='uploads/')
#or...
#file will be saved to MEDIA_ROOT/uploads/2015/01/30
upload = models.FileField(upload_to='uploads/%Y/%m/%d/')

If you are using the default FileSystemStorage, the string value will be appended to your MEDIA_ROOT path to form the location on the local filesystem where uploaded files will be stored. If you are using a different storage, check that storage’s documentation to see how it handles upload_to.

upload_to may also be a callable, such as a function. This will be called to obtain the upload path, including the filename. This callable must accept two arguments and return a Unix-style path (with forward slashes) to be passed along to the storage system. The two arguments are:

upload_to参数:设定上传文件的保存路径和文件名, 可以通过两种方式,一种为指定一个字符串,字符串中可能包括strftime()格式, 该格式会被替换为文件上传的时间;示例见上面; 如果使用的是默认的文件存储系统的话, 字符串将会加到MEDIA_ROOT路径后形成上传文件的最终保存目录;
另一种方式为指定一个可调用对象,例如函数;通过调用它来获得存储路径和文件名;这个函数必须传入两个参数, 返回一个Unix格式的路径(带正斜杠)传递到存储系统,这两个参数为:

instance :An instance of the model where the FileField is defined. More specifically, this is the particular instance where the current file is being attached. In most cases, this object will not have been saved to the database yet, so if it uses the default AutoField, it might not yet have a value for its primary key field.

FileField的模型的实例。 更具体地说,这是附加当前文件的特定实例。 在大多数情况下,此对象尚未保存到数据库,因此如果它使用默认的AutoField,则它可能还没有其主键字段的值。

filenname: The filename that was originally given to the file. This may or may not be taken into account when determining the final destination path.

最初提供给文件的文件名,确定最终存储路径时有可能使用或不使用;
示例:

def user_directory_path(instance, filename):
#file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'user_{0}/{1}'.format(instance.user.id, filename)

class MyModel(models.Model):
upload = models.FileField(upload_to=user_directory_path)

2)FileField.storage
A storage object, which handles the storage and retrieval of your files. See Managing files for details on how to provide this object.
处理文件的存储和检索;

The default form widget for this field is a ClearableFileInput.

3)使用FileField和ImageField的几大步骤:

Using a FileField or an ImageField (see below) in a model takes a few steps:

  1. In your settings file, you’ll need to define MEDIA_ROOT as the full path to a directory where you’d like Django to store uploaded files. (For performance, these files are not stored in the database.) Define MEDIA_URL as the base public URL of that directory. Make sure that this directory is writable by the Web server’s user account.
  2. Add the FileField or ImageField to your model, defining the upload_to option to specify a subdirectory of MEDIA_ROOT to use for uploaded files.
  3. All that will be stored in your database is a path to the file (relative to MEDIA_ROOT). You’ll most likely want to use the convenience url attribute provided by Django. For example, if your ImageField is called mug_shot, you can get the absolute path to your image in a template with {{ object.mug_shot.url}}.
    出于性能考虑,上传的文件不会存储在数据库中,而是存储在磁盘文件夹中,数据库中只存储指向该文件的相对路径(相对于MEDIA_ROOT),例如,如果你想访问该文件的绝对路径,调取 “object.字段名.url”;

4)访问上传文件的文件名或文件大小的方式: 调用size和name属性, 更多属性查看相关文档;

If you wanted to retrieve the uploaded file’s on-disk filename, or the file’s size, you could use the name and size attributes respectively; for more information on the available attributes and methods, see the File class reference and the Managing files topic guide.

5)注意:

Note: The file is saved as part of saving the model in the database, so the actual file name used on disk cannot be relied on until after the model has been saved.
The uploaded file’s relative URL can be obtained using the url attribute. Internally, this calls the url() method of the underlying Storage class.
在保存模型之前,不能依赖磁盘上使用的实际文件名。
可以使用url属性获取上传文件的相对URL。 在内部,这会调用底层类Storage的url()方法。

Note that whenever you deal with uploaded files, you should pay close attention to where you’re uploading them and what type of files they are, to avoid security holes. Validate all uploaded files so that you’re sure the files are what you think they are. For example, if you blindly let somebody upload files, without validation, to a directory that’s within your Web server’s document root, then somebody could upload a CGI or PHP script and execute that script by visiting its URL on your site. Don’t allow that.
Also note that even an uploaded HTML file, since it can be executed by the browser (though not by the server), can pose security threats that are equivalent to XSS or CSRF attacks.
一些要注意的安全事项;

FileField instances are created in your database as varchar columns with a default max length of 100 characters. As with other fields, you can change the maximum length using the max_length argument.
默认最大长度为100,可以自己设置max_length;

6)FileField and FieldFile

class FieldFile
When you access a FileField on a model, you are given an instance of FieldFile as a proxy for accessing the underlying file.
The API of FieldFile mirrors that of File, with one key difference: The object wrapped by the class is not necessarily a wrapper around Python’s built-in file object. Instead, it is a wrapper around the result of the Storage.
open() method, which may be a File object, or it may be a custom storage’s implementation of the File API.
In addition to the API inherited from File such as read() and write(), FieldFile includes several methods that can be used to interact with the underlying file:
Warning: Two methods of this class, save() and delete(), default to saving the model object of the associated FieldFile in the database.

当你访问模型上的FileField时, 会给 你一个FieldFile实例,作为访问底层文件的代理;
FieldFile的API镜像了文件的API,但有一个关键不同:类包装的对象不一定是内置文件对象的包装器;相反,它是Storage的包装器;
注意:该类的save()和delete()方法默认将相关模型对象保存入数据库;
除了从文件对象继承的read()和write()方法外, FieldFile还包括和底层文件交互的其他几个方法:
1)FieldFile.name

The name of the file including the relative path from the root of the Storage of the associated FileField.

文件名,包括相关文件字段的存储根目录的相对路径;

2)FieldFile.size

The result of the underlying Storage.size() method.

底层Storage.size()的结果;

3)FieldFile.url

A read-only property to access the file’s relative URL by calling the url() method of the underlying Storage class.

只读属性,访问文件的相关URL(通过调用底层Storage的url()方法)

 b = obj.cleaned_data
 a = b.get('photo', None)
stu = Students.objects.get(id=1)
                stu.img = a
                stu.save()
                print(stu.img)
                print(stu.img.url)
                print(stu.img.name)
#result
uploads/2018-12-22/迭代器iterator.png
/media/uploads/2018-12-22/%E8%BF%AD%E4%BB%A3%E5%99%A8iterator.png
uploads/2018-12-22/迭代器iterator.png

4)FieldFile.open(mode=’rb’)

Opens or reopens the file associated with this instance in the specified mode. Unlike the standard Python open() method, it doesn’t return a file descriptor.
Since the underlying file is opened implicitly when accessing it, it may be unnecessary to call this method except to reset the pointer to the underlying file or to change the mode.

在指定模式下打开或重新打开实例相关的文件, 和python的open()方法不同,并不会返回文件描述符;
因为底层文件是隐式打开的, 因此除非更改模式或重置文件中的指针,可能无需调用此方法;

5)FieldFile.close()

Behaves like the standard Python file.close() method and closes the file associated with this instance.

和python文件的close()方法相同;

6)FieldFile.save(name, content, save=True)

This method takes a filename and file contents and passes them to the storage class for the field, then associates the stored file with the model field. If you want to manually associate file data with FileField instances on your model, the save() method is used to persist that file data.

此方法获取文件名和文件内容,并将它们传递给该字段的存储类,然后将存储的文件与模型字段相关联。 如果要手动将文件数据与模型上的FileField实例关联,则save()方法用于保留该文件数据。

Takes two required arguments: name which is the name of the file, and content which is an object containing the file’s contents. The optional save argument controls whether or not the model instance is saved after the file associated with this field has been altered. Defaults to True.
Note that the content argument should be an instance of django.core.files.File, not Python’s built-in file object. You can construct a File from an existing Python file object like this:

from django.core.files import File
#Open an existing file using Python's built-in open()
f = open('/path/to/hello.world')
myfile = File(f)
#Or you can construct one from a Python string like this:
from django.core.files.base import ContentFile
myfile = ContentFile("hello world")

7)FieldFile.delete(save=True)

Deletes the file associated with this instance and clears all attributes on the field. Note: This method will close the file if it happens to be open when delete() is called.
The optional save argument controls whether or not the model instance is saved after the file associated with this field has been deleted. Defaults to True.
Note that when a model is deleted, related files are not deleted. If you need to cleanup orphaned files, you’ll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).

删除实例相关联的文件并清空所有属性;注意, 此方法将会关闭文件如果删除时文件是打开状态; 可选参数save控制是否在删除文件后保存实例;
注意当模型被删除时,相关文件并不会删除,你需要手动操作;

(10)FilePathField

class FilePathField(path=None, match=None, recursive=False, max_length=100, **options)
A CharField whose choices are limited to the filenames in a certain directory on the filesystem. Has three special arguments, of which the first is required:

特殊的CharField, 内容只限于某个目录下的文件名;有3个可选参数, 第一个是必须给出的:

1)FilePathField.path
Required. The absolute filesystem path to a directory from which this FilePathField should get its choices.
Example: “/home/images”.

必须参数;一个绝对路径, 对象要访问的目录;

2)FilePathField.match
Optional. A regular expression, as a string, that FilePathField will use to filter filenames. Note that the regex will be applied to the base filename, not the full path. Example: “foo.*.txt$”, which will match a
file called foo23.txt but not bar.txt or foo23.png.

正则表达式;用于筛选文件名;需要注意的是, 表达式只应用于基础文件名,并不会带路径;

3)FilePathField.recursive
Optional. Either True or False. Default is False. Specifies whether all subdirectories of path should be included

True或False, 用于指定是否要迭代查找子目录;

4)FilePathField.allow_files
Optional. Either True or False. Default is True. Specifies whether files in the specified location should be included. Either this or allow_folders must be True.

True或False, 默认为True, 用于确认是否包括目录下的文件;

5)FilePathField.allow_folders
Optional. Either True or False. Default is False. Specifies whether folders in the specified location should be included. Either this or allow_files must be True.

True或False, 默认为False, 用于确认是否包括目录下的文件夹,注意该参数和allow_files参数必须至少有一个为True;

6)The one potential gotcha is that match applies to the base filename, not the full path. So, this example:
FilePathField(path="/home/images", match=“foo.*”, recursive=True)
. . . will match /home/images/foo.png but not /home/images/foo/bar.png because the match applies to the base filename (foo.png and bar.png).
查找对象为基础文名的例子;

7)FilePathField instances are created in your database as varchar columns with a default max length of 100 characters. As with other fields, you can change the maximum length using the max_length argument.
max_length参数默认为100个字符,可以自己设定;

(11)ImageField

class ImageField(upload_to=None, height_field=None, width_field=None, max_length=100, **options)
1)Inherits all attributes and methods from FileField, but also validates that the uploaded object is a valid image.
In addition to the special attributes that are available for FileField, an ImageField also has height and width attributes.
To facilitate querying on those attributes, ImageField has two extra optional arguments:

继承了FileField的所有属性和方法,但同时会校验上传的对象是否是有效的图片;除了FileField可用的特殊属性外, 还具有高度和宽度属性; 为了便于查询这些属性, 该字段有两个额外的参数:

2)ImageField.height_field
Name of a model field which will be auto-populated with the height of the image each time the model instance is saved.

模型实例每次保存时,自动将图片高度填充入此参数;

3)ImageField.width_field
Name of a model field which will be auto-populated with the width of the image each time the model instance is saved.

模型实例每次保存时,自动将图片宽度填充入此参数;

4)Requires the Pillow library.
ImageField instances are created in your database as varchar columns with a default max length of 100 characters.
As with other fields, you can change the maximum length using the max_length argument.
The default form widget for this field is a ClearableFileInput.
该字段要求安装pillow库, max_length参数默认为100,可以自己设置;

(12)IntegerField

class IntegerField(**options)
An integer. Values from -2147483648 to 2147483647 are safe in all databases supported by Django.
It uses MinValueValidator and MaxValueValidator to validate the input based on the values that the default database supports.
The default form widget for this field is a NumberInput when localize is False or TextInput otherwise

整数字段,对于django支持的所有数据库都是安全的;

(13)TextField

class TextField(**options)
A large text field. The default form widget for this field is a Textarea.
If you specify a max_length attribute, it will be reflected in the Textarea widget of the auto-generated form field.
However it is not enforced at the model or database level. Use a CharField for that.

大文本字段, max_length不要求强制指定;

(14)TimeField

class TimeField(auto_now=False, auto_now_add=False, **options)
A time, represented in Python by a datetime.time instance. Accepts the same auto-population options as DateField.
The default form widget for this field is a TextInput. The admin adds some JavaScript shortcuts.

时间字段, 在python中以datetime.time对象呈现, 两个参数的含义及使用方式与DateField相同;

(15)URLField

class URLField(max_length=200, **options)
A CharField for a URL, validated by URLValidator.
The default form widget for this field is a TextInput.
Like all CharField subclasses, URLField takes the optional max_length argument. If you don’t specify max_length, a default of 200 is used.

url字段, CharField的特殊形式, 会校验是否为有效的URL, 默认最大长度为200;

(16)其他不常用字段待补充…

3.字段的常用参数
(1)null

If True, Django will store empty values as NULL in the database. Default is False.

如果该参数为True,那么对于空值数据库将会存储为null, 默认为false;

Avoid using null on string-based fields such as CharField and TextField. If a string-based field has null=True, that means it has two possible values for “no data”: NULL, and the empty string. In most cases, it’s redundant to have two possible values for “no data;” the Django convention is to use the empty string, not NULL. One exception is when a CharField has both unique=True and blank=True set. In this situation, null=True is required to avoid unique constraint violations when saving multiple objects with blank values.
For both string-based and non-string-based fields, you will also need to set blank=True if you wish to permit empty values in forms, as the null parameter only affects database storage (see blank).
Note: When using the Oracle database backend, the value NULL will be stored to denote the empty string regardless of this attribute.

避免在基于字符串的字段如CharField等使用null,因为对于没有数据有两种可能的值:null或空字符串;在大多数情况下,这会导致冗余;django的传统是使用空字符串而不是null;但有一种例外是当unique=True并且blank=True时,null=True可以避免违反unique的规则;
对于基于字符串的字段和非基于字符串的字段,都需要设置blank=True以允许空值在表单中的输入;
(2)blank

If True, the field is allowed to be blank. Default is False.
Note that this is different than null. null is purely database-related, whereas blank is validation-related. If a field has blank=True, form validation will allow entry of an empty value. If a field has blank=False,
the field will be required.

如果为True,则字段允许为空; 默认值为False,注意, 它与null不同, null是纯粹基于数据库来说的, 而blank是基于验证而言的, 如果参数设为True, 那表单验证时将允许输入空值, 反之,字段则为必填字段;

(3)choices

1)An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this field. If this is given, the default form widget will be a select box instead of the standard text field and will limit choices to the choices given. A choices list looks like this:

YEAR_IN_SCHOOL_CHOICES = (
('FR', 'Freshman'),
('SO', 'Sophomore'),
('JR', 'Junior'),
('SR', 'Senior'),
('GR', 'Graduate'),
)

该参数值为由一系列两个元素的元组构成的可迭代对象,如上面所示, 用作该字段的选择; 如果该参数被给出, 那默认的表单插件将是select box;

2)The first element in each tuple is the value that will be stored in the database. The second element is displayed by the field’s form widget.
Given a model instance, the display value for a field with choices can be accessed using the get_FOO_display() method. For example:

from django.db import models
class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)

>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'

元组的第一个元素是存储在数据库中的值, 第二个元素是展示在表单中的值, 该值可通过调用对象的get_FOO_display()方法获得, 该参数的使用示例如上;

(3)default

1)The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

字段的默认值, 可以是一个值也可以是一个可调用对象, 如果是个可调用对象的话,每一次调用它都会产生一个新的对象;

2)The default can’t be a mutable object (model instance, list, set, etc.), as a reference to the same instance of that object would be used as the default value in all new model instances. Instead, wrap the desired default in a callable.
For example, if you want to specify a default dict for JSONField, use a function:

def contact_default():
return {"email": "to1@example.com"}
contact_info = JSONField("ContactInfo", default=contact_default)

lambdas can’t be used for field options like default because they can’t be serialized by migrations. See that documentation for other caveats.

默认值不能是可变对象(例如模型实例,列表,字典等),因为对该对象的修改会导致新的模型对象的默认值被修改;解决方法: 可以将想要的默认值封装到可调用对象中, 见上例; lambda不能用于默认值, 因为无法被migrations序列化;

3)For fields like ForeignKey that map to model instances, defaults should be the value of the field they reference (pk unless to_field is set) instead of model instances.
The default value is used when new model instances are created and a value isn’t provided for the field. When the field is a primary key, the default is also used when the field is set to None.

对于外键字段, 默认值应该是它引用的字段的值,而不是模型实例;
当创建的新的模型实例没有指定字段值时,默认值将被使用;当字段是主键时,默认值也会使用;

(4)help_text

Extra “help” text to be displayed with the form widget. It’s useful for documentation even if your field isn’t used on a form.

用表单插件显示额外的帮助信息, 即使你的字段没有在表单上使用, 它对文档也很有用;

Note that this value is not HTML-escaped in automatically-generated forms. This lets you include HTML in help_text if you so desire. For example:

help_text="Please use the following format: < em>YYYY-MM-DD< /em>."

Alternatively you can use plain text and django.utils.html.escape() to escape any HTML special characters.
Ensure that you escape any help text that may come from untrusted users to avoid a cross-site scripting attack.

注意这个值并不会在自动生成的表单中转义, 这可以让你在help_text中包含HTML;确保你转义的help_text是安全的, 避免跨站攻击;

(5)primary_key

If True, this field is the primary key for the model.
If you don’t specify primary_key=True for any fields in your model, Django will automatically add an IntegerField to hold the primary key, so you don’t need to set primary_key=True on any of your fields unless you want to override the default primary-key behavior. For more, see Automatic primary key fields.
The primary key field is read-only. If you change the value of the primary key on an existing object and then save it, a new object will be created alongside the old one. For example:

from django.db import models
class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)

>>> fruit = Fruit.objects.create(name='Apple')
>>> fruit.name = 'Pear'
>>> fruit.save()
>>> Fruit.objects.values_list('name', flat=True)
<QuerySet ['Apple', 'Pear']>

如果该参数为True, 那么本字段就是model的主键;
如果在model中不指定主键,那么django会自动创建一个integerField作为主键, 所以除非你想自己改变默认设定主键的行为,不需要设置此参数;
另外,重要的是主键字段是只读的, 如果你更改对象的主键字段的值,并保存, 那么django会在原对象后面创建一个新对象;如上例;

(6)unique

If True, this field must be unique throughout the table.
Again, these are just short descriptions of the most common field options. Full details can be found in the common model field option reference.

如果设为True, 那该字段的值必须在表中唯一;

This option is valid on all field types except ManyToManyField and OneToOneField.
Note that when unique is True, you don’t need to specify db_index, because unique implies the creation of an index.

该选项对于多对多字段和一对一字段无效;
如果一个字段指定了unique则无需再指定db_index, 因为unique会隐式的创建索引;

(7)Verbose field names

Each field type, except for ForeignKey, ManyToManyField and OneToOneField, takes an optional first positional argument – a verbose name. If the verbose name isn’t given, Django will automatically create it using the field’s attribute name, converting underscores to spaces.

#In this example, the verbose name is "person's first name":
first_name = models.CharField("person's first name", max_length=30)
#In this example, the verbose name is "first name":
first_name = models.CharField(max_length=30)

每个字段类型(ForeignKey,ManyToManyField和OneToOneField除外)都可采用可选的第一个位置参数 - 一个详细的名称(verbose_name) .如果没有给出详细名称,Django将使用字段的属性名称自动创建它,并将下划线转换为空格。(Admin中字段的显示名称)

在foreignkey等字段中如下设置:

ForeignKey, ManyToManyField and OneToOneField require the first argument to be a model class, so use the verbose_name keyword argument:

poll = models.ForeignKey(
Poll,
on_delete=models.CASCADE,
verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
verbose_name="related place",
)

The convention is not to capitalize the first letter of the verbose_name. Django will automatically capitalize the first letter where it needs to.
约定并不需要将首字母大写,因为django会在需要时自动将其变为大写;

(8)db_column

Field.db_column
The name of the database column to use for this field. If this isn’t given, Django will use the field’s name.
If your database column name is an SQL reserved word, or contains characters that aren’t allowed in Python variable names – notably, the hyphen – that’s OK. Django quotes column and table names behind the scenes.

数据库该字段的列名;如果没有设置,django将会使用字段名;
如果数据库列名是SQL的保留字,那么也没有问题,django会在后台引用列名和表名;

(9)db_index

Field.db_index
If True, a database index will be created for this field.

如果为True, 则数据库索引将会在该字段上创建;

(10)db_tablespace

Field.db_tablespace
The name of the database tablespace to use for this field’s index, if this field is indexed. The default is the project’s DEFAULT_INDEX_TABLESPACE setting, if set, or the db_tablespace of the model, if any. If the backend doesn’t support tablespaces for indexes, this option is ignored.

如果此字段已编制索引,则用于此字段索引的数据库表空间的名称。 默认值为项目的DEFAULT_INDEX_TABLESPACE设置(如果已设置)或模型的db_tablespace(如果有)。 如果后端不支持索引的表空间,则忽略此选项。

(11)editable

Field.editable
If False, the field will not be displayed in the admin or any other ModelForm. They are also skipped during model validation. Default is True.

如果为False, 那该字段将不会在admin或其他任何ModelForm中显示, 同时也会跳过校验;默认为True;

(12)error_messages

Field.error_messages
The error_messages argument lets you override the default messages that the field will raise. Pass in a dictionary with keys matching the error messages you want to override.
Error message keys include null, blank, invalid, invalid_choice, unique, and unique_for_date. Additional error message keys are specified for each field in the Field types section below.
These error messages often don’t propagate to forms. See Considerations regarding model’s error_messages.

该参数让你可以覆盖字段默认的错误提示信息;传入一个字典, key为错误信息类型, 包括 null, blank, invalid, invalid_choice, unique, and unique_for_date等;每个特定字段也有额外的错误信息类型;
错误信息通常不会传播到表单;

(13)unique_for_date

Field.unique_for_date
Set this to the name of a DateField or DateTimeField to require that this field be unique for the value of the date field.
For example, if you have a field title that has unique_for_date=“pub_date”, then Django wouldn’t allow the entry of two records with the same title and pub_date.
Note that if you set this to point to a DateTimeField, only the date portion of the field will be considered. Besides, when USE_TZ is True, the check will be performed in the current time zone at the time the object gets saved.
This is enforced by Model.validate_unique() during model validation but not at the database level. If any unique_for_date constraint involves fields that are not part of a ModelForm (for example, if one of the fields is listed in exclude or has editable=False), Model.validate_unique() will skip validation for that particular constraint.

将此参数设为DateField或DateTimeField字段的名称来要求该字段相对于日期字段的值唯一;例如,title字段该参数设为unique_for_date=“pub_date”,那么django不会允许输入title和pub_date都相同的记录;
注意:如果将此参数指向DateTimeField,只有字段的日期部分会被考虑;另外,如果USE_TZ是True, 那当对象保存是会在当前时区进行检查;
这种限制在模型校验期间被Model.validate_unique() 强制执行,而不是在数据库级别;如果该参数指向的字段并不是ModelForm的一部分(例如,其中一个字段出现在exclude中或editable=False),Model.validate_unique()将会跳过校验;

(14)unique_for_month

Field.unique_for_month
Like unique_for_date, but requires the field to be unique with respect to the month.

相对于月份唯一;

(15)unique_for_year

Field.unique_for_year
Like unique_for_date and unique_for_month.

相对于年份唯一;

4.模型的属性和方法
(1)objects

The most important attribute of a model is the Manager. It’s the interface through which database query operations are provided to Django models and is used to retrieve the instances from the database. If no custom Manager is defined, the default name is objects. Managers are only accessible via model classes, not the
model instances.

模型最重要的属性是Manager, 它是为django模型提供数据库查询操作的接口, 并用于从数据库中检索实例;如果未定义Manager, 默认名为objects. 该属性只能通过类访问,不能通过实例访问;

(2)自定义方法

The model instance reference has a complete list of methods automatically given to each model. You can override most of these – see overriding predefined model methods, below – but there are a couple that you’ll almost always want to define
模型有一整套的方法, 绝大多数都可以自己进行覆盖,但有两个方法绝大多数情况下都会进行覆盖:

1)str()

A Python “magic method” that returns a string representation of any object. This is what Python and Django will use whenever a model instance needs to be coerced and displayed as a plain string. Most notably, this happens when you display an object in an interactive console or in the admin.
You’ll always want to define this method; the default isn’t very helpful at all.

返回对象的字符串显示; 需要注意的是, 在控制台和admin界面中依然会显示这种字符串

2)get_absolute_url()

This tells Django how to calculate the URL for an object. Django uses this in its admin interface, and any time it needs to figure out a URL for an object.
Any object that has a URL that uniquely identifies it should define this method.

这个方法告诉django如何计算一个对象的URL; django在admin界面中或任何需要获得对象的url的情况下使用它;
具有唯一标识它的url的任何对象都应该定义这个方法

3)模型继承:
有三种模式
待补充…

5.创建模型

5.1migration

Migrations are Django’s way of propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema. They’re designed to be mostly automatic, but you’ll need to know when to make migrations, when to run them, and the common problems you might run into.

迁移是django将对模型的更改发布到数据库的方式;它们大多数情况下是自动的,但你需要知道什么时候值作migration, 什么时候运行它们,以及可能遇到的问题;

5.1.1命令

There are several commands which you will use to interact with migrations and Django’s handling of database schema:
• migrate, which is responsible for applying and unapplying migrations.
• makemigrations, which is responsible for creating new migrations based on the changes you have made to your models.
• sqlmigrate, which displays the SQL statements for a migration.
• showmigrations, which lists a project’s migrations and their status.

migrate: 负责应用和取消应用migration;
makemigrations: 负责基于你对模型的更改创建新的migration;
sqlmigrate: 显示migration的SQL语句;
showmigrations:列出项目的migration和他们的状态;

You should think of migrations as a version control system for your database schema. makemigrations is responsible for packaging up your model changes into individual migration files - analogous to commits - and migrate is responsible for applying those to your database.

你应该将migration当作是对你的数据库的版本控制系统; makemigration负责将模型的更改打包到单个迁移文件中,类似于提交; migrate负责将这些更改应用到数据库中;

The migration files for each app live in a “migrations” directory inside of that app, and are designed to be committed to, and distributed as part of, its codebase. You should be making them once on your development machine and then running the same migrations on your colleagues’ machines, your staging machines, and eventually your production machines.

迁移文件放在每个应用下的migration目录中,它被用于提交,并且当作代码库的一部分进行分发; 你应该分别在你开发的机器, 同事的机器,临时计算机以及最终生产的计算机上都运行相同的迁移;

Note: It is possible to override the name of the package which contains the migrations on a per-app basis by modifying the MIGRATION_MODULES setting.
可以通过修改MIGRATION_MODULES设置来覆盖包含基于每个应用的迁移的程序包的名字;

Migrations will run the same way on the same dataset and produce consistent results, meaning that what you see in development and staging is, under the same circumstances, exactly what will happen in production.
迁移将在同一数据集上以相同的方式运行并产生一致的结果,这意味着在相同的情况下,您在开发和分段中看到的内容恰好是生产中将发生的情况。

Django will make migrations for any change to your models or fields - even options that don’t affect the database - as the only way it can reconstruct a field correctly is to have all the changes in the history, and you might need those options in some data migrations later on (for example, if you’ve set custom validators)
Django将对模型或字段的任何更改进行迁移 - 甚至是不影响数据库的选项 - 因为它可以正确重建字段的唯一方法是在历史记录中进行所有更改,并且您可能需要在 稍后进行一些数据迁移(例如,如果您设置了自定义验证程序)

5.2创建表
(1)models中创建类
(2)settings中配置默认数据库

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'exercise2',
        'USER': 'root',
        'PASSWORD': '328015',
        'HOST': '',
        'PORT': '3306',
    }
}

(3)应用目录下的_init_.py文件中添加:

import pymysql

pymysql.install_as_MySQLdb()

(4)运行命令:
python manage.py makemigrations
python manage.py migrate

5.3创建记录:
假设model名为Table;
(1) a=Table(**kwargs)
a.save()
(2)a=Table.objects.create(**kwargs)

两种方式区别:如果在参数中手动添加主键的值时,如果主键重复, save()方法会覆盖原主键的值, 而create方法会直接报错;因为主键重复时,save()会转而执行update语句;
(3)补充save():

Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)

When you save an object, Django performs the following steps:

  1. Emit a pre-save signal. The pre_save signal is sent, allowing any functions listening for that signal to do something.
  2. Preprocess the data. Each field’s pre_save() method is called to perform any automated data modification that’s needed. For example, the date/time fields override pre_save() to implement auto_now_add and auto_now.
  3. Prepare the data for the database. Each field’s get_db_prep_save() method is asked to provide its current value in a data type that can be written to the database. Most fields don’t require data preparation. Simple data types, such as integers and strings, are ‘ready to write’ as a Python object. However, more complex data types often require some modification.
    For example, DateField fields use a Python datetime object to store data. Databases don’t store datetime objects, so the field value must be converted into an ISO-compliant date string for insertion into the database.
  4. Insert the data into the database. The preprocessed, prepared data is composed into an SQL statement for insertion into the database.
  5. Emit a post-save signal. The post_save signal is sent, allowing any functions listening for that signal to do something.

使用save()时Django如何判断insert与update:

• If the object’s primary key attribute is set to a value that evaluates to True (i.e., a value other than None or the
empty string), Django executes an UPDATE.
• If the object’s primary key attribute is not set or if the UPDATE didn’t update anything, Django executes an
INSERT.

5.4更新记录:
(1) a=Table.objects.get(**kwargs)
a.name=new name
a.save()
(2)a= Table.objects.filter().update(**kwargs)
(3)注意:使用save()时, 无法修改主键的值,只会重新创建或覆盖其他记录;

(4)补充update(**kwargs)

1)Performs an SQL update query for the specified fields, and returns the number of rows matched (which may not be equal to the number of rows updated if some rows already have the new value).

完成数据库特定字段的更新的,返回匹配到的行数(注意此行数可能并不等于更新的实际行数,因为有些行数可能在更新前已经符合更改了)

2)You can only set non-relation fields and ForeignKey fields using this method. To update a non-relation field, provide the new value as a constant. To update ForeignKey fields, set the new value to be the new model instance you want to point to.

此方法只能设置非关联字段以及外键字段;

3)The only restriction on the QuerySet being updated is that it can only access one database table: the model’s main table. You can filter based on related fields, but you can only update columns in the model’s main table.

此方法的限制:只能更新一个表,即model的主表, 你可以通过关联字段进行过滤,但只能更新主表中的字段;

4)Be aware that the update() method is converted directly to an SQL statement. It is a bulk operation for direct updates. It doesn’t run any save() methods on your models, or emit the pre_save or post_save signals (which are a consequence of calling save()), or honor the auto_now field option. If you want to save every item in a QuerySet and make sure that the save() method is called on each instance, you don’t need any special function to handle that;

update()方法直接转化为sql语句,是直接更新的批量操作,并不会运行任何save()方法以及发出pre_save 或 post_save信号或遵守auto_now选项; 如果你想使用save()方法对QuerySet中的每个元素,直接用for循环就好;

5)Calls to update can also use F expressions to update one field based on the value of another field in the model. This is especially useful for incrementing counters based upon their current value. For example, to increment the pingback count for every entry in the blog:

>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

可以利用F表达式根据表中的某个字段更新另一个字段,对于需要自增的情况特别有用;

6)However, unlike F() objects in filter and exclude clauses, you can’t introduce joins when you use F() objects in an update – you can only reference fields local to the model being updated. If you attempt to introduce a join with an F() object, a FieldError will be raised:

#This will raise a FieldError
>>> Entry.objects.update(headline=F('blog__name'))

然鹅, 和filter, exclude语句中的F表达式不同, 在update中使用F时你无法引入连接, 你只能引用被更新模型的字段,否则会报错;

7)You cannot call update() on a QuerySet that has had a slice taken or can otherwise no longer be filtered;

无法对进行切片操作产生的QuerySet使用update()方法,否则无法对其进行过滤;

8)Using update() also prevents a race condition wherein something might change in your database in the short period of time between loading the object and calling save().

使用update()可避免在加载对象和调用save()方法之间的短时间内数据库发生改变的情况;

5.5删除记录
(1) a=Table.objects.filter().delete()

(2)补充delete()

1)The delete() is applied instantly. You cannot call delete() on a QuerySet that has had a slice taken or can otherwise no longer be filtered.

不能对切片产生的QuerySet使用;

2)The delete() method does a bulk delete and does not call any delete() methods on your models. It does, however, emit the pre_delete and post_delete signals for all deleted objects (including cascaded deletions).
Django needs to fetch objects into memory to send signals and handle cascades. However, if there are no cascades and no signals, then Django may take a fast-path and delete objects without fetching into memory. For large deletes this can result in significantly reduced memory usage. The amount of executed queries can be reduced, too.
ForeignKeys which are set to on_delete DO_NOTHING do not prevent taking the fast-path in deletion.
Note that the queries generated in object deletion is an implementation detail subject to change.

delete()方法不会在模型中调用,但会为所有删除的对象发送pre_delete 和 post_delete信号;django需要将对象载入内存以发送信号并处理级联删除,但如果没有级联和信号,django就能用一种快捷的方式删除记录, 这对大型的删除非常有用;
外键设置为on_delete DO_NOTHING不会阻止快捷删除的使用;
删除时生成的查询是一种可更改的实施细节;

3)This method immediately deletes the object and returns the
number of objects deleted and a dictionary with the number of deletions per object type.

此方法立即执行删除并且返回一个元组, 包括被删除的对象的个数以及以对象类型为键的字典,值为删除的个数;如:

>>> e.delete()
(1, {'weblog.Entry': 1})

4)Keep in mind that this will, whenever possible, be executed purely in SQL, and so the delete() methods of individual object instances will not necessarily be called during the process. If you’ve provided a custom delete() method on a model class and want to ensure that it is called, you will need to “manually” delete instances of that model (e.g., by iterating over a QuerySet and calling delete() on each object individually) rather than using the bulk delete() method of a QuerySet.

When Django deletes an object, by default it emulates the behavior of the SQL constraint ON DELETE CASCADE – in other words, any objects which had foreign keys pointing at the object to be deleted will be deleted along with it.

批量删除和单个删除没有区别;默认为级联删除,可以在foreignkey的参数中设置;

Note that delete() is the only QuerySet method that is not exposed on a Manager itself. This is a safety mechanism to prevent you from accidentally requesting Entry.objects.delete(), and deleting all the entries. If you do want to delete all the objects, then you have to explicitly request a complete query set:

Entry.objects.all().delete()

此方法只属于QuerySet, 不可以直接调用Entry.objects.delete(),此为一种安全机制,避免失误全删除;如你想全删除,使用如上方法;

5.6查询记录
5.6.1QuerySet
(1)QuerySet简介
该数据类型为django提供的一种对象集合数据类型, 内部存放了查询获得的一条或多条表记录, 大部分情况下由model的Manager属性产生, 可以通过索引或切片的方式提取其中的对象;,它具有如下几种方法:

(2)all()

Returns a copy of the current QuerySet (or QuerySet subclass). This can be useful in situations where you might want to pass in either a model manager or a QuerySet and do further filtering on the result. After calling all() on either object, you’ll definitely have a QuerySet to work with;

返回当前QuerySet的副本. 在你想将manager或queryset传入并进行进一步筛选时非常有用; 当对任一对象调用此方法后,你必然会得到一个QuerySet;

(3)filter()
可传入多个筛选条件,用逗号分割, 为AND形式, 更多的筛选条件使用F或Q查询;返回一个QuerySet;

(4)exclude()
filter()的相反形式;筛选出不符合条件的所有对象;返回一个QuerySet;

(5)过滤器的连用:
The result of refining a QuerySet is itself a QuerySet, so it’s possible to chain refinements together. For example:

>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.date.today()
... ).filter(
... pub_date__gte=datetime.date(2005, 1, 30)
... )

This takes the initial QuerySet of all entries in the database, adds a filter, then an exclusion, then another filter. The final result is a QuerySet containing all entries with a headline that starts with “What”, that were published between January 30, 2005, and the current day.

由于filter()的返回结果也是QuerySet, 因此可以使用多个filter连用的方式进行更进一步的筛选;

(7)筛选产生的每个QuerySet互相独立,互不影响,可以存储,使用;
Each time you refine a QuerySet, you get a brand-new QuerySet that is in no way bound to the previous QuerySet. Each refinement creates a separate and distinct QuerySet that can be stored, used and reused.

(8)QuerySet具有惰性, 生成QuerySet的操作并不会和数据库产生任何交互, 只有在调用Querset或访问其中的数据时它才会真正访问数据库;这样做可以提高程序运行效率; 另外,查询时QuerySet具有缓存机制, 对QuerySet重复相同的查询会直接调用上一次缓存中的内容, 因此当数据库更新时应该重新运行查询语句;
利用exists可以进行一种快速有效并节省资源的查询: 如果相应的QuerySet中有结果, 则返回True,反之返回False;

(9)first()

Returns the first object matched by the queryset, or None if there is no matching object. If the QuerySet has no ordering defined, then the queryset is automatically ordered by the primary key. This can affect aggregation results as described in Interaction with default ordering or order_by(). Example:

p = Article.objects.order_by('title', 'pub_date').first()

Note that first() is a convenience method, the following code sample is equivalent to the above example:

try:
p = Article.objects.order_by('title', 'pub_date')[0]
except IndexError:
p = None

返回QuerySet的第一个对象,如果结果为空则返回None; 如果QuerySet没有定义排序, 则自动按主键排列,这可能会影响聚合结果;

(10)last()

Works like first(), but returns the last object in the queryset.

同first()相同,但是返回的是第一个对象;

(11)aggregate(*args, **kwargs)

Returns a dictionary of aggregate values (averages, sums, etc.) calculated over the QuerySet. Each argument to aggregate() specifies a value that will be included in the dictionary that is returned.
The aggregation functions that are provided by Django are described in Aggregation Functions below. Since aggregates are also query expressions, you may combine aggregates with other aggregates or values to create complex aggregates.
Aggregates specified using keyword arguments will use the keyword as the name for the annotation. Anonymous arguments will have a name generated for them based upon the name of the aggregate function and the model field that is being aggregated. Complex aggregates cannot use anonymous arguments and must specify a keyword argument as an alias.

返回通过QuerySet计算的聚合值的字典, aggregate()的每个参数指定了字典中将要包含的值;
由于aggregate()也是查询表达式,因此可以对aggregate或其他aggregate的值进行组合以进行更复杂的查询;
当该方法使用关键参数时,会将关键字用作聚合结果的名称;匿名参数会自动生成一个由要聚合的字段名和聚合函数名组成名称, 复合聚合不能使用匿名参数, 必须使用关键字参数;下为示例:

>>> from django.db.models import Count
>>> q = Blog.objects.aggregate(Count('entry'))
{'entry__count': 16}

>>> q=Blog.objects.aggregate(number_of_entries=Count('entry'))
{'number_of_entries': 16}

(12)iterator(chunk_size=2000)

Evaluates the QuerySet (by performing the query) and returns an iterator (see PEP 234) over the results. A QuerySet typically caches its results internally so that repeated evaluations do not result in additional queries. In contrast, iterator() will read results directly, without doing any caching at the QuerySet level (internally, the default iterator calls iterator() and caches the return value). For a QuerySet which returns a large number of objects that you only need to access once, this can result in better performance and a significant reduction in memory. Note that using iterator() on a QuerySet which has already been evaluated will force it to evaluate again, repeating the query.
Also, use of iterator() causes previous prefetch_related() calls to be ignored since these two optimizations do not make sense together.
Depending on the database backend, query results will either be loaded all at once or streamed from the database using server-side cursors.

计算QuerySet并将结果返回一个迭代器; 与通常的QuerySet相反, 该方法不会在QuerySet级别进行任何缓存, 直接读取结果; 对于返回大量对象的QuerySet而你需要其中一小部分的情况,该方法对性能提升和内存优化特别有效;
注意对已经计算过的QuerySet上使用此方法会重新进行计算,重新查询,不会调用缓存;
同时使用该方法会导致先前的prefetch_related()方法失效,因为两种优化方式一起没有意义;
查询结果的加载方式应后端数据库的不同而不同,以一次性(mysql,sqlite)或者流的方式(Oracle,postgresql加载;
参数chunk_size为每次从数据库中获取的数据大小,默认为2000, 增加参数会减少数据库访问次数但会增加内存占用;

(13)count()

Returns an integer representing the number of objects in the database matching the QuerySet.

Example:
#Returns the total number of entries in the database.
Entry.objects.count()
#Returns the number of entries whose headline contains 'Lennon'
Entry.objects.filter(headline__contains='Lennon').count()

A count() call performs a SELECT COUNT(*) behind the scenes, so you should always use count() rather than loading all of the record into Python objects and calling len() on the result (unless you need to load the objects into memory anyway, in which case len() will be faster).
Note that if you want the number of items in a QuerySet and are also retrieving model instances from it (for example, by iterating over it), it’s probably more efficient to use len(queryset) which won’t cause an extra database query like count() would.

该方法返回QuerySet中的对象数;它底层会调用SELECT COUNT(*)语句,所以如果你只想获取QuerySet的长度, 就用此方法;
注意:如果你想获取QuerySet的长度同时也要获取其中的内容, 那调用len(queryset)比较好, 因为count()还会额外访问一次数据库;

(14)get()

filter() will always give you a QuerySet, even if only a single object matches the query - in this case, it will be a QuerySet containing a single element.
If you know there is only one object that matches your query, you can use the get() method on a Manager which returns the object directly;
You can use any query expression with get(), just like with filter() - again, see Field lookups below.
Note that there is a difference between using get(), and using filter() with a slice of [0]. If there are no results that match the query, get() will raise a DoesNotExist exception. This exception is an attribute of the model class that the query is being performed on - so in the code above, if there is no Entry object with a primary key of 1, Django will raise Entry.DoesNotExist.
Similarly, Django will complain if more than one item matches the get() query. In this case, it will raise MultipleObjectsReturned, which again is an attribute of the model class itself.

此方法将直接返回一个对象;参数与filter()完全相同; 但要注意的是,如果没有匹配结果,或匹配结果多于一个,都会抛出异常;

2)If you expect a queryset to return one row, you can use get() without any arguments to return the object for that row:

entry = Entry.objects.filter(...).exclude(...).get()

如果希望QuerSet返回一行,可以调用不带参数的get();

(15)select_related(*fields)

1)Returns a QuerySet that will “follow” foreign-key relationships, selecting additional related-object data when it executes its query. This is a performance booster which results in a single more complex query but means later use of foreign-key relationships won’t require database queries.
The following examples illustrate the difference between plain lookups and select_related() lookups. Here’s standard lookup:

#Hits the database.
e = Entry.objects.get(id=5)
#Hits the database again to get the related Blog object.
b = e.blog

#And here’s select_related lookup:
#Hits the database.
e = Entry.objects.select_related('blog').get(id=5)
#Doesn't hit the database, because e.blog has been prepopulated
#in the previous query.
b = e.blog

该方法返回一个追踪外键关系的QuerySet, 在查询中它会选择其他的相关对象数据;它相当于一个性能增强器,把单次查询变得更复杂但是以后调用外键关系时就不用再访问数据库了;上为示例:

#The order of filter() and select_related() chaining isn’t important. These querysets are equivalent:
Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog')
Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())

示例3:

from django.db import models
class City(models.Model):
#...
pass
class Person(models.Model):
#...
hometown = models.ForeignKey(
City,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
class Book(models.Model):
#...
author = models.ForeignKey(Person, on_delete=models.CASCADE)

#Hits the database with joins to the author and hometown tables.
b = Book.objects.select_related('author__hometown').get(id=4)
p = b.author # Doesn't hit the database.
c = p.hometown # Doesn't hit the database.
#Without select_related()...
b = Book.objects.get(id=4) # Hits the database.
p = b.author # Hits the database.
c = p.hometown # Hits the database.

2)You can refer to any ForeignKey or OneToOneField relation in the list of fields passed to select_related().
You can also refer to the reverse direction of a OneToOneField in the list of fields passed to select_related —that is, you can traverse a OneToOneField back to the object on which the field is defined. Instead of specifying the field name, use the related_name for the field on the related object.
There may be some situations where you wish to call select_related() with a lot of related objects, or where you don’t know all of the relations. In these cases it is possible to call select_related() with no arguments. This will follow all non-null foreign keys it can find - nullable foreign keys must be specified. This is not recommended in most cases as it is likely to make the underlying query more complex, and return more data, than is actually needed.
If you need to clear the list of related fields added by past calls of select_related on a QuerySet, you can pass None as a parameter:

>>> without_relations = queryset.select_related(None)

你可以在传递给select_related()的列表中引用任何foreignkey或onetoonefield关系;
不但可以引用外键的关联对象,还可以反方向引用;
如果你要引用许多对象或不知道所有的引用关系,可以使用不带参数的该方法,会自动获取所有外键关系, 但不推荐使用,可能会使结果混乱;
如果希望清除过去调用的select_related的相关字段,传入参数null;
该方法也可以连接使用,多个字段用逗号隔开;

(16)values()

values(*fields, **expressions)
1)Returns a QuerySet that returns dictionaries, rather than model instances, when used as an iterable.
Each of those dictionaries represents an object, with the keys corresponding to the attribute names of model objects. This example compares the dictionaries of values() with the normal model objects:

#This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
<QuerySet [<Blog: Beatles Blog>]>
#This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>

返回一个QuerySet,不同的是当它用作可迭代对象时, 返回的是字典而不是对象;每个字典代表一个对象,键是对象的字段名,而值为字段的值,如上例

2)The values() method takes optional positional arguments, *fields, which specify field names to which the SELECT should be limited. If you specify the fields, each dictionary will contain only the field keys/values for the fields you specify. If you don’t specify the fields, each dictionary will contain a key and value for every field in the database table.
Example:

>>> Blog.objects.values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
>>> Blog.objects.values('id', 'name')
<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>

可选参数*fileds可以指定要显示的字段名,指定后每个字典里只会显示相关字段;

3)The values() method also takes optional keyword arguments, **expressions, which are passed through to annotate():

>>> from django.db.models.functions import Lower
>>> Blog.objects.values(lower_name=Lower('name'))
<QuerySet [{'lower_name': 'beatles blog'}]>

可选参数**expression,将参数传入annotate();

4)You can use built-in and custom lookups in ordering. For example:

>>> from django.db.models import CharField
>>> from django.db.models.functions import Lower
>>> CharField.register_lookup(Lower)
>>> Blog.objects.values('name__lower')
<QuerySet [{'name__lower': 'beatles blog'}]>

可以使用内置和自定义的下划线查找;

5)An aggregate within a values() clause is applied before other arguments within the same values() clause. If you need to group by another value, add it to an earlier values() clause instead. For example:

>>> from django.db.models import Count
>>> Blog.objects.values('entry__authors', entries=Count('entry'))
<QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]>
>>> Blog.objects.values('entry__authors').annotate(entries=Count('entry'))
<QuerySet [{'entry__authors': 1, 'entries': 33}]>

values()内的aggregate会先于其他语句执行,因此如果你想使用其他值分组,把它放入前面的value语句中;

6)If you have a field called foo that is a ForeignKey, the default values() call will return a dictionary key called foo_id, since this is the name of the hidden model attribute that stores the actual value (the foo
attribute refers to the related model). When you are calling values() and passing in field names, you can pass in either foo or foo_id and you will get back the same thing (the dictionary key will match the field name you passed in).

>>> Entry.objects.values()
<QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]>
>>> Entry.objects.values('blog')
<QuerySet [{'blog': 1}, ...]>
>>> Entry.objects.values('blog_id')
<QuerySet [{'blog_id': 1}, ...]>

如果有一个字段foo是个外键,那么values()默认会返回字典键为foo_id, 它是隐藏模型的名称;无论你传入foo_id还是foo,返回值都是一样的;

7)When using values() together with distinct(), be aware that ordering can affect the results. See thenote in distinct() for details.

和distinct()一起连用时,顺序将会影响结果;

8)If you use a values() clause after an extra() call, any fields defined by a select argument in the extra() must be explicitly included in the values() call. Any extra() call made after a values() call will have its extra selected fields ignored.

Calling only() and defer() after values() doesn’t make sense, so doing so will raise a NotImplementedError.

待补充;

9)Combining transforms and aggregates requires the use of two annotate() calls, either explicitly or as keyword arguments to values(). As above, if the transform has been registered on the relevant field type the first annotate() can be omitted, thus the following examples are equivalent

转换和聚合组合使用需要两个annotate()调用,显式或作为values()的关键字参数。 如上所述,如果已在相关字段类型上注册了变换,则可以省略第一个annotate(),因此以下示例是等效的:

>>> from django.db.models import CharField, Count
>>> from django.db.models.functions import Lower
>>> CharField.register_lookup(Lower)
>>> Blog.objects.values('entry__authors__name__lower').annotate(entries=Count(
.'entry'))
<QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
>>> Blog.objects.values(
... entry__authors__name__lower=Lower('entry__authors__name')
... ).annotate(entries=Count('entry'))
<QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
>>> Blog.objects.annotate(
... entry__authors__name__lower=Lower('entry__authors__name')
... ).values('entry__authors__name__lower').annotate(entries=Count('entry'))
<QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>

10)It is useful when you know you’re only going to need values from a small number of the available fields and you won’t need the functionality of a model instance object. It’s more efficient to select only the fields you need to use.
Finally, note that you can call filter(), order_by(), etc. after the values() call, that means that these two calls are identical:

Blog.objects.values().order_by('id')
Blog.objects.order_by('id').values()

当你知道你只需要少部分的字段并且不需要对象的功能时,使用values会很高效;

11)The people who made Django prefer to put all the SQL-affecting methods first, followed (optionally) by any outputaffecting methods (such as values()), but it doesn’t really matter. This is your chance to really flaunt your individualism.
You can also refer to fields on related models with reverse relations through OneToOneField, ForeignKey and ManyToManyField attributes:

>>> Blog.objects.values('name', 'entry__headline')
<QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
{'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>

也可以在values中引用OneToOneField, ForeignKey ,ManyToManyField的相反关联;

Warning: Because ManyToManyField attributes and reverse relations can have multiple related rows, including these can have a multiplier effect on the size of your result set. This will be especially pronounced if you include multiple such fields in your values() query, in which case all possible combinations will be returned.

警示:因为ManyToManyField属性和反向关系可以有多个相关的行,包括这些行可能会对结果集的大小产生乘数效应。 如果在values()查询中包含多个此类字段,这将特别明显,在这种情况下,将返回所有可能的组合;

(17)values_list(*fields, flat=False, named=False)

1)This is similar to values() except that instead of returning dictionaries, it returns tuples when iterated over. Each tuple contains the value from the respective field or expression passed into the values_list() call — so the first item is the first field, etc. For example:

>>> Entry.objects.values_list('id', 'headline')
<QuerySet [(1, 'First entry'), ...]>
>>> from django.db.models.functions import Lower
>>> Entry.objects.values_list('id', Lower('headline'))
<QuerySet [(1, 'first entry'), ...]>

和values()相似,但当进行迭代时返回的是一个元组, 每个元组包括传入该方法的相关字段或表达式的值,所以第一个元素就是第一个字段的值;

2)If you only pass in a single field, you can also pass in the flat parameter. If True, this will mean the returned results are single values, rather than one-tuples. It is an error to pass in flat when there is more than one field;An example should make the difference clearer:

>>> Entry.objects.values_list('id').order_by('id')
<QuerySet[(1,), (2,), (3,), ...]>
>>> Entry.objects.values_list('id', flat=True).order_by('id')
<QuerySet [1, 2, 3, ...]>

如果传入单个字段,则 可以设置flat参数,如果设为True,那么意味着返回结果是单个值而不是元组,有多个字段时设置此参数会出错;示例如上;

3)You can pass named=True to get results as a namedtuple():

>>> Entry.objects.values_list('id', 'headline', named=True)
<QuerySet [Row(id=1, headline='First entry'), ...]>

Using a named tuple may make use of the results more readable, at the expense of a small performance penalty for transforming the results into a named tuple.

参数named设为True可以产生命名元组;

4)If you don’t pass any values to values_list(), it will return all the fields in the model, in the order they were declared.
A common need is to get a specific field value of a certain model instance. To achieve that, use values_list() followed by a get() call:

>>> Entry.objects.values_list('headline', flat=True).get(pk=1)
'First entry'

如果不传入任何参数,那将按顺序返回所有字段;
一个常用需求是获得某个对象的某个字段的值,可以用values_list和get()方法实现;如上所示;

5)values() and values_list() are both intended as optimizations for a specific use case: retrieving a subset of data without the overhead of creating a model instance. This metaphor falls apart when dealing with many-to-many and other multivalued relations (such as the one-to-many relation of a reverse foreign key) because the “one row, one
object” assumption doesn’t hold

values()和values_list()都是针对特定用例的优化:检索数据子集而无需创建模型实例的开销。 当处理多对多和其他多值关系(例如反向外键的一对多关系)时,这个比喻就会分崩离析,因为“一行,一个对象”假设不成立;下例:

#ManyToManyField
>>> Author.objects.values_list('name', 'entry__headline')
<QuerySet [('Noam Chomsky', 'Impressions of Gaza'),
('George Orwell', 'Why Socialists Do Not Believe in Fun'),
('George Orwell', 'In Defence of English Cooking'),
('Don Quixote', None)]>
#Authors with multiple entries appear multiple times and authors without any entries have None for the entry headline

#foreignkey
>>> Entry.objects.values_list('authors')
<QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>

(18)annotate(*args, **kwargs)

1)Annotates each object in the QuerySet with the provided list of query expressions. An expression may be a simple value, a reference to a field on the model (or any related models), or an aggregate expression (averages, sums, etc.) that has been computed over the objects that are related to the objects in the QuerySet.
Each argument to annotate() is an annotation that will be added to each object in the QuerySet that is returned.
The aggregation functions that are provided by Django are described in Aggregation Functions below.
Annotations specified using keyword arguments will use the keyword as the alias for the annotation. Anonymous arguments will have an alias generated for them based upon the name of the aggregate function and the model field that is being aggregated. Only aggregate expressions that reference a single field can be anonymous arguments. Everything else must be a keyword argument.

使用提供的一系列查询表达式对QuerySet中的每个对象进行注释;表达式可能是一个值, 模型或相关模型的字段, 或对QuerySet中相关对象计算的聚合表达式;
该方法的每个参数都是返回的QuerySet中的每个对象的注释;
如果使用关键字的形式指定参数,那关键字将被用作注释的别名, 匿名参数将会使用聚合函数名以及字段名的组合作为别名;只有引用单个字段的聚合表达式才可使用匿名参数,其他参数都必须是关键字参数;

示例:

#For example, if you were manipulating a list of blogs, you may want to determine how many entries have been made in each blog:
>>> from django.db.models import Count
>>> q = Blog.objects.annotate(Count('entry'))
#The name of the first blog
>>> q[0].name
'Blogasaurus'
#The number of entries on the first blog
>>> q[0].entry__count
42

>The Blog model doesn’t define an entry__count attribute by itself, but by using a keyword argument to specify the aggregate function, you can control the name of the annotation:
>>> q = Blog.objects.annotate(number_of_entries=Count('entry'))
# The number of entries on the first blog, using the name provided
>>> q[0].number_of_entries
42

注意:1)当annotate()前有values()时,会先分组, 然后对每一组做聚合计算;而如果没有values(),会对每一个对象做聚合计算(其实相当于按id分组)
2)annotate()中传入多个聚合函数时, 计算结果有可能产生bug;

Combining multiple aggregations with annotate() will yield the wrong results because joins are used instead of subqueries

3)与order_by连用时可能产生未预期的结果,因为order_by会为select产生额外的列,解决方法为order_by()不传入参数调用;
4)可与aggregate()连用;

(19)order_by(*fields)

1)By default, results returned by a QuerySet are ordered by the ordering tuple given by the ordering option in the model’s Meta. You can override this on a per-QuerySet basis by using the order_by method. Example:

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')

默认情况下,QuerySet返回的结果的顺序是按照模型的Meta.ordering属性规定的排序元组来排序的,但你可以使用此方法来覆盖排序方式;

2)The result above will be ordered by pub_date descending, then by headline ascending. The negative sign in front of “-pub_date” indicates descending order. Ascending order is implied. To order randomly, use “?”, like so:

Entry.objects.order_by('?')

Note: order_by(’?’) queries may be expensive and slow, depending on the database backend you’re using.

上例中将会使用pub_date降序排序,然后使用headline升序排序,负号标识降序,升序是默认的,如果想要随机排序,使用"?"; 但需要注意使用问号查询昂贵并且缓慢,取决于你的后端数据库;

3)To order by a field in a different model, use the same syntax as when you are querying across model relations. That is, the name of the field, followed by a double underscore (__), followed by the name of the field in the new model, and so on for as many models as you want to join. For example:

Entry.objects.order_by('blog__name', 'headline')

如果要按照不同模型的字段排序,那么可以使用和跨模型查询相同的方式, 即利用双下划线的方式引用其他模型的字段,这样可以引用你想要的任意多的模型;

4)If you try to order by a field that is a relation to another model, Django will use the default ordering on the related model, or order by the related model’s primary key if there is no Meta.ordering specified. For example, since the Blog model has no default ordering specified:

Entry.objects.order_by('blog')
#. . . is identical to:
Entry.objects.order_by('blog__id')
#If Blog had ordering = ['name'], then the first queryset would be identical to:
Entry.objects.order_by('blog__name')

如果使用和其他模型关联的字段排序,django将会使用相关模型的默认排序方式,或是使用相关模型的主键排序如果没有指明Meta.ordering的话,如上例;

5)You can also order by query expressions by calling asc() or desc() on the expression:

Entry.objects.order_by(Coalesce('summary', 'headline').desc())

也可在表达式上调用asc()和desc()来进行排序;

6)Be cautious when ordering by fields in related models if you are also using distinct(). See the note in distinct() for an explanation of how related model ordering can change the expected results.

如果同时使用distinct(),可能会影响输出结果;

7)Note: It is permissible to specify a multi-valued field to order the results by (for example, a ManyToManyField field, or the reverse relation of a ForeignKey field). Consider this case:

class Event(Model):
parent = models.ForeignKey(
'self',
on_delete=models.CASCADE,
related_name='children',
)
date = models.DateField()
Event.objects.order_by('children__date')

Here, there could potentially be multiple ordering data for each Event; each Event with multiple children will be returned multiple times into the new QuerySet that order_by() creates. In other words, using order_by() on the QuerySet could return more items than you were working on to begin with - which is probably neither expected nor useful.
Thus, take care when using multi-valued field to order the results. If you can be sure that there will only be one ordering piece of data for each of the items you’re ordering, this approach should not present problems. If not, make sure the results are what you expect.

使用多值字段排序的注意事项;

8)There’s no way to specify whether ordering should be case sensitive. With respect to case-sensitivity, Django will order results however your database backend normally orders them. You can order by a field converted to lowercase with Lower which will achieve case-consistent ordering:

Entry.objects.order_by(Lower('headline').desc())

无法指定排序是否应该区分大小写,关于大小写的区分,django会对结果进行排序但是往往是后端数据库对其进行排序, 你可以将字段转换为小写然后实现大小写一致的排序

9)If you don’t want any ordering to be applied to a query, not even the default ordering, call order_by() with no parameters.

如果不想对查询结果排序,甚至是默认排序,可以使用不带参数的order_by();

10)You can tell if a query is ordered or not by checking the QuerySet.ordered attribute, which will be True if the QuerySet has been ordered in any way.

如果想确认查询是否进行了排序, 可以调用QuerySet.ordered属性,会返回True或False;

11)Each order_by() call will clear any previous ordering. For example, this query will be ordered by pub_date and not headline:

Entry.objects.order_by('headline').order_by('pub_date')

后一个order_by会覆盖前一个;

12)Warning: Ordering is not a free operation. Each field you add to the ordering incurs a cost to your database. Each foreign key you add will implicitly include all of its default orderings as well.
If a query doesn’t have an ordering specified, results are returned from the database in an unspecified order. A particular ordering is guaranteed only when ordering by a set of fields that uniquely identify each object in the results. For example, if a name field isn’t unique, ordering by it won’t guarantee objects with the same name always appear in the same order.

排序并不是一个免费操作,你添加排序的每个字段都会导致数据库成本增加,添加的每个外键都会隐性的增加所有的默认排序;
如果查询没有指定排序,那从数据库返回结果也是没有顺序的;只有在通过一系列和对象唯一对应的字段进行排序时才能保证特定的顺序;例如:如果name字段不唯一,那么使用name字段排序每次返回的结果有可能不同;

(13)reverse()

Use the reverse() method to reverse the order in which a queryset’s elements are returned. Calling reverse() a second time restores the ordering back to the normal direction.
To retrieve the “last” five items in a queryset, you could do this:

my_queryset.reverse()[:5]

Note that this is not quite the same as slicing from the end of a sequence in Python. The above example will return the last item first, then the penultimate item and so on. If we had a Python sequence and looked at seq[-5:], we would see the fifth-last item first. Django doesn’t support that mode of access (slicing from the end), because it’s not possible to do it efficiently in SQL.
Also, note that reverse() should generally only be called on a QuerySet which has a defined ordering (e.g., when querying against a model which defines a default ordering, or when using order_by()). If no such ordering is defined for a given QuerySet, calling reverse() on it has no real effect (the ordering was undefined prior to calling reverse(), and will remain undefined afterward).

使用此方法将QuerySet中的元素反序排列, 连续调用两次此方法会恢复原来的顺序;如果想获取QuerSet的后五个元素,可以用如上方法获得;

需要注意:该方法和python中切片调用的方式不同, 该方法会首先返回最后一个元素, 然后是倒数第二个元素等; 而使用切片[-5:]会首先返回倒数第五个元素, django不支持用切片从最后一个元素返回;
另外, 该方法只应该应用于已经定义了排序的QuerSet(默认排序或使用order_by()),如果QuerySet没有排序, 那么使用此方法不会有实际影响;使用reverse()后仍然是未定义排序;

(14)distinct(*fields)

1)Returns a new QuerySet that uses SELECT DISTINCT in its SQL query. This eliminates duplicate rows from the query results.
By default, a QuerySet will not eliminate duplicate rows. In practice, this is rarely a problem, because simple queries such as Blog.objects.all() don’t introduce the possibility of duplicate result rows. However, if your query spans multiple tables, it’s possible to get duplicate results when a QuerySet is evaluated. That’s when you’d
use distinct().

返回一个新的Querset, 底层使用SELECT DISTINCT语句;排除了查询结果中的重复的行;
在默认情况下,QuerySet不会排除重复行, 因为在简单的查询中也不会存在有重复行的可能;但是如果是跨多表查询,则有可能产生重复结果,这时就要用到distinct()了;

2)Note: Any fields used in an order_by() call are included in the SQL SELECT columns. This can sometimes lead to unexpected results when used in conjunction with distinct(). If you order by fields from a related model, those fields will be added to the selected columns and they may make otherwise duplicate rows appear to be distinct. Since the extra columns don’t appear in the returned results (they are only there to support ordering), it sometimes looks like non-distinct results are being returned.
Similarly, if you use a values() query to restrict the columns selected, the columns used in any order_by() (or default model ordering) will still be involved and may affect uniqueness of the results.
The moral here is that if you are using distinct() be careful about ordering by related models. Similarly, when using distinct() and values() together, be careful when ordering by fields not in the values() call.

注意:在order_by中使用的任何字段都会包含在select语句的列中,同distinct()一起使用时有时会导致不可预期的结果; 如果你利用相关模型的字段排序, 那这些字段会被添加到select的列中,并且有可能使相同的行看起来不同;由于额外的列不会出现在返回的结果中(它们只是支撑排序),所以有时看起来像是没有进行去重的结果;

关于产生问题的示例:

from django.db import models
class Item(models.Model):
name = models.CharField(max_length=10)
data = models.IntegerField()
class Meta:
ordering = ["name"]

The important part here is the default ordering on the name field. If you want to count how many times each distinct data value appears, you might try this:

#Warning: not quite correct!
Item.objects.values("data").annotate(Count("id"))

. . . which will group the Item objects by their common data values and then count the number of id values in each group. Except that it won’t quite work. The default ordering by name will also play a part in the grouping, so this query will group by distinct (data, name) pairs, which isn’t what you want. Instead, you should construct this queryset:

Item.objects.values("data").annotate(Count("id")).order_by()

. . . clearing any ordering in the query. You could also order by, say, data without any harmful effects, since that is already playing a role in the query.
This behavior is the same as that noted in the queryset documentation for distinct() and the general rule is the same: normally you won’t want extra columns playing a part in the result, so clear out the ordering, or at least make sure it’s restricted only to those fields you also select in a values() call.

3)只有PostSQL可以传入*fields参数…

(15)none()

Calling none() will create a queryset that never returns any objects and no query will be executed when accessing the results. A qs.none() queryset is an instance of EmptyQuerySet. Examples:

>>> Entry.objects.none()
<QuerySet []>
>>> from django.db.models.query import EmptyQuerySet
>>> isinstance(Entry.objects.none(), EmptyQuerySet)
True

返回空的queryset;

(16)union()

union(*other_qs, all=False)
Uses SQL’s UNION operator to combine the results of two or more QuerySets. For example:

>>> qs1.union(qs2, qs3)

The UNION operator selects only distinct values by default. To allow duplicate values, use the all=True argument.
union(), intersection(), and difference() return model instances of the type of the first QuerySet even if the arguments are QuerySets of other models. Passing different models works as long as the SELECT list is the same in all QuerySets (at least the types, the names don’t matter as long as the types in the same order). In such cases, you must use the column names from the first QuerySet in QuerySet methods applied to the resulting QuerySet. For example:

>>> qs1 = Author.objects.values_list('name')
>>> qs2 = Entry.objects.values_list('headline')
>>> qs1.union(qs2).order_by('name')

In addition, only LIMIT, OFFSET, COUNT(*), ORDER BY, and specifying columns (i.e. slicing, count(), order_by(), and values()/values_list()) are allowed on the resulting QuerySet. Further, databases place restrictions on what operations are allowed in the combined queries. For example, most databases don’t allow LIMIT or OFFSET in the combined queries.

使用SQL的并集操作符来组合两个或多个QuerySet的结果;
UNION操作符默认只选择去重后的结果;如果你想允许重复值, 将all参数设为True;
union(), intersection(), 和differrence()返回第一个QuerySet类型的模型实例,即使参数是来自不同model的QuerySet, 传入不同的模型也可以, 只要所有QuerySet的SELECT列表是相同的,至少类型相同(即输出表的列数相同),而字段名不同也没有关系;在这种情况下,最终产生的QuerySet的方法必须使用第一个QuerySet的列名;见上例;

另外,只有LIMIT, OFFSET, COUNT(*), ORDER BY,和指定列,例如slicing, count(), order_by(), and values()/values_list()可以用在产生的QuerySet上; 再者,数据库会对组合查询进行限制,例如,大多数数据库不允许在组合查询时使用limit或offset;

(17)intersection()

intersection(*other_qs)
Uses SQL’s INTERSECT operator to return the shared elements of two or more QuerySets. For example:

>>> qs1.intersection(qs2, qs3)

See union() for some restrictions.

使用SQL的 INTERSECT操作符以返回多个QuerySet的共同元素,限制同union;

(18)difference()

difference(*other_qs)
Uses SQL’s EXCEPT operator to keep only elements present in the QuerySet but not in some other QuerySets. For example:

>>> qs1.difference(qs2, qs3)

See union() for some restrictions.

使用SQL的 EXCEPT操作符以返回只在一个QuerySet而不在其他QuerySet中的元素,限制见union;

(19)defer()

defer(*fields)
1)In some complex data-modeling situations, your models might contain a lot of fields, some of which could contain a lot of data (for example, text fields), or require expensive processing to convert them to Python objects. If you are using the results of a queryset in some situation where you don’t know if you need those particular fields when you initially fetch the data, you can tell Django not to retrieve them from the database. This is done by passing the names of the fields to not load to defer():

Entry.objects.defer("headline", "body")

A queryset that has deferred fields will still return model instances. Each deferred field will be retrieved from the database if you access that field (one at a time, not all the deferred fields at once).
You can make multiple calls to defer(). Each call adds new fields to the deferred set:

#Defers both the body and headline fields.
Entry.objects.defer("body").filter(rating=5).defer("headline")

在某些复杂的数据建模中, 你的模型可能包括很多字段,某些字段可能包含大量数据,或者需要昂贵的处理才能转变为python对象;如果你在开始查询时并不确定是否需要某些字段,那你可以告诉django不要从数据库中检索它们,可以通过将字段名传入defer()来实现;

一个减少字段的QuerySet仍然返回模型实例;每个被减少的字段仍然可以访问到,每次访问一个字段,不是所有的减少字段;
可以多次调用defer()如上例;

2)The order in which fields are added to the deferred set does not matter. Calling defer() with a field name that has already been deferred is harmless (the field will still be deferred).
You can defer loading of fields in related models (if the related models are loading via select_related()) by using the standard double-underscore notation to separate related fields:

Blog.objects.select_related().defer("entry__headline", "entry__body")
#If you want to clear the set of deferred fields, pass None as a parameter to defer():
#Load all fields immediately.
my_queryset.defer(None)

defer()中的字段的顺序并不重要;对一个字段再次调用defer()也没有关系,它仍然会是defer的;
你还可以defer相关模型中的字段,如果相关模型是通过select_related()加载的,通过标准的双下划线的方式访问;如果你想情况derfer,可以传入参数None;

3)Some fields in a model won’t be deferred, even if you ask for them. You can never defer the loading of the primary key. If you are using select_related() to retrieve related models, you shouldn’t defer the loading of the field that connects from the primary model to the related one, doing so will result in an error.

主键永远不会被defer,即使你在该方法中调用它; 如果你使用select_related()来检索相关模型,你不应该defer和主模型相关联的字段;

4)Note: The defer() method (and its cousin, only(), below) are only for advanced use-cases. They provide an optimization for when you have analyzed your queries closely and understand exactly what information you need and have measured that the difference between returning the fields you need and the full set of fields for the model will be significant.
Even if you think you are in the advanced use-case situation, only use defer() when you cannot, at queryset load time, determine if you will need the extra fields or not. If you are frequently loading and using a particular subset of your data, the best choice you can make is to normalize your models and put the non-loaded data into a separate model (and database table). If the columns must stay in the one table for some reason, create a model with Meta.managed = False (see the managed attribute documentation) containing just the fields you normally need to load and use that where you might otherwise call defer(). This makes your code more explicit to the reader, is slightly faster
and consumes a little less memory in the Python process.
For example, both of these models use the same underlying database table:

注意:defer()方法和下面的only()只适用于高级使用;它提供了一种优化,在你仔细分析了你的查询并且准确知道你需要的信息,以及衡量过返回你需要的字段和加载全部字段间的差异的情况下;
即使你认为你是在高级使用的情况, 只在你无法在加载QuerySet时确定是否需要额外的字段时使用defer();如果你频繁加载特定字段,那最好的选择是规范化你的模型并将不加载的数据放入单独的模型中,而如果基于某种原因列必须放在一个模型中,那在模型中定义Meta.managed = False(参考相关章节)然后包含你需要的字段,其他情况下则调用defer(),这将使你的代码更清晰,更快并且会减少python进程使用的一点内存;下例:

class CommonlyUsedModel(models.Model):
f1 = models.CharField(max_length=10)
class Meta:
managed = False
db_table = 'app_largetable'
class ManagedModel(models.Model):
f1 = models.CharField(max_length=10)
f2 = models.CharField(max_length=10)
class Meta:
db_table = 'app_largetable'
# Two equivalent QuerySets:
CommonlyUsedModel.objects.all()
ManagedModel.objects.all().defer('f2')

5)If many fields need to be duplicated in the unmanaged model, it may be best to create an abstract model with the shared fields and then have the unmanaged and managed models inherit from the abstract model.
Note:When calling save() for instances with deferred fields, only the loaded fields will be saved. See save() for more details.

如果很多字段需要在unmanaged模型中重复,那可以定义一个抽象模型,其中定义共同的字段然后让其他模型继承该抽象模型;

注意:当对defer字段的实例调用save()方法时,只有加载的字段会被保存;

(20)only()

only(*fields)
The only() method is more or less the opposite of defer(). You call it with the fields that should not be deferred when retrieving a model. If you have a model where almost all the fields need to be deferred, using only() to specify the complementary set of fields can result in simpler code.
Suppose you have a model with fields name, age and biography. The following two querysets are the same, in terms of deferred fields:

Person.objects.defer("age", "biography")
Person.objects.only("name")

Whenever you call only() it replaces the set of fields to load immediately. The method’s name is mnemonic: only those fields are loaded immediately; the remainder are deferred. Thus, successive calls to only() result in only the final fields being considered:

#This will defer all fields except the headline.
Entry.objects.only("body", "rating").only("headline")

Since defer() acts incrementally (adding fields to the deferred list), you can combine calls to only() and defer() and things will behave logically:

#Final result is that everything except "headline" is deferred.
Entry.objects.only("headline", "body").defer("body")
#Final result loads headline and body immediately (only() replaces any
#existing set of fields).
Entry.objects.defer("body").only("headline", "body")

All of the cautions in the note for the defer() documentation apply to only() as well. Use it cautiously and only after exhausting your other options.
Using only() and omitting a field requested using select_related() is an error as well.
Note: When calling save() for instances with deferred fields, only the loaded fields will be saved. See save() for more details.

only是defer()的相反方法;无论何时调用only()都会立即替代加载的字段集,只有only()中的字段会被加载,连续调用only()只有最后一次会被考虑;
only和defer可以组合使用;
所有使用defer()的注意事项对only()都适用;只有在没有其他选择时再使用only();
使用only()省略select_related()需要的字段也会报错;
当调用save()方法时,只有加载的字段会保存;

(21)using()

using(alias)
This method is for controlling which database the QuerySet will be evaluated against if you are using more than one database. The only argument this method takes is the alias of a database, as defined in DATABASES.
For example:

#queries the database with the 'default' alias.
>>> Entry.objects.all()
#queries the database with the 'backup' alias
>>> Entry.objects.using('backup')

查询时要使用的数据库别名, 别名在settings中的DARABASES中规定.默认使用default数据库;

5.6.2 聚合函数

Note Aggregation functions return None when used with an empty QuerySet. For example, the Sum aggregation function returns None instead of 0 if the QuerySet contains no entries. An exception is Count, which does return 0 if the QuerySet is empty.

当QuerySet为空时聚合函数返回None而不是0, 除了Count()是返回0
(1)公共参数

expressions
Strings that reference fields on the model, or query expressions.
模型的字段的字符串,或者查询表达式;

output_field
An optional argument that represents the model field of the return value
Note: When combining multiple field types, Django can only determine the output_field if all fields are of the same type. Otherwise, you must provide the output_field yourself.
可选参数,表示返回值的字段类型, 注意,当多个字段类型组合是,django只有当所有字段类型相同时才能自己决定输出的字段类型, 否则,你必须自己给出此参数;

filter
An optional Q object that’s used to filter the rows that are aggregated.
See Conditional aggregation and Filtering on annotations for example usage.
可选参数:是一个Q对象,用于过滤聚合的对象

**extra
Keyword arguments that can provide extra context for the SQL generated by the aggregate.
其他的关键字参数,提供额外的上下文;

(2)Avg: 求平均数

class Avg(expression, output_field=FloatField(), filter=None, **extra)
Returns the mean value of the given expression, which must be numeric unless you specify a different output_field.
• Default alias: < field>__avg
• Return type: float (or the type of whatever output_field is specified)

(3)Count: 计算个数

class Count(expression, distinct=False, filter=None, **extra)
Returns the number of objects that are related through the provided expression.
• Default alias: < field>__count
• Return type: int
Has one optional argument: distinct
If distinct=True, the count will only include unique instances. This is the SQL equivalent of COUNT(DISTINCT < field>). The default value is False.

有额外的可选参数distinct, 默认为False, 当为True时, 只计算唯一的对象;

(4)Max: 找出最大值

class Max(expression, output_field=None, filter=None, **extra)
Returns the maximum value of the given expression.
• Default alias: __max
• Return type: same as input field, or output_field if supplied

(5)Min: 找出最小值

class Min(expression, output_field=None, filter=None, **extra)
Returns the minimum value of the given expression.
• Default alias: __min
• Return type: same as input field, or output_field if supplied

(6)StdDev: 求标准差

class StdDev(expression, sample=False, filter=None, **extra)
Returns the standard deviation of the data in the provided expression.
• Default alias: < field>__stddev
• Return type: float
Has one optional argument:
sample
By default, StdDev returns the population standard deviation. However, if sample=True, the return value will be the sample standard deviation.

有一个可选参数sample:默认情况下,StdDev返回总体标准偏差。 但是,如果sample = True,则返回值将是样本标准差

(7)Sum :求和

class Sum(expression, output_field=None, filter=None, **extra)
Computes the sum of all values of the given expression.
• Default alias: __sum
• Return type: same as input field, or output_field if supplied

(8)Variance: 求方差

class Variance(expression, sample=False, filter=None, **extra)
Returns the variance of the data in the provided expression.
• Default alias: __variance
• Return type: float
Has one optional argument:
sample
By default, Variance returns the population variance. However, if sample=True, the return value will be the sample variance

有一个可选参数sample:默认情况下,StdDev返回总体方差。 但是,如果sample = True,则返回值将是样本方差;

5.6.3 ForeignKey外键
(1)概述:

class ForeignKey(to, on_delete, **options)
1)A many-to-one relationship. Requires two positional arguments: the class to which the model is related and the on_delete option.
To create a recursive relationship – an object that has a many-to-one relationship with itself – use models.ForeignKey(‘self’, on_delete=models.CASCADE).
If you need to create a relationship on a model that has not yet been defined, you can use the name of the model, rather than the model object itself;

定义一对多关系,要求两个位置参数,要关联的模型以及级联删除选项;
此外,还可以递归关联,一个模型和它本身有一对多关系 :models.ForeignKey(‘self’, on_delete=models.CASCADE).
如果你关联的模型还为定义, 可以使用加引号的字符串名字;

2)To refer to models defined in another application, you can explicitly specify a model with the full application label.
For example, if the Manufacturer model above is defined in another application called production, you’d need to use:

class Car(models.Model):
manufacturer = models.ForeignKey(
'production.Manufacturer',
on_delete=models.CASCADE,
)

This sort of reference, called a lazy relationship, can be useful when resolving circular import dependencies between two applications.

引用其他应用中的模块,可以使用如上述方式;这种引用方式称为惰性关系,对解决两个应用程序之间的循环导入依赖关系非常有用;

3)A database index is automatically created on the ForeignKey. You can disable this by setting db_index to False. You may want to avoid the overhead of an index if you are creating a foreign key for consistency rather than joins, or if you will be creating an alternative index like a partial or multiple column index.

会在外键上自动创建数据库索引, 你可以通过将参数db_index设为False来禁用此功能;当你创建外键只是希望实现一致性而不是进行连接时或者你会创建替代索引(多列或部分索引)时, 会希望避免自动创建索引的开销;

4)Database Representation
Behind the scenes, Django appends “_id” to the field name to create its database column name. In the above example, the database table for the Car model will have a manufacturer_id column. (You can change this explicitly by specifying db_column) However, your code should never have to deal with the database column name, unless you
write custom SQL. You’ll always deal with the field names of your model object.

在后台, django会将"-id"自动添加到字段名后面, 你可以更改这种设定用设置db_column参数的方法, 但除非你写自定义SQL, 你永远不应该更改它, 你将会一直和字段名打交道;

(2)参数on_delete

on_delete doesn’t create a SQL constraint in the database

该参数不会在数据库中创建约束,只是模拟相应的行为;

• CASCADE

Cascade deletes. Django emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey. Model.delete() isn’t called on related models, but the pre_delete and post_delete signals are sent for all deleted objects.

级联删除;并不会为关联对象调用delete()方法, 但是会为每个被删除的对象发送pre_delete 和 post_delete信号;

• PROTECT

Prevent deletion of the referenced object by raising ProtectedError, a subclass of django.db. IntegrityError.

避免关联对象被删除, 会抛出异常;

• SET_NULL

Set the ForeignKey null; this is only possible if null is True.

删除后将外键设为null; 只有在相应字段的null参数设为True时才起作用;

• SET_DEFAULT

Set the ForeignKey to its default value; a default for the ForeignKey must be set.

删除后将外键设为默认值;必须设置外键的default参数;

• SET()

Set the ForeignKey to the value passed to SET(), or if a callable is passed in, the result of calling it. In most cases, passing a callable will be necessary to avoid executing queries at the time your models.py is imported:

from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class MyModel(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user),
)

将外键值设为传递到SET()中的值,如果一个可调用对象被传入,那将设为该对象调用后的结果;大多数情况下传入可调用对象是避免导入文件是执行查找的必要方法;例子如上;

• DO_NOTHING

Take no action. If your database backend enforces referential integrity, this will cause an IntegrityError unless you manually add an SQL ON DELETE constraint to the database field.

不采取行动;如果后端数据库强制实行参照完整性, 你必须手动将约束添加到数据库中, 否则会抛出异常;

(3)参数ForeignKey.limit_choices_to

1)Sets a limit to the available choices for this field when this field is rendered using a ModelForm or the admin (by default, all objects in the queryset are available to choose). Either a dictionary, a Q object, or a callable returning a dictionary or Q object can be used.

当使用ModelForm或admin呈现此字段时, 限制该字段的可用选择,值可以为字典或Q对象或返回字典,Q对象的可调用对象,示例如下;

staff_member = models.ForeignKey(
User,
on_delete=models.CASCADE,
limit_choices_to={'is_staff': True},
)

causes the corresponding field on the ModelForm to list only Users that have is_staff=True. This may be helpful in the Django admin.
导致ModelForm上的相关字段只显示is_staff=True的User, 这对于admin可能很有用;

2)The callable form can be helpful, for instance, when used in conjunction with the Python datetime module to limit selections by date range. For example:

def limit_pub_date_choices():
return {'pub_date__lte': datetime.date.utcnow()}
limit_choices_to = limit_pub_date_choices

可调用对象的方式可能对按日期范围限制选择有用;

3)If limit_choices_to is or returns a Q object, which is useful for complex queries, then it will only have an effect on the choices available in the admin when the field is not listed in raw_id_fields in the
ModelAdmin for the model.

???

Note: If a callable is used for limit_choices_to, it will be invoked every time a new form is instantiated. It may also be invoked when a model is validated, for example by management commands or the admin. The admin constructs querysets to validate its form inputs in various edge cases multiple times, so there is a possibility your callable may be invoked several times.
注意:如果将一个callable用于limit_choices_to,则每次实例化一个新表单时都会调用它。 也可能在验证模型时调用它,例如通过管理命令或管理员。 admin构造查询集以多次验证其在各种边缘情况下的表单输入,因此可能会多次调用您的可调用对象。

(4)参数ForeignKey.related_name

The name to use for the relation from the related object back to this one. It’s also the default value for related_query_name (the name to use for the reverse filter name from the target model). See the related
objects documentation for a full explanation and example. Note that you must set this value when defining relations on abstract models; and when you do so some special syntax is available.
If you’d prefer Django not to create a backwards relation, set related_name to ‘+’ or end it with ‘+’. For example, this will ensure that the User model won’t have a backwards relation to this model:

user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='+',
)

用于从关联对象返回到此对象的名称;也是related_query_name参数的默认值,不设置时默认使用.model_set进行反向调用;注意当使用abstract models定义关联时必须设置此参数;如果你想让django不创建返回关系,那就将此参数设为"+“或以”+"结尾,示例如上;

(5)参数ForeignKey.related_query_name

The name to use for the reverse filter name from the target model. It defaults to the value of related_name or default_related_name if set, otherwise it defaults to the name of the model:

#Declare the ForeignKey with related_query_name
class Tag(models.Model):
article = models.ForeignKey(
Article,
on_delete=models.CASCADE,
related_name="tags",
related_query_name="tag",
)
name = models.CharField(max_length=255)

# That's now the name of the reverse filter
Article.objects.filter(tag__name="important")

用于目标模型反向过滤的名称;默认为related_name 或default_related_name的值(如果设置了的话),否则默认为模型名称;

(6)ForeignKey.to_field

The field on the related object that the relation is to. By default, Django uses the primary key of the related object. If you reference a different field, that field must have unique=True.

关联对象的字段;默认情况下django使用主键作为关联字段;如果你想定义不同字段,该字段必须有unique=True;

(7)ForeignKey.db_constraint

Controls whether or not a constraint should be created in the database for this foreign key. The default is True, and that’s almost certainly what you want; setting this to False can be very bad for data integrity. That said, here are some scenarios where you might want to do this:
• You have legacy data that is not valid.
• You’re sharding your database.
If this is set to False, accessing a related object that doesn’t exist will raise its DoesNotExist exception.

控制是否应该在数据库上创建此外键约束;默认为True, 如果设为False则对数据完整性是非常不好的;也就是说,在以下几种情况下你可能想这么做:
1.你的遗留数据无效;
2.你正在分片数据库;
如果设为false, 访问不存在的关联对象会抛出DoesNotExist异常;

(8)ForeignKey.swappable

Controls the migration framework’s reaction if this ForeignKey is pointing at a swappable model. If it is True - the default - then if the ForeignKey is pointing at a model which matches the current value of
settings.AUTH_USER_MODEL (or another swappable model setting) the relationship will be stored in the migration using a reference to the setting, not to the model directly.
You only want to override this to be False if you are sure your model should always point towards the swappedin model - for example, if it is a profile model designed specifically for your custom user model.
Setting it to False does not mean you can reference a swappable model even if it is swapped out - False just means that the migrations made with this ForeignKey will always reference the exact model you specify (so it will fail hard if the user tries to run with a User model you don’t support, for example).
If in doubt, leave it to its default of True.

不懂??

5.6.4 ManyToManyField多对多字段
(1)概述

It doesn’t matter which model has the ManyToManyField, but you should only put it in one of the models – not both.

在哪个模型上设置ManyToManyField不重要,但只能在其中一个模型上设置;通常会选择要在表单上编辑的模型中,也即被包含的那个模型;

class ManyToManyField(to, **options)
A many-to-many relationship. Requires a positional argument: the class to which the model is related, which works exactly the same as it does for ForeignKey, including recursive and lazy relationships.
Related objects can be added, removed, or created with the field’s RelatedManager.

建立多对多关系; 要求一个位置参数:要关联的模型,工作方式和外键完全一致,包括递归多对多关系和惰性关系;
关联对象可以添加,删除,创建通过该字段的RelatedManager;

(2)呈现方式:

Database Representation
Behind the scenes, Django creates an intermediary join table to represent the many-to-many relationship. By default, this table name is generated using the name of the many-to-many field and the name of the table for the model that contains it. Since some databases don’t support table names above a certain length, these table names will be automatically truncated to 64 characters and a uniqueness hash will be used. This means you might see table names like author_books_9cdf4; this is perfectly normal. You can manually provide the name of the join table using the db_table option.

在后台django会创建一个中间连接表来表示多对多关系;默认情况下表名是多对多字段的名字和包含该字段的模型的表名组合而成;你可以通过使用db_table参数来更改连接表的表名;

(3)参数ManyToManyField.related_name

Same as ForeignKey.related_name.

(4)参数ManyToManyField.related_query_name

Same as ForeignKey.related_query_name.

(5)参数ManyToManyField.limit_choices_to

Same as ForeignKey.limit_choices_to.
limit_choices_to has no effect when used on a ManyToManyField with a custom intermediate table specified using the through parameter.
使用自定义的中间表时该参数无效;

(6)参数ManyToManyField.symmetrical

Only used in the definition of ManyToManyFields on self. Consider the following model:

from django.db import models
class Person(models.Model):
friends = models.ManyToManyField("self")

When Django processes this model, it identifies that it has a ManyToManyField on itself, and as a result, it doesn’t add a person_set attribute to the Person class. Instead, the ManyToManyField is assumed to be symmetrical – that is, if I am your friend, then you are my friend. If you do not want symmetry in many-to-many relationships with self, set symmetrical to False. This will force Django to add the descriptor for the reverse relationship, allowing ManyToManyField relationships to be non-symmetrical.

当django处理该模型时,它鉴别到有自已对自己的多对多字段时将不会为该模型添加person_set属性;而是将多对多字段假设为对称的, 如果你不想在自关联中使用对此,可以将此参数设为False;这将强迫django添加反向关系的描述符;

该参数只适用于递归的多对多关系;

(7)参数ManyToManyField.through

1)Django will automatically generate a table to manage many-to-many relationships. However, if you want to manually specify the intermediary table, you can use the through option to specify the Django model that represents the intermediate table that you want to use.
The most common use for this option is when you want to associate extra data with a many-to-many relationship.
If you don’t specify an explicit through model, there is still an implicit through model class you can use to directly access the table created to hold the association. It has three fields to link the models.

django会自动多对多关系的中间表;但是如果你想手动指定中间表,可以使用through参数来选择代表中间表的model;
最常见的需求是你想将额外数据与多对多关系相关联;
如果你不显性的指定through参数,仍然会有隐性的through模型来直接访问为保持关联而创建的表??

2)If the source and target models differ, the following fields are generated:
• id: the primary key of the relation.
• < containing_model>_id: the id of the model that declares the ManyToManyField.
• < other_model>_id: the id of the model that the ManyToManyField points to.

中间表有三个字段来连接模型,当源模型和目标模型不同时,三个字段为:id, < containing_model>_id(声明多对多字段的模型的id),
< other_model>_id(多对多字段指向的模型的id)

3)If the ManyToManyField points from and to the same model, the following fields are generated:
• id: the primary key of the relation.
• from_< model>id: the id of the instance which points at the model (i.e. the source instance).
• to
< model>_id: the id of the instance to which the relationship points (i.e. the target model instance).

当连接的两个模型相同时的字段;

4)This class can be used to query associated records for a given model instance like a normal model.

此类可用于查询给定模型实例的相关记录;

(8)参数ManyToManyField.through_fields

1)Only used when a custom intermediary model is specified. Django will normally determine which fields of the intermediary model to use in order to establish a many-to-many relationship automatically. However, consider the following models:

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)

Membership has two foreign keys to Person (person and inviter), which makes the relationship ambiguous and Django can’t know which one to use. In this case, you must explicitly specify which foreign keys.
Django should use using through_fields, as in the example above.
through_fields accepts a 2-tuple (‘field1’, ‘field2’), where field1 is the name of the foreign key to the model the ManyToManyField is defined on (group in this case), and field2 the name of the foreign key to the target model (person in this case).
When you have more than one foreign key on an intermediary model to any (or even both) of the models participating in a many-to-many relationship, you must specify through_fields. This also applies to recursive relationships when an intermediary model is used and there are more than two foreign keys to the model, or you want to explicitly specify which two Django should use.

仅用于指定自定制的中间表时,通常情况下django会自动决定使用中间表的那个字段来建立多对多关系,但有些情况下中间表会定义多个外键字段,这样django就无法知道使用哪两个外键字段了;因此当你对任意模型定义了超过一个外键字段,那必须使用此参数;如上例所示;
该参数组成为一个两元素元组(‘field1’, ‘field2’), field1为指向定义多对多关系的模型的外键, field2为要指向模型的外键;

2)Recursive relationships using an intermediary model are always defined as non-symmetrical – that is, with symmetrical=False – therefore, there is the concept of a “source” and a “target”. In that case ‘field1’ will be treated as the “source” of the relationship and ‘field2’ as the “target”.

当是递归多对多字段时的说明;

(9)参数ManyToManyField.db_table

The name of the table to create for storing the many-to-many data. If this is not provided, Django will assume a default name based upon the names of: the table for the model defining the relationship and the name of the field itself.

如前所述,定义中间表的表名,不定义则使用默认;

(10)参数ManyToManyField.db_constraint

Controls whether or not constraints should be created in the database for the foreign keys in the intermediary table. The default is True, and that’s almost certainly what you want; setting this to False can be very bad for data integrity. That said, here are some scenarios where you might want to do this:
• You have legacy data that is not valid.
• You’re sharding your database.
It is an error to pass both db_constraint and through.

控制是否应该在数据库上创建中间表的外键约束;默认为True, 如果设为False则对数据完整性是非常不好的;也就是说,在以下几种情况下你可能想这么做:
1.你的遗留数据无效;
2.你正在分片数据库;
同时设定db_constraint 和 through参数会抛出错误;

(11)参数ManyToManyField.swappable

Controls the migration framework’s reaction if this ManyToManyField is pointing at a swappable model. If it is True - the default - then if the ManyToManyField is pointing at a model which matches the current value of settings.AUTH_USER_MODEL (or another swappable model setting) the relationship will be stored in the migration using a reference to the setting, not to the model directly.
You only want to override this to be False if you are sure your model should always point towards the swappedin model - for example, if it is a profile model designed specifically for your custom user model.
If in doubt, leave it to its default of True.

ManyToManyField does not support validators.
null has no effect since there is no way to require a relationship at the database level.

不懂系列…

5.6.5 关联处理函数
(1)适用范围

A “related manager” is a manager used in a one-to-many or many-to many related context. This happens in two cases:
• The “other side” of a ForeignKey relation. That is:

from django.db import models
class Reporter(models.Model):
#...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

In the above example, the methods below will be available on the manager reporter.article_set.
• Both sides of a ManyToManyField relation:

class Topping(models.Model):
#...
pass
class Pizza(models.Model):
toppings = models.ManyToManyField(Topping)

In this example, the methods below will be available both on topping.pizza_set and on pizza. toppings.

在一对多关系中,适用于外键的反向关系;
在多对多关系中,双向关系都适用;

(2)add(*objs, bulk=True)

Adds the specified model objects to the related object set.
Example:

>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.add(e) # Associates Entry e with Blog b.

In the example above, in the case of a ForeignKey relationship, QuerySet.update() is used to perform the update. This requires the objects to already be saved.
You can use the bulk=False argument to instead have the related manager perform the update by calling e.save().
Using add() with a many-to-many relationship, however, will not call any save() methods (the bulk argument doesn’t exist), but rather create the relationships using QuerySet.bulk_create(). If you need to execute some custom logic when a relationship is created, listen to the m2m_changed signal, which will trigger pre_add and post_add actions.
Using add() on a relation that already exists won’t duplicate the relation, but it will still trigger signals.

用于将某个对象添加到关联对象的对象集中;
在外键关系中,底层调用update()来实现, 如果bulk参数设为False,则使用save()方法;
在多对多关系中,bulk参数不存在, 底层调用 QuerySet.bulk_create()

(3)create(**kwargs)

Creates a new object, saves it and puts it in the related object set. Returns the newly created object:

>>> b = Blog.objects.get(id=1)
>>> e = b.entry_set.create(
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... )
#No need to call e.save() at this point -- it's already been saved.
This is equivalent to (but much simpler than):
>>> b = Blog.objects.get(id=1)
>>> e = Entry(
... blog=b,
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... )
>>> e.save(force_insert=True)

Note that there’s no need to specify the keyword argument of the model that defines the relationship. In the above example, we don’t pass the parameter blog to create(). Django figures out that the new
Entry object’s blog field should be set to b.

创建对象并将其添加进关联对象集中,注意,不需要传入关联其他对象参数,django会自己判断;

(4)remove(*objs, bulk=True)

Removes the specified model objects from the related object set:

>>> b = Blog.objects.get(id=1)
>>> e = Entry.objects.get(id=234)
>>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.

Similar to add(), e.save() is called in the example above to perform the update. Using remove() with a many-to-many relationship, however, will delete the relationships using QuerySet.delete() which means no model save() methods are called; listen to the m2m_changed signal if you wish to execute custom code when a relationship is deleted.
For ForeignKey objects, this method only exists if null=True. If the related field can’t be set to None (NULL), then an object can’t be removed from a relation without being added to another. In the above example, removing e from b.entry_set() is equivalent to doing e.blog = None, and because the blog ForeignKey doesn’t have null=True, this is invalid.
For ForeignKey objects, this method accepts a bulk argument to control how to perform the operation. If True (the default), QuerySet.update() is used. If bulk=False, the save() method of each individual model instance is called instead. This triggers the pre_save and post_save signals and comes at the expense of performance.
For many-to-many relationships, the bulk keyword argument doesn’t exist.

从关联对象集中移除对象;
对于一对多关系, 只有在null=True的情况下该方法才有效, bulk为True时底层调用update()方法,反之调用save()方法.
对于多对多关系, 底层调用QuerySet.delete()方法,bulk参数不存在;

(5)clear(bulk=True)

Removes all objects from the related object set:

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.clear()

Note this doesn’t delete the related objects – it just disassociates them.
Just like remove(), clear() is only available on ForeignKeys where null=True and it also accepts the bulk keyword argument.
For many-to-many relationships, the bulk keyword argument doesn’t exist.

移除关联对象集中的所有对象, 注意并不会删除对象本身,只是取消关联;
同样在一对多关系中,只有null=True时该方法才有效;
多对多关系中,bulk参数不存在;

(6)set(objs, bulk=True, clear=False)

Replace the set of related objects:

>>> new_list = [obj1, obj2, obj3]
>>> e.related_set.set(new_list)

This method accepts a clear argument to control how to perform the operation. If False (the default), the elements missing from the new set are removed using remove() and only the new ones are added. If clear=True, the clear() method is called instead and the whole set is added at once.
For ForeignKey objects, the bulk argument is passed on to add() and remove().
For many-to-many relationships, the bulk keyword argument doesn’t exist.
Note that since set() is a compound operation, it is subject to race conditions. For instance, new objects may be added to the database in between the call to clear() and the call to add().

替换关联对象集中的对象;
该方法有一个clear参数来控制执行方法; 如果为false(默认情况),则移除新集中缺少的元素并仅添加新元素; 如果为True, 则整个新集都会一次性添加进去;
对于一对多关系,将bulk参数传入add() 和 remove()方法;
对于多对多关系,bulk参数不存在;
注意set()方法是复合操作,所以符合竞性条件, 例如可以在对clear()的调用和对add()的调用之间向数据库添加新对象。

(7)注意事项;

Note: Note that add(), create(), remove(), clear(), and set() all apply database changes immediately for all types of related fields. In other words, there is no need to call save() on either end of the relationship.
Also, if you are using an intermediate model for a many-to-many relationship, then the add(), create(), remove(), and set() methods are disabled.
If you use prefetch_related(), the add(), remove(), clear(), and set() methods clear the prefetched cache.

add(), create(), remove(), clear(), set() 都会立即对所有类型的相关字段应用数据库更改, 也就是说, 无需使用save()方法;
如果使用手动的中间表处理多对多关系, 那么add(), create(), remove(), 和set()方法无效;
如果使用prefetch_related()方法, add(), remove(), clear(), set()则去除预取的缓存;

5.6.6 查询语句lookups

Field lookups are how you specify the meat of an SQL WHERE clause. They’re specified as keyword arguments to the QuerySet methods filter(), exclude() and get().

字段查找是指定SQL WHERE子句的内容的方式, 它们以filter(), exclude() 和 get()中的关键字参数的方式指定;

(1)exact

An “exact” match.If you don’t provide a lookup type – that is, if your keyword argument doesn’t contain a double underscore – the lookup type is assumed to be exact.

精确匹配,如果不指定查询类型,即没有双下划线, 则默认为精确查找;

(2)iexact

A case-insensitive match.

不区分字母大小写的精确匹配;例如:

>>> Blog.objects.get(name__iexact="beatles blog")
#Would match a Blog titled "Beatles Blog", "beatles blog", or even "BeAtlES blOG".

(3)contains

Case-sensitive containment test. For example:

Entry.objects.get(headline__contains='Lennon')
#Roughly translates to this SQL:
SELECT ... WHERE headline LIKE '%Lennon%';

Note this will match the headline ‘Today Lennon honored’ but not ‘today lennon honored’.
There’s also a case-insensitive version, icontains.

区分大小写的包含查找;见上例;

(4)icontains
不区分大小写的包含查找;见上述;

(5)startswith, endswith

Starts-with and ends-with search, respectively. There are also case-insensitive versions called istartswith and iendswith.

分别是以…开始和以…结束的匹配

(6)istartswith 和 iendswith
不区分大小写的版本;

(7)in

In a given iterable; often a list, tuple, or queryset. It’s not a common use case, but strings (being iterables) are accepted.

在一个给定的可迭代对象中,例如列表, 元组, 字符串;
也可以动态的指定,相当于sql中select的嵌套查询:

inner_qs = Blog.objects.filter(name__contains='Cheddar')
entries = Entry.objects.filter(blog__in=inner_qs)

在有values()的情况下也可以, 但要注意values返回的字典只有一组键值对:

inner_qs = Blog.objects.filter(name__contains='Ch').values('name')
entries = Entry.objects.filter(blog__name__in=inner_qs)

#Bad code! Will raise a TypeError.
inner_qs = Blog.objects.filter(name__contains='Ch').values('name', 'id')
entries = Entry.objects.filter(blog__name__in=inner_qs)

注意性能比较:

Be cautious about using nested queries and understand your database server’s performance characteristics (if in doubt, benchmark!). Some database backends, most notably MySQL, don’t optimize nested queries very well. It is more efficient, in those cases, to extract a list of values and then pass that into the second query. That is, execute two queries instead of one:

values = Blog.objects.filter(
name__contains='Cheddar').values_list('pk', flat=True)
entries = Entry.objects.filter(blog__in=list(values))

Note the list() call around the Blog QuerySet to force execution of the first query. Without it, a nested query would be executed, because QuerySets are lazy.

尤其是MySQL,没有很好的优化嵌套查询, 所有把查询分成两次将比一次效率更高,见上例

(8) gt, gte, lt, lte
分别为大于, 大于等于, 小于, 小于等于;

(9)range

Range test (inclusive).
Example:

import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))

#sql相当于
SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';

You can use range anywhere you can use BETWEEN in SQL — for dates, numbers and even characters.

在某个范围;在SQL中使用between的地方你都可以使用range, 无论是数字, 日期, 还是字母;

Warning: Filtering a DateTimeField with dates won’t include items on the last day, because the bounds are interpreted as “0am on the given date”. If pub_date was a DateTimeField, the above expression would be turned into this SQL:
SELECT … WHERE pub_date BETWEEN ‘2005-01-01 00:00:00’ and ‘2005-03-31 00:00:00’;
Generally speaking, you can’t mix dates and datetimes.

注意,当指定时间范围时,将不会包含最后一天,见上述;

(10)date

For datetime fields, casts the value as date. Allows chaining additional field lookups. Takes a date value.
Example:

Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

查找日期适用于datetime字短;

(11)year

For date and datetime fields, an exact year match. Allows chaining additional field lookups. Takes an integer year.
Example:

Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)
#SQL equivalent:
SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
SELECT ... WHERE pub_date >= '2005-01-01';

选择年份,适用于date和datetime字段,精确匹配;

(12)month

For date and datetime fields, an exact month match. Allows chaining additional field lookups. Takes an integer 1 (January) through 12 (December).
Example:

Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)

匹配月份,适用于date 和 datetime 字段;

(13)day

For date and datetime fields, an exact day match. Allows chaining additional field lookups. Takes an integer day.
Example:

Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)
#SQL equivalent:
SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';

(The exact SQL syntax varies for each database engine.)
Note this will match any record with a pub_date on the third day of the month, such as January 3, July 3, etc.

用于date 和 datetime 字段,匹配某一日,传入一个整数;

(14)week

For date and datetime fields, return the week number (1-52 or 53) according to ISO-8601, i.e., weeks start on a Monday and the first week contains the year’s first Thursday.
Example:

Entry.objects.filter(pub_date__week=52)
Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38)

(No equivalent SQL code fragment is included for this lookup because implementation of the relevant query varies among different database engines.)
When USE_TZ is True, fields are converted to the current time zone before filtering.

匹配周数;

(15)week_day

For date and datetime fields, a ‘day of the week’ match. Allows chaining additional field lookups.
Takes an integer value representing the day of week from 1 (Sunday) to 7 (Saturday).
Example:

Entry.objects.filter(pub_date__week_day=2)
Entry.objects.filter(pub_date__week_day__gte=2)

匹配每周的某一天;

(16)quarter

For date and datetime fields, a ‘quarter of the year’ match. Allows chaining additional field lookups. Takes an integer value between 1 and 4 representing the quarter of the year.
Example to retrieve entries in the second quarter (April 1 to June 30):

Entry.objects.filter(pub_date__quarter=2)

(No equivalent SQL code fragment is included for this lookup because implementation of the relevant query varies among different database engines.)
When USE_TZ is True, datetime fields are converted to the current time zone before filtering. This requires time zone definitions in the database.

匹配季度;

(17)time

For datetime fields, casts the value as time. Allows chaining additional field lookups. Takes a datetime.time value.
Example:

Entry.objects.filter(pub_date__time=datetime.time(14, 30))
Entry.objects.filter(pub_date__time__range=(datetime.time(8), datetime.time(17)))

(No equivalent SQL code fragment is included for this lookup because implementation of the relevant query varies among different database engines.)
When USE_TZ is True, fields are converted to the current time zone before filtering.

匹配时间,适用于datetime字段, 将值转换为时间, 传入一个datetime.time值;

(18)hour

For datetime and time fields, an exact hour match. Allows chaining additional field lookups. Takes an integer between 0 and 23.
Example:

Event.objects.filter(timestamp__hour=23)
Event.objects.filter(time__hour=5)
Event.objects.filter(timestamp__hour__gte=12)
SQL equivalent:
SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';

匹配小时;传入一个整数

(19)minute

For datetime and time fields, an exact minute match. Allows chaining additional field lookups. Takes an integer between 0 and 59.
Example:

Event.objects.filter(timestamp__minute=29)
Event.objects.filter(time__minute=46)
Event.objects.filter(timestamp__minute__gte=29)
SQL equivalent:
SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
SELECT ... WHERE EXTRACT('minute' FROM time) = '46';
SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29';

(The exact SQL syntax varies for each database engine.)
For datetime fields, When USE_TZ is True, values are converted to the current time zone before filtering.

匹配分钟;传入一个整数;

(20)second

For datetime and time fields, an exact second match. Allows chaining additional field lookups. Takes an integer between 0 and 59.
Example:

Event.objects.filter(timestamp__second=31)
Event.objects.filter(time__second=2)
Event.objects.filter(timestamp__second__gte=31)
SQL equivalent:
SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
SELECT ... WHERE EXTRACT('second' FROM time) = '2';
SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31';
(

匹配秒数,传入一个整数;

(21)isnull

Takes either True or False, which correspond to SQL queries of IS NULL and IS NOT NULL, respectively.
Example:

Entry.objects.filter(pub_date__isnull=True)
SQL equivalent:
SELECT ... WHERE pub_date IS NULL;

传入True或False, 匹配值为null或不是null的对象;

(22)regex

Case-sensitive regular expression match.
The regular expression syntax is that of the database backend in use. In the case of SQLite, which has no built in regular expression support, this feature is provided by a (Python) user-defined REGEXP function, and the regular expression syntax is therefore that of Python’s re module.
Example:

Entry.objects.get(title__regex=r'^(An?|The) +')
SQL equivalents:
SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL
SELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c'); -- Oracle
SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL
SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite

Using raw strings (e.g., r’foo’ instead of ‘foo’) for passing in the regular expression syntax is recommended.

区分大小写的正则匹配;正则表达式语法是正在使用的后端数据库的语法; 使用原生字符串是推荐的;

(23)iregex

Case-insensitive regular expression match.

不区分大小写的正则匹配;

5.6.7跨表查询Lookups that span relationships

django提供强大的跨表查询方式,利用双下划线可以查询与本对象关联的对象的内容;例如:

>>> Entry.objects.filter(blog__name='Beatles Blog')

(2)注意使用filter时,多表查询使用多个filter和一个filter内多个条件将导致不一样的结果:多个filter代表筛选多次,后一次筛选从前一次筛选出的对象中重新筛选, 而一个filter中多个条件则是使用多个条件同时进行一次筛选,详细解释及示例如下;

Everything inside a single filter() call is applied simultaneously to filter out items matching all those requirements. Successive filter() calls further restrict the set of objects, but for multi-valued relations, they apply to any object linked to the primary model, not necessarily those objects that were selected by an earlier filter() call.
That may sound a bit confusing, so hopefully an example will clarify. To select all blogs that contain entries with both “Lennon” in the headline and that were published in 2008 (the same entry satisfying both conditions), we would write:

Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)

To select all blogs that contain an entry with “Lennon” in the headline as well as an entry that was published in 2008, we would write:

Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

Suppose there is only one blog that had both entries containing “Lennon” and entries from 2008, but that none of the entries from 2008 contained “Lennon”. The first query would not return any blogs, but the second query would return that one blog.
In the second example, the first filter restricts the queryset to all those blogs linked to entries with “Lennon” in the headline. The second filter restricts the set of blogs further to those that are also linked to entries that were published in 2008. The entries selected by the second filter may or may not be the same as the entries in the first filter. We are
filtering the Blog items with each filter statement, not the Entry items.

(3)注意:exclude()表现和filter不同,同一个exclude()中的多个条件会排除满足其中任一条件的所有对象,为实现排除同时满足多个条件的对象的查找, 只能使用多次筛选,见下例;

Note: The behavior of filter() for queries that span multi-value relationships, as described above, is not implemented equivalently for exclude(). Instead, the conditions in a single exclude() call will not necessarily refer to the same item.
For example, the following query would exclude blogs that contain both entries with “Lennon” in the headline and entries published in 2008:

Blog.objects.exclude(
entry__headline__contains='Lennon',
entry__pub_date__year=2008,
)

However, unlike the behavior when using filter(), this will not limit blogs based on entries that satisfy both conditions. In order to do that, i.e. to select all blogs that do not contain entries published with “Lennon” that were published in 2008, you need to make two queries:

Blog.objects.exclude(
entry__in=Entry.objects.filter(
headline__contains='Lennon',
pub_date__year=2008,
),
)

5.6.8 F对象

1)Instances of F() act as a reference to a model field within a query. These references can then be used in query filters to compare the values of two different fields on the same model instance.
For example, to find a list of all blog entries that have had more comments than pingbacks, we construct an F() object to reference the pingback count, and use that F() object in the query:

>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

F对象可以在查询中引用模型的其他字段,并可以用于做计算或与其他字段进行比较;

2)Django supports the use of addition, subtraction, multiplication, division, modulo, and power arithmetic with F() objects, both with constants and with other F() objects. To find all the blog entries with more than twice as many comments as pingbacks, we modify the query:

>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

F对象支持加,减,乘,除,模运算, 幂运算与常量或者其他F对象;

3)You can also use the double underscore notation to span relationships in an F() object. An F() object with a double underscore will introduce any joins needed to access the related object. For example, to retrieve all the entries where the author’s name is the same as the blog name, we could issue the query:

>>> Entry.objects.filter(authors__name=F('blog__name'))

可以在F对象中使用双下划线引用相关的其他模型中的对象;

4)For date and date/time fields, you can add or subtract a timedelta object. The following would return all entries that were modified more than 3 days after they were published:

>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

对于date或date/time字段,可以加上或减去timedelta对象;

5)The F() objects support bitwise operations by .bitand(), .bitor(), .bitrightshift(), and . bitleftshift(). For example:

>>> F('somefield').bitand(16)

F对象支持按位运算;

6)F对象的好处

F() therefore can offer performance advantages by:
• getting the database, rather than Python, to do work
• reducing the number of queries some operations require

Another useful benefit of F() is that having the database - rather than Python - update a field’s value avoids a race condition.
If two Python threads execute the code in the first example above, one thread could retrieve, increment, and save a field’s value after the other has retrieved it from the database. The value that the second thread saves will be based on the original value; the work of the first thread will simply be lost.
If the database is responsible for updating the field, the process is more robust: it will only ever update the field based on the value of the field in the database when the save() or update() is executed, rather than based on its value when the instance was retrieved.

(7)F对象在调用save后仍然会留存,使用须注意:

F() objects assigned to model fields persist after saving the model instance and will be applied on each save(). For example:

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()
reporter.name = 'Tintin Jr.'
reporter.save()

stories_filed will be updated twice in this case. If it’s initially 1, the final value will be 3.

(8)与annotate的使用:

F() can be used to create dynamic fields on your models by combining different fields with arithmetic:

company = Company.objects.annotate(
chairs_needed=F('num_employees') - F('num_chairs'))

If the fields that you’re combining are of different types you’ll need to tell Django what kind of field will be returned. Since F() does not directly support output_field you will need to wrap the expression with
ExpressionWrapper:

from django.db.models import DateTimeField, ExpressionWrapper, F
Ticket.objects.annotate(
expires=ExpressionWrapper(
F('active_at') + F('duration'), output_field=DateTimeField()))

When referencing relational fields such as ForeignKey, F() returns the primary key value rather than a model instance:

>> car = Company.objects.annotate(built_by=F('manufacturer'))[0]
>> car.manufacturer
<Manufacturer: Toyota>
>> car.built_by
3

(9)利用F对空值进行排序:

Using F() to sort null values
Use F() and the nulls_first or nulls_last keyword argument to Expression.asc() or desc() to control the ordering of a field’s null values. By default, the ordering depends on your database.
For example, to sort companies that haven’t been contacted (last_contacted is null) after companies that have been contacted:

from django.db.models import F
Company.object.order_by(F('last_contacted').desc(nulls_last=True))

5.6.9 转义百分号和下划线

The field lookups that equate to LIKE SQL statements (iexact, contains, icontains, startswith, istartswith, endswith and iendswith) will automatically escape the two special characters used in LIKE statements – the percent sign and the underscore. (In a LIKE statement, the percent sign signifies a multiple-character
wildcard and the underscore signifies a single-character wildcard.)

等同于SQL中like语句的查找((iexact, contains, icontains, startswith, istartswith, endswith and iendswith)将自动对百分号和下划线进行转义;

>>> Entry.objects.filter(headline__contains='%')
#Django takes care of the quoting for you; the resulting SQL will look something like this:
SELECT ... WHERE headline LIKE '%\%%';

5.6.10 Q对象
(1)通常filter等方法中写的多个查询条件是并列关系(and),如果想实现更复杂的查询(如或,非等)就需要使用Q对象;

A Q object (django.db.models.Q) is an object used to encapsulate a collection of keyword arguments. These keyword arguments are specified as in “Field lookups” above.

Q对象是用于封装一系列关键字参数的;
例如:

from django.db.models import Q
Q(question__startswith='What')

(2)Q对象可使用&和|符号连接起来,表示与和或:

Q objects can be combined using the & and | operators. When an operator is used on two Q objects, it yields a new Q object.

Q(question__startswith='Who') | Q(question__startswith='What')
#This is equivalent to the following SQL WHERE clause:
WHERE question LIKE 'Who%' OR question LIKE 'What%'

(3)可使用~表示非:

You can compose statements of arbitrary complexity by combining Q objects with the & and | operators and use parenthetical grouping. Also, Q objects can be negated using the ~ operator, allowing for combined lookups that combine both a normal query and a negated (NOT) query:

Q(question__startswith='Who') | ~Q(pub_date__year=2005)

(4)查询函数如filter(), exclude(), get()都可以传入一个或多个Q对象作为位置参数, 如果多个Q对象并列,相当于AND:

Each lookup function that takes keyword-arguments (e.g. filter(), exclude(), get()) can also be passed one or more Q objects as positional (not-named) arguments. If you provide multiple Q object arguments to a lookup function, the arguments will be “AND”ed together. For example:

Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
#. . . roughly translates into the SQL:
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

(5)Q对象可以和关键字参数混合使用,表示AND,但Q对象必须放关键字参数前面,否则报错:

Lookup functions can mix the use of Q objects and keyword arguments. All arguments provided to a lookup function (be they keyword arguments or Q objects) are “AND”ed together. However, if a Q object is provided, it must precede the definition of any keyword arguments. For example:

Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who',
)
#. . . would be a valid query, equivalent to the previous example; but:
# INVALID QUERY
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

Q对象构造举例

#传入条件进行查询:
q1 = Q()
q1.connector = 'OR'
q1.children.append(('id', 1))
q1.children.append(('id', 2))
q1.children.append(('id', 3))
    
models.Tb1.objects.filter(q1)


#合并条件进行查询:
con = Q()
 
q1 = Q()
q1.connector = 'OR'
q1.children.append(('id', 1))
q1.children.append(('id', 2))
q1.children.append(('id', 3))
 
q2 = Q()
q2.connector = 'OR'
q2.children.append(('status', '在线'))
 
con.add(q1, 'AND')
con.add(q2, 'AND')
 
models.Tb1.objects.filter(con)

5.6.10OneToOneField

class OneToOneField(to, on_delete, parent_link=False, **options)
A one-to-one relationship. Conceptually, this is similar to a ForeignKey with unique=True, but the “reverse” side of the relation will directly return a single object.
This is most useful as the primary key of a model which “extends” another model in some way; Multi-table inheritance is implemented by adding an implicit one-to-one relation from the child model to the parent model, for example.
One positional argument is required: the class to which the model will be related. This works exactly the same as it does for ForeignKey, including all the options regarding recursive and lazy relationships.
If you do not specify the related_name argument for the OneToOneField, Django will use the lower-case name of the current model as default value.

一对一关系, 概念上讲,和具有unique=True的外键相似,但反向关系返回的是单个对象;
这对想要以某种方式扩展另一个模型的模型主键非常有用;例如,通过隐式的从子模型向父模型添加一对一关系完成多表继承;
要求一个位置参数:模型要相关的类;和外键的工作方式相同,包括递归和惰性关系;
如果不指定related_name, django会使用模型名的小写作为默认值;示例如下:

from django.conf import settings
from django.db import models
class MySpecialUser(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
supervisor = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='supervisor_of',
)

#your resulting User model will have the following attributes:
>>> user = User.objects.get(pk=1)
>>> hasattr(user, 'myspecialuser')
True
>>> hasattr(user, 'supervisor_of')
True

#A DoesNotExist exception is raised when accessing the reverse relationship if an entry in the related table doesn’t exist. For example, if a user doesn’t have a supervisor designated by MySpecialUser:
>>> user.supervisor_of
Traceback (most recent call last):
...
DoesNotExist: User matching query does not exist.

Additionally, OneToOneField accepts all of the extra arguments accepted by ForeignKey, plus one extra argument:
OneToOneField.parent_link
When True and used in a model which inherits from another concrete model, indicates that this field should be used as the link back to the parent class, rather than the extra OneToOneField which would normally be implicitly created by subclassing.

一对一关系还有一个额外参数:parent_link:
当该参数为True并且使用在一个继承于另一个具体模型的模型中时,表明此字段是用于链接到父类的,而不是一般意义的额外的一对一字段;

6.关于QuerySet的缓存
QuerySet引入缓存以减少访问数据库的次数;
以下是一些使用示例:
(1)
以下示例会访问两次数据库:

>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])

避免方式:

>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset]) # Evaluate the query set.
>>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.

(2)并不是每次都会缓存查询结果:

Querysets do not always cache their results. When evaluating only part of the queryset, the cache is checked, but if it is not populated then the items returned by the subsequent query are not cached. Specifically, this means that limiting the queryset using an array slice or an index will not populate the cache.

使用切片或索引的方式访问QuerySet会先检查缓存,如果没有后续也将不会创建缓存:

>>> queryset = Entry.objects.all()
>>> print(queryset[5]) # Queries the database
>>> print(queryset[5]) # Queries the database again

优化方案:

>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database
>>> print(queryset[5]) # Uses cache
>>> print(queryset[5]) # Uses cache

(3)其他会创建缓存的操作:

Here are some examples of other actions that will result in the entire queryset being evaluated and therefore populate the cache:

>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)

(4)注意:

Note: Simply printing the queryset will not populate the cache. This is because the call to repr() only returns a slice of the entire queryset.

仅仅打印QuerySet并不会创建缓存!!!

7.关于asc()和desc()

asc(nulls_first=False, nulls_last=False)
Returns the expression ready to be sorted in ascending order.
nulls_first and nulls_last define how null values are sorted. See Using F() to sort null values for example usage.

desc(nulls_first=False, nulls_last=False)
Returns the expression ready to be sorted in descending order.
nulls_first and nulls_last define how null values are sorted. See Using F() to sort null values for example usage.

When a query expression wraps another expression, it is responsible for calling the appropriate methods on the wrapped expression

升序和降序,参数的使用须配合F对象;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值