source: products/quintagroup.referencedatagridfield/trunk/quintagroup/referencedatagridfield/_field.py @ 2287

Last change on this file since 2287 was 2287, checked in by mylan, 14 years ago

Apply BlockColumn? for the Link column, add hidden-field stylesheet to the ReferenceDataGridFieldWidget?

  • Property svn:eol-style set to native
File size: 6.0 KB
Line 
1#from Products.Archetypes import atapi
2import re
3import logging
4import urlparse
5from urllib import quote
6from types import ListType, TupleType
7
8from AccessControl import ClassSecurityInfo
9
10from Products.CMFCore.utils import getToolByName
11from Products.validation import validation #validators import baseValidators
12from Products.Archetypes.Field import encode, ReferenceField
13from Products.Archetypes.Registry import registerField, registerWidget
14
15from Products.ATReferenceBrowserWidget.ATReferenceBrowserWidget import ReferenceBrowserWidget
16
17from Products.DataGridField.Column import Column
18from Products.DataGridField.DataGridField import DataGridField
19from Products.DataGridField.DataGridWidget import DataGridWidget
20
21from quintagroup.referencedatagridfield.columns import BlockColumn
22from quintagroup.referencedatagridfield.columns import HiddenColumn
23
24# Logger object
25#logger = logging.getLogger('ReferenceDataGridField')
26#logger.debug("ReferenceDataGrid loading")
27
28class ReferenceDataGridWidget(DataGridWidget, ReferenceBrowserWidget):
29    _properties = ReferenceBrowserWidget._properties.copy()
30    _properties.update(DataGridWidget._properties.copy())
31    _properties.update({
32        'macro': "referencedatagridwidget",
33        'helper_css': ('datagridwidget.css','referencedatagridwidget.css'),
34        'helper_js': ('referencebrowser.js', 'datagridwidget.js',),
35        'force_close_on_insert': True,
36        'columns': {
37            'title': Column("Title"), 
38            'link': BlockColumn("Link", column_on_class="hidden-field",
39                                columns=['link','uid'], read_only=True),
40            'uid': HiddenColumn("UID", visible=False)},
41        })
42
43isURL = validation.validatorFor('isURL')
44
45class ReferenceDataGridField(DataGridField, ReferenceField):
46    _properties = ReferenceField._properties.copy()
47    _properties.update(DataGridField._properties.copy())
48    _properties.update({
49        'columns': ('title', 'link', 'uid'),
50        'widget': ReferenceDataGridWidget,
51        'multiValued' : True,
52        })
53
54    security = ClassSecurityInfo()
55
56    security.declarePrivate('isRemoteURL')
57    def isRemoteURL(self, url):
58        return isURL(url) == 1 and True or False
59
60    security.declarePrivate('set')
61    def set(self, instance, value, **kwargs):
62        """
63        The passed in object should be a records object, or a sequence of dictionaries
64        About link data:
65          * interpretations:
66            * if data not starts with standard protocol names (http://, ftp://) than
67              *uid* field data will be used as reference
68          * record removed if:
69            * no data;
70            * data contains UID of not existent object
71        About title:
72          * if there is UID of existent object and record has same title to the original
73            object - title will not be saved.
74        """
75        catalog = getToolByName(instance, "uid_catalog")
76
77        if value is None:
78            value = ()
79
80        if not isinstance(value, (ListType, TupleType)):
81            value = value,
82
83        result = []
84        for row in value:
85            data = {"title":"", "link":"", "uid":""}
86
87            uid = str(row.get("uid", "")).strip()
88            link = str(row.get("link", "")).strip()
89            title = str(row.get('title', "")).strip()
90
91            if not title == "":
92                data["title"] = title
93
94            if link == "":
95                continue
96            elif self.isRemoteURL(link):
97                data["link"] = urlparse.urlunparse(urlparse.urlparse(link))
98            else:
99                if uid == '':
100                    continue
101
102                brains = catalog(UID=uid)
103                if len(brains) == 0:
104                    continue
105                # Found objects with pointed UID
106                brain = brains[0]
107                data["uid"] = uid
108                # Fix title for uid
109                if data['title'] == getattr(brain, "Title", ""):
110                    data['title'] = ""
111            result.append(data)
112
113        DataGridField.set(self, instance, result, **kwargs)
114
115        uids = [r['uid'] for r in result if r['uid']!=""]
116        ReferenceField.set(self, instance, uids, **kwargs)
117       
118    security.declarePrivate('get')
119    def get(self, instance, **kwargs):
120        """ Return DataGridField value
121
122        Value is a list object of rows.
123        Row id dictionary object with standard 'link', 'uid' and 'title' keys
124        plus extra informal *url* and *url_title* keys
125        """
126        purl = getToolByName(instance, "portal_url")
127        # use portal_catalog to hide protected object for the logged in user.
128        catalog = getToolByName(instance, "portal_catalog")
129
130        result = []
131        uids = {}
132        rows = DataGridField.get(self, instance, **kwargs)
133        for row in rows:
134            result.append({
135                # DataGridField row data
136                "uid": row["uid"],
137                "link": row["link"],
138                "title": row["title"],
139                # View data
140                "url": ""})
141            data = result[-1]
142            # Process remote URL and collect UIDs
143            if row["link"]:
144                data["url"] = quote(row["link"], safe='?$#@/:=+;$,&%')
145                # if title not set for remote url - set it equals to url
146                if not data["title"]:
147                    data["title"] = row["link"]
148            else:
149                uids[row["uid"]] = data
150        # Process UIDs
151        if uids:
152            brains = catalog(UID=uids.keys())
153            for b in brains:
154                data = uids[b.UID]
155                data["url"] = b.getURL()
156                data["link"] = b.getPath()
157                # If title not set - get it from the brain
158                if not data["title"]:
159                    data["title"] = self._brains_title_or_id(b, instance)
160
161        return result
162
163
164registerWidget(
165    ReferenceDataGridWidget,
166    title='DataGrid Reference',
167    used_for=('quintagroup.referencedatagridfield.ReferenceDataGridField',)
168    )
169
170registerField(
171    ReferenceDataGridField,
172    title="DataGrid Reference Field",
173    description=("Reference DataGrid field.")
174    )
Note: See TracBrowser for help on using the repository browser.