MongoEngine中⽂参考
在MongoDB⾥⾯,⼀条⽂档⼤致相当于关系型数据库⾥⾯的⼀⾏。在关系型数据库⾥⾯,⾏是被存储在表⾥⾯,并且有⼀个严格的结构。MongoDB⾥⾯把⽂档存储在集合⾥⾯⽽不是存在表⾥⾯,最根本上的不同就是在数据库层⾯上没有强制的结构限制。
定义⼀个⽂档纲要
MongoEngine允许你为⽂档定义⼀个纲要这可以帮你减少编码错误,让你利⽤现有的字段来定义各种功能的函数。
定义⼀个⽂档的纲要,⾸先需要创建⼀个继承 Document 的类。⽂档的字段都被作为这个继承类的属性。
from mongoengine import *
import datetime
class Page(Document):
title = StringField(max_length=200, required=True)
date_modified = DateTimeField(default=w)
动态⽂档纲要 MongoDB的⼀个好处就是为集合定义动态的纲要,这在有动态⽂档的场景下能让数据有组织,有计划的存储。
动态⽂档与⼀般⽂档的⼯作⽅式⼀样,但是任何为它们设置的数据或属性也会被存储
from mongoengine import *
class Page(DynamicDocument):
title = StringField(max_length=200, required=True)
# Create a new page and add tags >>> page = Page(title='Using MongoEngine')
>>> page.tags = ['mongodb', 'mongoengine']a>>> page.save()
>>> Page.objects(tags='mongoengine').count()
>>> 1
字段
在默认情况下,字段可以不需要。让⼀个字段强制存在,可以将这个字段的 require 关键字设置为 true 。字段也可以有验证限制。字段也可以设置默认值,在字段没有被提供值的时候会⽤到。可以使⽤的字段类型如下:
BinaryField
BooleanField
ComplexDateTimeField
DateTimeField
DecimalField
DictField
DynamicField
EmailField
EmbeddedDocumentField
FileField
FloatField
GenericEmbeddedDocumentField
GenericReferenceField
ImageField
IntField
ListField
MapField
ObjectIdField
ReferenceField
SequenceField
SortedListField
StringField
URLField
UUIDField
字段参数
db_field(default: None)
mongodb字段名
name(default: None)
mongoengine字段名
required(default: False)
如果设置为True,那么在存储数据的时候,如果这个字段为空,在验证的时候会产⽣ValidateError。
default(default: None)
为字段设置默认值。
default这个参量的定义是遵循 the general rules on Python,实例如下:
class ExampleFirst(Document):
# Default an empty list values = ListField(IntField(), default=list)
class ExampleSecond(Document):
# Default a set of values values = ListField(IntField(), default=lambda: [1,2,3])
class ExampleDangerous(Document):
# This can make an .append call to add values to the default (and all the following objects), # instead to just an object values = ListField(IntField(), default=[1,2,3])
unique(default: False)
如果设置为True,那么同⼀个collection⾥⾯不能有⼀个document与它的值相同。
unique_with(default: None)
让⼀个字段与该字段⼀同设置为unique
primary_key(default: False)
如果设置为True,那么这个字段被设置为主键。
choices(default: None)
当字段的值需要限制的时候设置⼀个可迭代的list或者tuple,也可以是⼀个嵌套的tuple。
SIZE = (('S', 'Small'),
('M', 'Medium'),
('XL', 'Extra Large'),
('XXL', 'Extra Extra Large'))
class Shirt(Document):
size = StringField(max_length=3, choices=SIZE)
或者只包含值的也可以
SIZE = ('S', 'M', 'L', 'XL', 'XXL')
class Shirt(Document):
size = StringField(max_length=3, choices=SIZE)
help_text(default: None) 在使⽤这个字段的时候输出帮助---在使⽤表单的时候⽤到。
verbose_name(default: None) 为这个字段起更能让⼈接受的名字---在使⽤表单的时候⽤到。
列表字段
mongodb⾥⾯允许你存储list。给document添加⼀个list字段,使⽤ListField类型,ListField把另⼀个类型的对象作为它的第⼀个参数,⽤来指定在list⾥⾯存储的数据类型。
class Page(Document):
tags = ListField(StringField(max_length=50))
嵌⼊的document mongodb能够存储嵌⼊的document。需要为这些document定义Schemata,它们也是规范的document。定义嵌⼊的document的时候,像往常⼀样定义⼀个document,但是要继承EmbeddedDocument⽽不是Document:
class Comment(EmbeddedDocument):
content = StringField()
在document中嵌⼊另⼀个document,使⽤ EmbeddedDocumentField 类型。第⼀个参数是嵌⼊document的类:
class Page(Document):
comments = ListField(EmbeddedDocumentField(Comment))
comment1 = Comment(content='Good work!')
comment2 = Comment(content='Nice article!')
page = Page(comments=[comment1, comment2])
字典字段通常,会使⽤嵌⼊document来代替字典----总的来说字典不⽀持任何类型检查与约束。可是,有时候你不知道你想存储的数据是什么类型,这时候使⽤ DictField会⽐较合适:
class SurveyResponse(Document):
date = DateTimeField()
user = ReferenceField(User)
answers = DictField()
survey_response = SurveyResponse(w(), user=request.user)
response_form = ResponseForm(request.POST)
survey_response.answers = response_form.cleaned_data()
survey_response.save()
引⽤字段引⽤字段⽤来引⽤在数据库⾥⾯存储的其他document,使⽤ ReferenceField ,在构造器中把另⼀个document的类作为第⼀个参数,然后就可以简单地指定document到这个字段。
class User(Document):
name = StringField()
class Page(Document):
content = StringField()
author = ReferenceField(User)
john = User(name="John Smith")
john.save()
post = Page(content="Test Page")
post.author = john
post.save()
User对象⾃动成为了引⽤类,在检索Page的时候会间接引⽤User。当引⽤字段引⽤的是⾃⾝的时候,
在ReferenceField 的构造器中添加'self' 作为它的参数,如果引⽤还未定义的document,则使⽤应⽤类的类名作为构造器参数:
class Employee(Document):
name = StringField()
boss = ReferenceField('self')
profile_page = ReferenceField('ProfilePage')
class ProfilePage(Document):
content = StringField()
使⽤ListField的⼀对多
如果你想利⽤⼀个引⽤的list来实现⼀对多,那么引⽤会被存储成 DBRefs ,那么需要查询的时候,你也需要通过这个对象来进⾏查询。class User(Document):
name = StringField()
class Page(Document):
content = StringField()
authors = ListField(ReferenceField(User))
bob = User(name="Bob Jones").save()
john = User(name="John Smith").save()
Page(content="Test Page", authors=[bob, john]).save()
Page(content="Another Page", authors=[john]).save()
# Find all pages Bob authored Page.objects(authors__in=[bob])
# Find all pages that both Bob and John have authored Page.objects(authors__all=[bob, john])
处理删除引⽤的document 默认情况下,mongodb不会检查数据的完整性,如果删除了其他document正在引⽤的document会引发⼀致性的问题。mongoengine的ReferenceField 添加了⼀些功能来维持数据⼀致性,为没⼀个引⽤提供了删除规则。删除规则通过声明ReferenceField 的reverse_delete_rule 属性
来指定,就像这样:
class Employee(Document):
...
profile_page = ReferenceField('ProfilePage', reverse_delete_rule=mongoengine.NULLIFY)
这个例⼦中的声明定义了如果⼀个Employee对象删除,与它关联的ProfilePage也会删除。如果⼀批Employee对象被删除,那么与它关联的ProfilePage也会被删除。它的值也可以被设置成如下的常量:
mongoengine.DO_NOTHING
这是默认值不做任何事。在删除的时候速度⽐较快,但是会带来数据不⼀致和空引⽤的问题。
mongoengine.DENY
如果仍有document引⽤到这个对象,那么会阻⽌删除
mongoengine.NULLIFY
任何对象的字段关联到这个对象的如果被删除,那么这个document也会被删除,关联关系作废。
mongoengine.CASCADE
任何对象的字段引⽤到这个对象的会被先删除
mongoengine.PULL
移除对于对象的引⽤关系
通⽤引⽤字段
⼀种次选的引⽤字段也是存在的, GenericReferenceField 。它可以让你引⽤任何类型的document,因此它不⽤其他document的类来作为它的参数:
class Link(Document):
url = StringField()
class Post(Document):
title = StringField()
class Bookmark(Document):
bookmark_object = GenericReferenceField()
link = Link(url='hmarr/mongoengine/')
link.save()
post = Post(title='Using MongoEngine')
post.save()
Bookmark(bookmark_object=link).save()
Bookmark(bookmark_object=post).save()
唯⼀性约束 mongoengine⾥⾯允许你制定字段在collection⾥⾯的值是唯⼀的,通过在构造器⾥⾯指定 unique=True 如果你想在数据库⾥存储已存在的value的document,会引发OperationError。你也可以通过使⽤unique_with来设置多字段的唯⼀性约束,它的值可以是⼀个字段名,或者是存储了字段名的list或tuple。
class User(Document):
username = StringField(unique=True)
first_name = StringField()
last_name = StringField(unique_with='first_name')
在保存时跳过document验证你可以在使⽤save()的时候通过设置validate=False 来在保存的时候跳过验证
class Recipient(Document):
name = StringField()
email = EmailField()
recipient = Recipient(name='admin', email='root@localhost')
profile中文recipient.save() # will raise a ValidationError while recipient.save(validate=False) # won't Document Collection
document对象是直接继承于Document ,会在数据库⾥⾯拥有它们⾃⼰的collection。这个collection的
名字默认就是类的名字,被转化成了⼩写。如果你想改变这个collection的名字,可以在类⾥⾯创建⼀个字典属性叫meta,然后可以随意设置这个collection的名字了。
class Page(Document):
title = StringField(max_length=200, required=True)
meta = {'collection': 'cmsPage'}
索引你可以在document⾥⾯指定索引来使查询的时候速度更快。这个可以通过在meta字典⾥声明⼀个叫键为 'indexes', 值为存放索引规则的list的键值对来实现,⼀个索引规则可以是⼀个字段名,或者是由⼏个字段名组成的tuple,也可以是⼀个包含完整索引声明的字典。可以
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论