~ubuntu-branches/ubuntu/saucy/python-django/saucy-updates

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
"""
These classes are light wrappers around Django's database API that provide
convenience functionality and permalink functions for the databrowse app.
"""
from __future__ import unicode_literals

from django.db import models
from django.utils import formats
from django.utils.text import capfirst
from django.utils.encoding import smart_text, force_str, iri_to_uri
from django.db.models.query import QuerySet
from django.utils.encoding import python_2_unicode_compatible

EMPTY_VALUE = '(None)'
DISPLAY_SIZE = 100

class EasyModel(object):
    def __init__(self, site, model):
        self.site = site
        self.model = model
        self.model_list = list(site.registry.keys())
        self.verbose_name = model._meta.verbose_name
        self.verbose_name_plural = model._meta.verbose_name_plural

    def __repr__(self):
        return force_str('<EasyModel for %s>' % self.model._meta.object_name)

    def model_databrowse(self):
        "Returns the ModelDatabrowse class for this model."
        return self.site.registry[self.model]

    def url(self):
        return '%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name)

    def objects(self, **kwargs):
        return self.get_query_set().filter(**kwargs)

    def get_query_set(self):
        easy_qs = self.model._default_manager.get_query_set()._clone(klass=EasyQuerySet)
        easy_qs._easymodel = self
        return easy_qs

    def object_by_pk(self, pk):
        return EasyInstance(self, self.model._default_manager.get(pk=pk))

    def sample_objects(self):
        for obj in self.model._default_manager.all()[:3]:
            yield EasyInstance(self, obj)

    def field(self, name):
        try:
            f = self.model._meta.get_field(name)
        except models.FieldDoesNotExist:
            return None
        return EasyField(self, f)

    def fields(self):
        return [EasyField(self, f) for f in (self.model._meta.fields + self.model._meta.many_to_many)]

class EasyField(object):
    def __init__(self, easy_model, field):
        self.model, self.field = easy_model, field

    def __repr__(self):
        return force_str('<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))

    def choices(self):
        for value, label in self.field.choices:
            yield EasyChoice(self.model, self, value, label)

    def url(self):
        if self.field.choices:
            return '%s%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name)
        elif self.field.rel:
            return '%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name)

class EasyChoice(object):
    def __init__(self, easy_model, field, value, label):
        self.model, self.field = easy_model, field
        self.value, self.label = value, label

    def __repr__(self):
        return force_str('<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))

    def url(self):
        return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, iri_to_uri(self.value))

@python_2_unicode_compatible
class EasyInstance(object):
    def __init__(self, easy_model, instance):
        self.model, self.instance = easy_model, instance

    def __repr__(self):
        return force_str('<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val()))

    def __str__(self):
        val = smart_text(self.instance)
        if len(val) > DISPLAY_SIZE:
            return val[:DISPLAY_SIZE] + '...'
        return val

    def pk(self):
        return self.instance._get_pk_val()

    def url(self):
        return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk()))

    def fields(self):
        """
        Generator that yields EasyInstanceFields for each field in this
        EasyInstance's model.
        """
        for f in self.model.model._meta.fields + self.model.model._meta.many_to_many:
            yield EasyInstanceField(self.model, self, f)

    def related_objects(self):
        """
        Generator that yields dictionaries of all models that have this
        EasyInstance's model as a ForeignKey or ManyToManyField, along with
        lists of related objects.
        """
        for rel_object in self.model.model._meta.get_all_related_objects() + self.model.model._meta.get_all_related_many_to_many_objects():
            if rel_object.model not in self.model.model_list:
                continue # Skip models that aren't in the model_list
            em = EasyModel(self.model.site, rel_object.model)
            yield {
                'model': em,
                'related_field': rel_object.field.verbose_name,
                'object_list': [EasyInstance(em, i) for i in getattr(self.instance, rel_object.get_accessor_name()).all()],
            }

class EasyInstanceField(object):
    def __init__(self, easy_model, instance, field):
        self.model, self.field, self.instance = easy_model, field, instance
        self.raw_value = getattr(instance.instance, field.name)

    def __repr__(self):
        return force_str('<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name))

    def values(self):
        """
        Returns a list of values for this field for this instance. It's a list
        so we can accomodate many-to-many fields.
        """
        # This import is deliberately inside the function because it causes
        # some settings to be imported, and we don't want to do that at the
        # module level.
        if self.field.rel:
            if isinstance(self.field.rel, models.ManyToOneRel):
                objs = getattr(self.instance.instance, self.field.name)
            elif isinstance(self.field.rel, models.ManyToManyRel): # ManyToManyRel
                return list(getattr(self.instance.instance, self.field.name).all())
        elif self.field.choices:
            objs = dict(self.field.choices).get(self.raw_value, EMPTY_VALUE)
        elif isinstance(self.field, models.DateField) or isinstance(self.field, models.TimeField):
            if self.raw_value:
                if isinstance(self.field, models.DateTimeField):
                    objs = capfirst(formats.date_format(self.raw_value, 'DATETIME_FORMAT'))
                elif isinstance(self.field, models.TimeField):
                    objs = capfirst(formats.time_format(self.raw_value, 'TIME_FORMAT'))
                else:
                    objs = capfirst(formats.date_format(self.raw_value, 'DATE_FORMAT'))
            else:
                objs = EMPTY_VALUE
        elif isinstance(self.field, models.BooleanField) or isinstance(self.field, models.NullBooleanField):
            objs = {True: 'Yes', False: 'No', None: 'Unknown'}[self.raw_value]
        else:
            objs = self.raw_value
        return [objs]

    def urls(self):
        "Returns a list of (value, URL) tuples."
        # First, check the urls() method for each plugin.
        plugin_urls = []
        for plugin_name, plugin in self.model.model_databrowse().plugins.items():
            urls = plugin.urls(plugin_name, self)
            if urls is not None:
                return zip(self.values(), urls)
        if self.field.rel:
            m = EasyModel(self.model.site, self.field.rel.to)
            if self.field.rel.to in self.model.model_list:
                lst = []
                for value in self.values():
                    if value is None:
                        continue
                    url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, iri_to_uri(value._get_pk_val()))
                    lst.append((smart_text(value), url))
            else:
                lst = [(value, None) for value in self.values()]
        elif self.field.choices:
            lst = []
            for value in self.values():
                url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, iri_to_uri(self.raw_value))
                lst.append((value, url))
        elif isinstance(self.field, models.URLField):
            val = list(self.values())[0]
            lst = [(val, iri_to_uri(val))]
        else:
            lst = [(list(self.values())[0], None)]
        return lst

class EasyQuerySet(QuerySet):
    """
    When creating (or cloning to) an `EasyQuerySet`, make sure to set the
    `_easymodel` variable to the related `EasyModel`.
    """
    def iterator(self, *args, **kwargs):
        for obj in super(EasyQuerySet, self).iterator(*args, **kwargs):
            yield EasyInstance(self._easymodel, obj)

    def _clone(self, *args, **kwargs):
        c = super(EasyQuerySet, self)._clone(*args, **kwargs)
        c._easymodel = self._easymodel
        return c