allow dynamically adding object classes to types
[matthijs/upstream/django-ldapdb.git] / ldapdb / models / fields.py
1 # -*- coding: utf-8 -*-
2
3 # django-ldapdb
4 # Copyright (c) 2009-2011, BollorĂ© telecom
5 # All rights reserved.
6
7 # See AUTHORS file for a full list of contributors.
8
9 # Redistribution and use in source and binary forms, with or without modification,
10 # are permitted provided that the following conditions are met:
11
12 #     1. Redistributions of source code must retain the above copyright notice, 
13 #        this list of conditions and the following disclaimer.
14 #     
15 #     2. Redistributions in binary form must reproduce the above copyright 
16 #        notice, this list of conditions and the following disclaimer in the
17 #        documentation and/or other materials provided with the distribution.
18
19 #     3. Neither the name of BollorĂ© telecom nor the names of its contributors
20 #        may be used to endorse or promote products derived from this software
21 #        without specific prior written permission.
22
23 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
27 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #
34
35 from django.db.models import fields, SubfieldBase
36
37 from ldapdb import escape_ldap_filter
38
39 class CharField(fields.CharField):
40     def __init__(self, *args, **kwargs):
41         kwargs['max_length'] = 200
42         super(CharField, self).__init__(*args, **kwargs)
43
44     def from_ldap(self, value, connection):
45         if len(value) == 0:
46             return ''
47         else:
48             return value[0].decode(connection.charset)
49
50     def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
51         "Returns field's value prepared for database lookup."
52         if lookup_type == 'endswith':
53             return ["*%s" % escape_ldap_filter(value)]
54         elif lookup_type == 'startswith':
55             return ["%s*" % escape_ldap_filter(value)]
56         elif lookup_type in ['contains', 'icontains']:
57             return ["*%s*" % escape_ldap_filter(value)]
58         elif lookup_type == 'exact':
59             return [escape_ldap_filter(value)]
60         elif lookup_type == 'in':
61             return [escape_ldap_filter(v) for v in value]
62
63         raise TypeError("CharField has invalid lookup: %s" % lookup_type)
64
65     def get_db_prep_save(self, value, connection):
66         return [value.encode(connection.charset)]
67
68     def get_prep_lookup(self, lookup_type, value):
69         "Perform preliminary non-db specific lookup checks and conversions"
70         if lookup_type == 'endswith':
71             return "*%s" % escape_ldap_filter(value)
72         elif lookup_type == 'startswith':
73             return "%s*" % escape_ldap_filter(value)
74         elif lookup_type in ['contains', 'icontains']:
75             return "*%s*" % escape_ldap_filter(value)
76         elif lookup_type == 'exact':
77             return escape_ldap_filter(value)
78         elif lookup_type == 'in':
79             return [escape_ldap_filter(v) for v in value]
80
81         raise TypeError("CharField has invalid lookup: %s" % lookup_type)
82
83 class ImageField(fields.Field):
84     def from_ldap(self, value, connection):
85         if len(value) == 0:
86             return ''
87         else:
88             return value[0]
89
90     def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
91         "Returns field's value prepared for database lookup."
92         return [self.get_prep_lookup(lookup_type, value)]
93
94     def get_db_prep_save(self, value, connection):
95         return [value]
96
97     def get_prep_lookup(self, lookup_type, value):
98         "Perform preliminary non-db specific lookup checks and conversions"
99         raise TypeError("ImageField has invalid lookup: %s" % lookup_type)
100
101 class IntegerField(fields.IntegerField):
102     def from_ldap(self, value, connection):
103         if len(value) == 0:
104             return 0
105         else:
106             return int(value[0])
107         
108     def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
109         "Returns field's value prepared for database lookup."
110         return [self.get_prep_lookup(lookup_type, value)]
111
112     def get_db_prep_save(self, value, connection):
113         return [str(value)]
114
115     def get_prep_lookup(self, lookup_type, value):
116         "Perform preliminary non-db specific lookup checks and conversions"
117         if lookup_type in ('exact', 'gte', 'lte'):
118             return value
119         raise TypeError("IntegerField has invalid lookup: %s" % lookup_type)
120
121 class ListField(fields.Field):
122     __metaclass__ = SubfieldBase
123
124     def from_ldap(self, value, connection):
125         return value
126
127     def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
128         "Returns field's value prepared for database lookup."
129         return [self.get_prep_lookup(lookup_type, value)]
130
131     def get_db_prep_save(self, value, connection):
132         return [x.encode(connection.charset) for x in value]
133
134     def get_prep_lookup(self, lookup_type, value):
135         "Perform preliminary non-db specific lookup checks and conversions"
136         if lookup_type == 'contains':
137             return escape_ldap_filter(value)
138         raise TypeError("ListField has invalid lookup: %s" % lookup_type)
139
140     def to_python(self, value):
141         if not value:
142             return []
143         return value
144