Skip to content

Commit 9468b41

Browse files
SharePoint API: Improved support for fields (create tax field, create field from schema)
1 parent cfe036e commit 9468b41

File tree

15 files changed

+273
-12
lines changed

15 files changed

+273
-12
lines changed

examples/sharepoint/lists_and_items/read_large_list.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from office365.runtime.auth.client_credential import ClientCredential
44
from office365.sharepoint.client_context import ClientContext
5-
from office365.sharepoint.file_system_object_type import FileSystemObjectType
5+
from office365.sharepoint.files.file_system_object_type import FileSystemObjectType
66

77

88
def print_progress(items_read):

office365/runtime/client_object_collection.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66

77
class ClientObjectCollection(ClientObject):
88

9-
def __init__(self, context, item_type, resource_path=None):
9+
def __init__(self, context, child_item_type, resource_path=None):
1010
"""Client object collection
1111
1212
:type context: office365.runtime.client_runtime_context.ClientRuntimeContext
13-
:type item_type: type[ClientObject]
13+
:type child_item_type: type[ClientObject]
1414
:type resource_path: office365.runtime.resource_path.ResourcePath
1515
"""
1616
super(ClientObjectCollection, self).__init__(context, resource_path)
1717
self._data = []
18-
self._item_type = item_type
18+
self._item_type = child_item_type
1919
self.page_loaded = EventHandler(False)
2020
self._default_page_size = 100
2121
self._paged_mode = True

office365/sharepoint/base_entity.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ class BaseEntity(ClientObject):
66

77
def __init__(self, context, resource_path=None, namespace="SP", parent_collection=None):
88
"""
9-
SharePoint base entity
9+
SharePoint entity
1010
1111
:param office365.sharepoint.client_context.ClientContext context: SharePoint context
12-
:param ResourcePath resource_path:
13-
:param str namespace:
12+
:param ResourcePath resource_path: Resource Path
13+
:param str namespace: default namespace
1414
"""
1515
super().__init__(context, resource_path, None, parent_collection)
1616
self._namespace = namespace
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from office365.runtime.client_object_collection import ClientObjectCollection
2+
3+
4+
class BaseEntityCollection(ClientObjectCollection):
5+
"""Represents a collection of View resources."""
6+
7+
def __init__(self, context, child_item_type=None, resource_path=None, parent=None):
8+
"""
9+
SharePoint entity set
10+
11+
:param office365.sharepoint.client_context.ClientContext context: SharePoint context
12+
:type child_item_type: type[ClientObject]
13+
:type resource_path: office365.runtime.resource_path.ResourcePath
14+
:type parent: office365.sharepoint.base_entity.BaseEntity or None
15+
"""
16+
super(BaseEntityCollection, self).__init__(context, child_item_type, resource_path)
17+
self._parent = parent

office365/sharepoint/eventreceivers/__init__.py

Whitespace-only changes.

office365/sharepoint/fields/field_collection.py

Lines changed: 179 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
from office365.runtime.client_object_collection import ClientObjectCollection
1+
import uuid
2+
23
from office365.runtime.queries.create_entity_query import CreateEntityQuery
4+
from office365.runtime.queries.service_operation_query import ServiceOperationQuery
35
from office365.runtime.resource_path_service_operation import ResourcePathServiceOperation
6+
from office365.sharepoint.base_entity_collection import BaseEntityCollection
47
from office365.sharepoint.fields.field import Field
8+
from office365.sharepoint.fields.xmlSchemaFieldCreationInformation import XmlSchemaFieldCreationInformation
59

610

7-
class FieldCollection(ClientObjectCollection):
11+
class FieldCollection(BaseEntityCollection):
812
"""Represents a collection of Field resource."""
913

10-
def __init__(self, context, resource_path=None):
11-
super(FieldCollection, self).__init__(context, Field, resource_path)
14+
def __init__(self, context, resource_path=None, parent=None):
15+
super(FieldCollection, self).__init__(context, Field, resource_path, parent)
1216

1317
def create_typed_object(self, properties):
1418
field = super(FieldCollection, self).create_typed_object(properties)
@@ -25,6 +29,177 @@ def add(self, field_create_information):
2529
self.context.add_query(qry)
2630
return field
2731

32+
def create_taxonomy_field(self, name, ssp_id, term_set_id, anchor_id="00000000-0000-0000-0000-000000000000",
33+
field_id=None, text_field_id=None, web_id=None, list_id=None):
34+
35+
target_field = Field(self.context)
36+
field_params = {
37+
"name": name,
38+
"ssp_id": ssp_id,
39+
"term_set_id": term_set_id,
40+
"anchor_id": anchor_id,
41+
"field_id": field_id,
42+
"text_field_id": text_field_id,
43+
"list_id": list_id,
44+
"web_id": web_id,
45+
"target_field": target_field
46+
}
47+
48+
if field_id is None:
49+
field_params["field_id"] = str(uuid.uuid1())
50+
51+
from office365.sharepoint.lists.list import List
52+
if isinstance(self._parent, List):
53+
parent_list = self._parent
54+
55+
def _list_loaded():
56+
field_params["web_id"] = parent_list.parentWeb.properties["Id"]
57+
field_params["list_id"] = parent_list.properties["Id"]
58+
self._create_taxonomy_field_query(**field_params)
59+
self._parent.ensure_properties(["Id", "ParentWeb"], _list_loaded)
60+
else:
61+
def _web_loaded():
62+
field_params["web_id"] = self.context.web.properties["Id"]
63+
self._create_taxonomy_field_query(**field_params)
64+
self.context.web.ensure_property("Id", _web_loaded)
65+
return target_field
66+
67+
def _create_taxonomy_field_query(self, name, ssp_id, term_set_id, anchor_id,
68+
field_id=None, text_field_id=None, web_id=None, list_id=None,
69+
target_field=None):
70+
"""
71+
72+
:param str text_field_id: Text Field Id
73+
:param str web_id: Web Id
74+
:param str list_id: List Id
75+
:param str field_id: Field Id
76+
:type name: str
77+
:type ssp_id: str
78+
:type term_set_id: str
79+
:type anchor_id: str
80+
:type target_field: Field
81+
"""
82+
83+
list_attr = f'List="{{{list_id}}}"' if list_id is not None else ""
84+
85+
schema_xml = f'''
86+
<Field Type="TaxonomyFieldType" DisplayName="{name}" {list_attr}
87+
WebId="{web_id}" Required="FALSE" EnforceUniqueValues="FALSE"
88+
ID="{{{field_id}}}" StaticName="{name}" Name="{name}">
89+
<Default/>
90+
<Customization>
91+
<ArrayOfProperty>
92+
<Property>
93+
<Name>SspId</Name>
94+
<Value xmlns:q1="http://www.w3.org/2001/XMLSchema" p4:type="q1:string"
95+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{ssp_id}
96+
</Value>
97+
</Property>
98+
<Property>
99+
<Name>GroupId</Name>
100+
</Property>
101+
<Property>
102+
<Name>TermSetId</Name>
103+
<Value xmlns:q2="http://www.w3.org/2001/XMLSchema" p4:type="q2:string"
104+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{term_set_id}
105+
</Value>
106+
</Property>
107+
<Property>
108+
<Name>AnchorId</Name>
109+
<Value xmlns:q3="http://www.w3.org/2001/XMLSchema" p4:type="q3:string"
110+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{anchor_id}
111+
</Value>
112+
</Property>
113+
<Property>
114+
<Name>UserCreated</Name>
115+
<Value xmlns:q4="http://www.w3.org/2001/XMLSchema" p4:type="q4:boolean"
116+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">false
117+
</Value>
118+
</Property>
119+
<Property>
120+
<Name>Open</Name>
121+
<Value xmlns:q5="http://www.w3.org/2001/XMLSchema" p4:type="q5:boolean"
122+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">true
123+
</Value>
124+
</Property>
125+
<Property>
126+
<Name>TextField</Name>
127+
<Value xmlns:q6="http://www.w3.org/2001/XMLSchema" p4:type="q6:string"
128+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">{{{text_field_id}}}
129+
</Value>
130+
</Property>
131+
<Property>
132+
<Name>IsPathRendered</Name>
133+
<Value xmlns:q7="http://www.w3.org/2001/XMLSchema" p4:type="q7:boolean"
134+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">false
135+
</Value>
136+
</Property>
137+
<Property>
138+
<Name>IsKeyword</Name>
139+
<Value xmlns:q8="http://www.w3.org/2001/XMLSchema" p4:type="q8:boolean"
140+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">false
141+
</Value>
142+
</Property>
143+
<Property>
144+
<Name>TargetTemplate</Name>
145+
</Property>
146+
<Property>
147+
<Name>CreateValuesInEditForm</Name>
148+
<Value xmlns:q9="http://www.w3.org/2001/XMLSchema" p4:type="q9:boolean"
149+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">false
150+
</Value>
151+
</Property>
152+
<Property>
153+
<Name>FilterAssemblyStrongName</Name>
154+
<Value xmlns:q10="http://www.w3.org/2001/XMLSchema" p4:type="q10:string"
155+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">Microsoft.SharePoint.Taxonomy,
156+
Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c
157+
</Value>
158+
</Property>
159+
<Property>
160+
<Name>FilterClassName</Name>
161+
<Value xmlns:q11="http://www.w3.org/2001/XMLSchema" p4:type="q11:string"
162+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">Microsoft.SharePoint.Taxonomy.TaxonomyField
163+
</Value>
164+
</Property>
165+
<Property>
166+
<Name>FilterMethodName</Name>
167+
<Value xmlns:q12="http://www.w3.org/2001/XMLSchema" p4:type="q12:string"
168+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">GetFilteringHtml
169+
</Value>
170+
</Property>
171+
<Property>
172+
<Name>FilterJavascriptProperty</Name>
173+
<Value xmlns:q13="http://www.w3.org/2001/XMLSchema" p4:type="q13:string"
174+
xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">FilteringJavascript
175+
</Value>
176+
</Property>
177+
</ArrayOfProperty>
178+
</Customization>
179+
</Field>
180+
'''
181+
182+
field_schema = XmlSchemaFieldCreationInformation(schema_xml)
183+
self._create_field_as_xml_query(field_schema, target_field)
184+
185+
def create_field_as_xml(self, schema_xml):
186+
"""
187+
:type schema_xml: str
188+
"""
189+
field = Field(self.context)
190+
field_schema = XmlSchemaFieldCreationInformation(schema_xml)
191+
self._create_field_as_xml_query(field_schema, field)
192+
return field
193+
194+
def _create_field_as_xml_query(self, schema_xml, field):
195+
"""
196+
:type field: Field
197+
:type schema_xml: XmlSchemaFieldCreationInformation
198+
"""
199+
self.add_child(field)
200+
qry = ServiceOperationQuery(self, "CreateFieldAsXml", None, schema_xml, "parameters", field)
201+
self.context.add_query(qry)
202+
28203
def get_by_id(self, _id):
29204
"""Gets the fields with the specified ID."""
30205
return Field(self.context, ResourcePathServiceOperation("getById", [_id], self.resource_path))
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from office365.runtime.client_value import ClientValue
2+
3+
4+
class XmlSchemaFieldCreationInformation(ClientValue):
5+
6+
def __init__(self, schemaXml, options=None):
7+
"""
8+
:type schemaXml: str
9+
:type options: int or None
10+
"""
11+
super().__init__("SP")
12+
self.SchemaXml = schemaXml
13+
self.Options = options

office365/sharepoint/lists/list.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def fields(self):
197197
if self.is_property_available('Fields'):
198198
return self.properties['Fields']
199199
else:
200-
return FieldCollection(self.context, ResourcePath("Fields", self.resource_path))
200+
return FieldCollection(self.context, ResourcePath("Fields", self.resource_path), self)
201201

202202
@property
203203
def views(self):
@@ -231,6 +231,13 @@ def forms(self):
231231
return self.properties.get('Forms',
232232
FormCollection(self.context, ResourcePath("forms", self.resource_path)))
233233

234+
@property
235+
def parentWeb(self):
236+
"""Gets a value that specifies the web where list resides."""
237+
from office365.sharepoint.webs.web import Web
238+
return self.properties.get('ParentWeb',
239+
Web(self.context, ResourcePath("parentWeb", self.resource_path)))
240+
234241
@property
235242
def item_count(self):
236243
"""Gets a value that specifies the number of list items in the list.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from office365.sharepoint.fields.field_lookup import FieldLookup
2+
3+
4+
class TaxonomyField(FieldLookup):
5+
pass

0 commit comments

Comments
 (0)