用于在单个页面上进行跨模型搜索的框架和通用应用程序
django-appsearch的Python项目详细描述
django应用程序搜索
用于在单个页面上进行跨模型搜索的框架和通用应用程序
主要章节:
作者
- 蒂姆·瓦伦塔
- 高拉夫·卡普尔
- 史蒂文·克拉斯
用法
AppSearch集成由几个单独的部分组成。在最简单的默认设置中,您必须至少执行以下操作:
- 向AppSearch注册模型
- call
appsearch.autodiscover()
(可能在项目的url中的某个位置,比如类似的管理函数) - 在搜索页面出现的地方创建主视图
- 创建一个可以呈现搜索表单的简单模板
有多种方法可以自定义模板、修改搜索查询集等,基本介绍后将介绍这些方法。
型号注册
在django.contrib.admin
接口之后,appsearch包含一个registry
子模块,该子模块包含一个modelsearch
类(沿着admin的modelsadmin
行),以及一个名为search
的默认注册表对象
modelsearch
有几个基本选项,其中最重要的是搜索字段
和显示字段
我们将使用这个示例基本模型进行注册,为了演示,它会接触到其他一些伪模型:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()
搜索字段
若要注册此模型,请在应用程序的目录中放置一个search.py
子模块,并至少包含此基本注册代码。为了清楚起见,我们将省略大部分car
字段:
# car/search.pyfromappsearch.registryimportModelSearch,searchfromproject.car.modelsimportCarclassCarSearch(ModelSearch):search_fields=('year','nickname','adoption_story',)search.register(Car,CarSearch)
搜索字段
是一个iterable,其项描述可搜索字段。此处列出字段的顺序将在AppSearch UI中得到遵守。如果列表中的项直接描述模型字段名,则该项可以是字符串。将查找该字段,并将其详细名称
存储在ui中使用。要显式声明"详细名称"以便在AppSearch UI中使用,可以将字符串设为详细名称和字段名称的2元组:
search_fields=('year',("Name",'nickname'),'adoption_story',)
若要将相关字段拉入组合,项可以改为单个条目字典,将属性映射到遵循相同格式的嵌套结构:
search_fields=('year',("Name",'nickname'),'adoption_story',{'make':('name',)},{'model':('name',)},{'owners':('username','first_name','last_name',)},)
此语法减少了潜在的重复查询语言,例如"owners庘u username"
、"owners庘u first庘u name"
、以及"owners庘u last庘u name"
。
任何在搜索配置中不提供自己详细名称的相关字段都将显示在其前面,并显示相关模型的详细名称
。换言之,为了防止搜索用户界面显示车主的"名字"字段,就好像它是汽车的名字一样,用户界面将在该字段的名称前面加上用户的详细名称。在本例中,
名字
将显示为"用户名"。
为了防止自动前缀,您可以提供自己的详细名称,如前所示:
search_fields=(# ...{'owners':(("Username",'username'),# would have been "User username"("User's First name","first_name"),# would have been "User first name"("User's Last name","last_name"),# would have been "User last name")},)
相关字段可以嵌套:
search_fields=(# ...{'owners':('username',# displayed as "User username"{'groups':('name',# displayed as "Group name")},)},)
另一种指定相关字段的方法是使用相关模型类本身作为字典键。使用此方法,将通过检查两个模型之间的关系自动检索字段名:
search_fields=(# ...{User:(# validated to the string "owner", as in the previous example'username',# displayed as "User username"{'groups':('name',# displayed as "Group name")},)})
最终,此语法将成为访问泛型外键的受支持方法,尽管此类关系尚未实现。
注意:由ageneric relation字段引用的通用模型(例如,包含一个名为"comments"的genericrelation字段的car对象到一个generic comment模型)。红色有效,由AppSearch框架摘要:
search_fields=(# ...{'comments':(# Car.comments as a GenericRelation field to Comment model'title','content',)},)
显示字段
默认情况下,appsearch显示的结果表将包含模型上的所有本地字段。要显式声明字段列表,您的配置可以包含另一个属性display_fields
,其格式类似于search_fields
:
classCarSearch(ModelSearch):display_fields=('nickname','year',("Make",'make__name'),("Model",'model__name'),("Owners",'get_owners_list'),# attribute on the Car model)search_fields=(# ...)
display_fields
是一个iterable项,可以是字符串,也可以是(verbosename,fieldname)的2元组。与search_fields
一样,除非在配置中显式提供,否则将自动检索字段的详细名称
。
字段不一定是数据库字段;在上面的示例中,我们在表头中放置了一个"owners"列,该字段实际上是一个方法名。这很方便,但请注意不要在appsearch的控制范围之外生成太多查询!
此列表中的第一个项将转换为链接,并用一段简单的html代码片段包装该值:<;a href="{object.get_absolute_url}">;{{value}}<;/a>;
AppSearch将检查显示字段
以了解如何最好地发出对搜索结果queryset的调用,这有助于降低自动查询计数。
appsearch.autodiscover()
与内置管理一样,AppSearch可以对应用程序进行爬网,以在每个应用程序中发现search.py
模块。autodiscover()
只会导入这些配置并使其执行,因此如果使用自定义或多个注册表,此函数将允许这些注册表自行设置。
与管理员一样,一个很好的调用autodiscover()
的地方是在您的url模块中,或者是在项目的根目录中,或者是在一个本地"搜索"应用程序中,您无论如何都要在其中设置视图。请参阅下一节中的示例。
主视图
您需要声明自己的起点,以便客户最初访问并配置搜索。
basesearchview
是一个简单的templateview
子类,它也继承自appsearch.views.searchmixin
。对于完全普通的行为,可以直接包含basesearchview
:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()0
记住,因为basesearchview
几乎只是一个templateview
,所以需要给它一个template\u name
值。不过,不要担心,因为视图继承了使搜索表单变得简单的机制,以便呈现到自定义模板中。
另外,您当然可以去实际子类化basesearchview并获得额外的灵活性:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()1
搜索.html
你可以自由地制作你想要的任何模板来进行搜索。默认情况下,您只需将search
上下文变量呈现到模板中。只需确保jquery和appsearch插件已加载:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()2
有很多方法可以自定义表单的呈现方式和javascript的行为方式,但这足以获得一个功能齐全的搜索实现。
就这样!
挂载ajaxurl,运行中的basesearchview实例,注册模型配置,模板转储生成的表单,就完成了。
API
- 模型搜索
- 搜索注册表
模型搜索
appsearch.registry.modelsearch
用于为搜索发现注册模型的基本配置类。
详细名称
如果提供,则使用此modelsearch实例注册的模型将采用此详细名称,隐藏模型自己的详细名称< < > >
默认值:注册模型的详细名称
详细名称的复数形式
如果提供,则使用此ModelSearch实例注册的模型将采用此复数详细名称,隐藏模型自己的"详细名称"选项。
默认值:配置的多个"verbose"名称(如果可用),或者模型类的多个"verbose"名称(如果可用)。
显示字段
列描述项的Iterable。
每个"项目"可以是一个字符串:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()3
或显式提供详细名称的2元组:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()4
在这两种情况下,字段名都可以引用本地字段(包括方法名)或查询集样式的查找路径。在后一种情况下,应提供显式的详细名称:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()5
将自动检测任何跨模型查找,并发出相应的。select_related()
语句。
默认值:所有本地字段
搜索字段
一组字段描述项。
每个"item"都可以是一个描述本地数据库字段的字符串:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()3
或显式提供详细名称的2元组:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()4
或者一个单项目字典,将一个相关访问器映射到一个新的相关字段描述项的iterable,遵循相同的格式规则:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()8
搜索表单用户界面将遵循搜索字段
的声明顺序。
对于字典项中的相关字段,详细名称的前缀将是字段模型的详细名称
:
# car/models.pyclassCar(models.Model):year=models.PositiveIntegerField()make=models.ForeignKey(CarMake)model=models.ForeignKey(CarModel)owners=models.ManyToManyField(User)nickname=models.CharField(max_length=50)adoption_story=models.TextField()9
如果字段已显式声明详细名称,则不会添加前缀:
# car/search.pyfromappsearch.registryimportModelSearch,searchfromproject.car.modelsimportCarclassCarSearch(ModelSearch):search_fields=('year','nickname','adoption_story',)search.register(Car,CarSearch)0
获取查询集(用户)
返回在此模型上搜索将用于应用生成的查询的基queryset。默认情况下,模型的默认管理器用于返回未筛选的queryset。使用此钩子的适当方法是使用不同的管理器,或基于权限机制限制queryset。
用户
是发出请求的用户。
获取对象数据(obj)
给定搜索结果对象obj
,返回前端表的数据字段列表。列表的长度应与显示列的数目相匹配。
默认实现将自动读取配置的显示字段中指定的属性并生成此列表。如果一个值是可调用的,则调用该值时将不带参数,并使用返回值代替它,从而允许
显示字段
指定实例属性和方法,以及具体的数据库支持字段。
在对每个结果对象调用此方法之前,默认搜索机制所做的工作将尝试在源QuerySet上调用select_related()
,但请注意不要为每个对象生成过多的查询。如果需要选择其他相关字段以避免高查询计数,则可以提供自己的子类searcher
和:
- 重写
searcher.build_queryset()
方法,调用super()并对返回值执行额外的select_related()
调用。 - 直接覆盖并添加到列表中。
搜索注册表
appsearch.registry.searchregistry
存储配置以便在搜索表单中使用的注册表容器。
默认注册表在名为search
的模块变量中可用。
\uu iter\uuu()
生成注册表项,它们是"applabel.modelname"
格式的字符串
获取项目(k)
< ><代码>k是一个模型类,注册密钥在其位置生成("applabel.modelname"
)。否则,k
直接用于在注册表中查找模型配置。\u包含(k)
如果k
是模型类,则会在其位置生成注册密钥("applabel.modelname"
)。否则,k
直接用于测试注册表中的成员身份。
寄存器(型号、配置)
使用给定的配置注册模型类模型
。
获取配置(型号)
返回与模型相关联的配置实例
获取配置([用户[,权限]])
按顺序返回配置。
如果指定了user
,则只有当用户对关联的模型类具有内置的"applabel.change\u modelname"
权限时,才会包括配置。
如果还提供了权限
,则它应该是一个字符串,具有applabel和modelname的两个字符串格式位置,例如"{}.add{}"
或{}.manage{}
设置排序功能(f)
f
应该是接受参数配置并按所需顺序返回配置的函数。默认的排序函数根据其
详细名称
属性排列配置。
搜索者
appsearch.utils.searcher
对象包装呈现搜索用户界面和执行搜索本身所需的所有数据。当前实例将发送到表单模板上下文,默认情况下名称为"search"
searcher
类可以由生成主搜索页的basesearchview
的实例指定。
表单模板名称
默认值:"appsearch/default_form.html"
通常,构建searcher
实例的视图将提供自己的模板名称,但如果该视图的值显式设置为none
,或者searcher
正在自定义构建,则将使用该值。
搜索表单模板名称
默认值:"appsearch/search_form.html"
与表单模板名称
相同
结果列表模板名
默认值:"appsearch/results\list.html"
与表单模板名称
相同
\uu unicode\uu()
在self.form\u template\u name中呈现模板名称
此默认模板自动调用render_search_form()
和render_results_list()
,使其成为生成AppSearch UI的最简单方法。
呈现搜索表单()
在self.search\u form\u template\u name中呈现模板名称
这将生成表单的HTML,不包括结果列表。
呈现结果列表()
在self.results\u list\u template\u name中呈现模板名称
这将为结果列表生成html,不包括表单。如果在当前请求期间未执行搜索,则此结果为空。
型号选择表
appsearch.forms.modelselectionform的一个实例
约束格式集
appsearch.forms.constraintformset的一个实例,包含appsearch.forms.constraintformset实例。
字段数据URL
一旦在model\u selection\u form
上进行了选择,appsearch javascript应使用该url来获取给定模型的可搜索字段列表。这个url是在构建时通过反转默认url名称"appsearch:constraint fields"
(可选地包括在构建时指定的前缀)来派生的,由构建搜索者的视图根据basesearchview.get_searcher_kwargs()
返回的关键字参数发送进来
操作员数据URL
与field_data_url一样,appsearch javascript应该使用该url来获取在ui上选择的模型和字段组合的有效运算符列表。
就绪
用于确定是否可以执行搜索的只读标志。ready
仅当模型选择窗体和约束窗体集都通过normalis_valid()
检查时才为true。
型号
只有在选中了ready
并且model_selection_form
之后,才能确定其所选模型。搜索将操作的模型类。
型号配置
仅在选中了ready
之后才可用,例如模型
。与所选模型类关联的配置modelsearch
实例。
结果
在ready
之后可用的结果数据字典是真的,视图因此生成了最终的搜索查询并执行了它。结果
字典在模板中专门用于呈现包含列标题和行数据的ui表。
结果[计数]
结果查询集的长度。
结果['list']
数据行的iterable列表。每个"行"由ui表的列数据列表表示。结果列表由modelsearch.get_object_data()
的返回值组成
结果['字段]
表示由模型的modelsearch.display\fields
列表指定的字段的详细名称列表。
结果["自然字符串"]
使用约束表单集选项生成的字符串,用前缀字符串"where"生成,并用逗号连接每个约束表单。结果是一个字符串,格式为:
# car/search.pyfromappsearch.registryimportModelSearch,searchfromproject.car.modelsimportCarclassCarSearch(ModelSearch):search_fields=('year','nickname','adoption_story',)search.register(Car,CarSearch)
1
生成查询集(model,query[,queryset=none])
当表单有效且将执行搜索时,此方法将query
对象(django.db.models.query.q
实例的组合)应用于model
类。此方法还注意选择必要的相关字段,模型配置将通过modelsearch.display_fields
这可以作为searcher对象对查询进行最终修改的钩子,而不管模型类是什么。大多数queryset修改应该在每个modelsearch.get_queryset()
方法中进行,因为每个模型都可以在更清晰的上下文中控制其基本queryset。
只有在选中了ready
并且model_selection_form
之后,才能确定其所选模型。搜索将操作的模型类。
型号配置
仅在选中了ready
之后才可用,例如模型
。与所选模型类关联的配置modelsearch
实例。
结果
在ready
之后可用的结果数据字典是真的,视图因此生成了最终的搜索查询并执行了它。结果
字典在模板中专门用于呈现包含列标题和行数据的ui表。
结果[计数]
结果查询集的长度。
结果['list']
数据行的iterable列表。每个"行"由ui表的列数据列表表示。结果列表由modelsearch.get_object_data()
的返回值组成
结果['字段]
表示由模型的modelsearch.display\fields
列表指定的字段的详细名称列表。
结果["自然字符串"]
使用约束表单集选项生成的字符串,用前缀字符串"where"生成,并用逗号连接每个约束表单。结果是一个字符串,格式为:
# car/search.pyfromappsearch.registryimportModelSearch,searchfromproject.car.modelsimportCarclassCarSearch(ModelSearch):search_fields=('year','nickname','adoption_story',)search.register(Car,CarSearch)
1
生成查询集(model,query[,queryset=none])
当表单有效且将执行搜索时,此方法将query
对象(django.db.models.query.q
实例的组合)应用于model
类。此方法还注意选择必要的相关字段,模型配置将通过modelsearch.display_fields
仅在选中了ready
之后才可用,例如模型
。与所选模型类关联的配置modelsearch
实例。
结果
在ready
之后可用的结果数据字典是真的,视图因此生成了最终的搜索查询并执行了它。结果
字典在模板中专门用于呈现包含列标题和行数据的ui表。
结果[计数]
结果查询集的长度。
结果['list']
数据行的iterable列表。每个"行"由ui表的列数据列表表示。结果列表由modelsearch.get_object_data()
的返回值组成
结果['字段]
表示由模型的modelsearch.display\fields
列表指定的字段的详细名称列表。
结果["自然字符串"]
使用约束表单集选项生成的字符串,用前缀字符串"where"生成,并用逗号连接每个约束表单。结果是一个字符串,格式为:
# car/search.pyfromappsearch.registryimportModelSearch,searchfromproject.car.modelsimportCarclassCarSearch(ModelSearch):search_fields=('year','nickname','adoption_story',)search.register(Car,CarSearch)1
生成查询集(model,query[,queryset=none])
当表单有效且将执行搜索时,此方法将query
对象(django.db.models.query.q
这可以作为searcher对象对查询进行最终修改的钩子,而不管模型类是什么。大多数queryset修改应该在每个modelsearch.get_queryset()
默认情况下,AppSearch中的机器不会直接将QuerySet
参数传递给此方法,但是如果将Searcher
子类化并重写此方法,则可以调用super()
将此默认实现发送一个基QuerySet来代替模型的默认管理器查询集。当所有可搜索模型都使用公共查询接口(如共享项目级对象管理器或权限系统)时,这是适当的。
此方法的返回值是由query
筛选的模型queryset生成的queryset。
获取选择相关字段(型号、配置)
返回将发送到对模型的queryset的最终调用的queryset名称列表 机械构建一个 默认值: 默认值: 默认值: 负责搜索用户界面中初始模型下拉列表的窗体。默认表单提供对注册表的自动验证,提供ContentType ID模糊处理,并定义两种方法来检索已验证实例的选定模型类和关联的 要提供修改过的表单,请确保它是 默认值: 此窗体类的一个实例表示Constraint Builder UI中的一行,由描述约束的字段组成:核心和/或、要检查的字段、运算符和描述约束的一个或多个术语。 默认情况下, 将清除约束表单的所有字段并返回数据库就绪值。例如,字段 默认值: 用作 返回 返回 返回 默认值: 此默认模板包括位于 默认值: 呈现搜索表单,不包括搜索结果。 默认值: 呈现结果列表,不包括搜索表单。如果当前请求未执行任何搜索,则模板的输出为空。 返回 返回 返回 返回self.searcher类
返回要传递给搜索器构造函数的关键字参数字典。默认Kwargs是视图指定的模板名称。 使用 返回 通过 如果搜索者实例报告它是完全有效的,则在此方法期间将执行搜索。 继承自select_related()
。默认列表是通过检查config
的显示字段生成的。
searchmixin
appsearch.views.searchmixin
搜索器
实例并将其插入到模板上下文中。
搜索器类
搜索者
上下文对象名称
"搜索"
搜索器
实例的名称将在模板上下文中给定。型号选择窗体类
appsearch.forms.modelselectionform
modelsearch
配置。modelselectionform的子类
或提供相同的api方法get_selected_model()
和get_selected_model_configuration()
约束形式类
appsearch.forms.constraintform
字段
和运算符
字段有一个空的选项列表,因为这些选项取决于模型选择表单中的有效选择。前端javascript查询核心appsearch ajax视图,从注册表中查找适当的选项。因此,表单的字段清理方法将验证有效的选择。type
,该字段描述约束是and还是or操作,并分别清除为运算符和
运算符或
运算符。相应地,将
运算符
字段清除为实际的queryset语言路径,例如"related\u lookup\u path"
约束格式集类
appsearch.forms.constraintformset
formset_factory()
创建的基础的formset类。默认表单重写内部方法,以确保将模型选择表单的相应配置发送到中约束表单的构造函数。它不包含其他逻辑或重写。获取模型选择窗体类()
self.model\u selection\u form\u类
get_constraint_form_class()
self.constraint\u form\u类
get_constraint_formset_class()
self.constraint\u formset类
表单模板名称
"appsearch/default_form.html"
search\u form\u template\u name
和results\u template\u name
的默认模板的内容。
搜索表单模板名称
"appsearch/search_form.html"
结果列表模板名
"appsearch/results\list.html"
获取表单模板名()
self.form_template_name
获取搜索表单模板名()
self.search_form_template_name
获取结果列表模板
self.results\u list\u模板名
获取搜索器类
获取搜索程序kwargs()
获取搜索器()
get_searcher_class()
提供的类和get_searcher_kwargs()
提供的关键字参数返回一个实例化的搜索器获取上下文对象名()
self.context\u对象名
获取上下文数据(**kwargs)
get context\u object\u name()提供的名称将
searcher
实例添加到上下文中
basesearchview
appsearch.views.basesearchview
searchmixin
和内置的templateview
生成过程:
git tag<;version>;-m"release";git push——标记
捆绳上传距离/*
推荐PyPI第三方库