Statistics
| Branch: | Tag: | Revision:

root / snf-django-lib / snf_django / management / commands / __init__.py @ 72cbea06

History | View | Annotate | Download (13.6 kB)

1 99955a02 Christos Stavrakakis
# Copyright 2012-2014 GRNET S.A. All rights reserved.
2 7cfc0cef Christos Stavrakakis
#
3 7cfc0cef Christos Stavrakakis
# Redistribution and use in source and binary forms, with or
4 7cfc0cef Christos Stavrakakis
# without modification, are permitted provided that the following
5 7cfc0cef Christos Stavrakakis
# conditions are met:
6 7cfc0cef Christos Stavrakakis
#
7 7cfc0cef Christos Stavrakakis
#   1. Redistributions of source code must retain the above
8 7cfc0cef Christos Stavrakakis
#      copyright notice, this list of conditions and the following
9 7cfc0cef Christos Stavrakakis
#      disclaimer.
10 7cfc0cef Christos Stavrakakis
#
11 7cfc0cef Christos Stavrakakis
#   2. Redistributions in binary form must reproduce the above
12 7cfc0cef Christos Stavrakakis
#      copyright notice, this list of conditions and the following
13 7cfc0cef Christos Stavrakakis
#      disclaimer in the documentation and/or other materials
14 7cfc0cef Christos Stavrakakis
#      provided with the distribution.
15 7cfc0cef Christos Stavrakakis
#
16 7cfc0cef Christos Stavrakakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 7cfc0cef Christos Stavrakakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 7cfc0cef Christos Stavrakakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 7cfc0cef Christos Stavrakakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 7cfc0cef Christos Stavrakakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 7cfc0cef Christos Stavrakakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 7cfc0cef Christos Stavrakakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 7cfc0cef Christos Stavrakakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 7cfc0cef Christos Stavrakakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 7cfc0cef Christos Stavrakakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 7cfc0cef Christos Stavrakakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 7cfc0cef Christos Stavrakakis
# POSSIBILITY OF SUCH DAMAGE.
28 7cfc0cef Christos Stavrakakis
#
29 7cfc0cef Christos Stavrakakis
# The views and conclusions contained in the software and
30 7cfc0cef Christos Stavrakakis
# documentation are those of the authors and should not be
31 7cfc0cef Christos Stavrakakis
# interpreted as representing official policies, either expressed
32 7cfc0cef Christos Stavrakakis
# or implied, of GRNET S.A.
33 7cfc0cef Christos Stavrakakis
34 7cfc0cef Christos Stavrakakis
from optparse import make_option
35 1e285210 Giorgos Korfiatis
from django.core.management.base import (BaseCommand,
36 99955a02 Christos Stavrakakis
                                         handle_default_options)
37 1e285210 Giorgos Korfiatis
from django.core.management.base import CommandError as DjangoCommandError
38 7cfc0cef Christos Stavrakakis
from django.core.exceptions import FieldError
39 7cfc0cef Christos Stavrakakis
40 7cfc0cef Christos Stavrakakis
from snf_django.management import utils
41 7cfc0cef Christos Stavrakakis
from snf_django.lib.astakos import UserCache
42 7cfc0cef Christos Stavrakakis
43 c406d7d9 Dionysis Grigoropoulos
import distutils
44 c406d7d9 Dionysis Grigoropoulos
45 4845dfaa Christos Stavrakakis
USER_EMAIL_FIELD = "user.email"
46 4845dfaa Christos Stavrakakis
47 7cfc0cef Christos Stavrakakis
48 1e285210 Giorgos Korfiatis
class CommandError(DjangoCommandError):
49 1e285210 Giorgos Korfiatis
    def __str__(self):
50 72cbea06 Christos Stavrakakis
        return utils.smart_locale_str(self.message, errors='replace')
51 1e285210 Giorgos Korfiatis
52 1e285210 Giorgos Korfiatis
53 7cfc0cef Christos Stavrakakis
class SynnefoCommand(BaseCommand):
54 7cfc0cef Christos Stavrakakis
    option_list = BaseCommand.option_list + (
55 7cfc0cef Christos Stavrakakis
        make_option(
56 7cfc0cef Christos Stavrakakis
            "--output-format",
57 7cfc0cef Christos Stavrakakis
            dest="output_format",
58 7cfc0cef Christos Stavrakakis
            metavar="[pretty, csv, json]",
59 7cfc0cef Christos Stavrakakis
            default="pretty",
60 7cfc0cef Christos Stavrakakis
            choices=["pretty", "csv", "json"],
61 85ddc6a3 Christos Stavrakakis
            help="Select the output format: pretty [the default], json, "
62 85ddc6a3 Christos Stavrakakis
                 "csv [comma-separated output]"),
63 7cfc0cef Christos Stavrakakis
    )
64 7cfc0cef Christos Stavrakakis
65 99955a02 Christos Stavrakakis
    def run_from_argv(self, argv):
66 99955a02 Christos Stavrakakis
        """Override BaseCommand.run_from_argv to decode arguments and options
67 99955a02 Christos Stavrakakis

68 99955a02 Christos Stavrakakis
        Convert command line arguments and options to unicode objects using
69 99955a02 Christos Stavrakakis
        user's preferred encoding.
70 99955a02 Christos Stavrakakis

71 99955a02 Christos Stavrakakis
        """
72 857f8a2f Christos Stavrakakis
        argv = [utils.smart_locale_unicode(a) for a in argv]
73 99955a02 Christos Stavrakakis
        parser = self.create_parser(argv[0], argv[1])
74 99955a02 Christos Stavrakakis
        options, args = parser.parse_args(argv[2:])
75 99955a02 Christos Stavrakakis
        handle_default_options(options)
76 99955a02 Christos Stavrakakis
        self.execute(*args, **options.__dict__)
77 99955a02 Christos Stavrakakis
78 7cfc0cef Christos Stavrakakis
79 85ddc6a3 Christos Stavrakakis
class ListCommand(SynnefoCommand):
80 7cfc0cef Christos Stavrakakis
    """Generic *-list management command.
81 7cfc0cef Christos Stavrakakis

82 7cfc0cef Christos Stavrakakis
    Management command to handle common tasks when implementing a -list
83 7cfc0cef Christos Stavrakakis
    management command. This class handles the following tasks:
84 7cfc0cef Christos Stavrakakis

85 7cfc0cef Christos Stavrakakis
    * Retrieving objects from database.
86 7cfc0cef Christos Stavrakakis

87 7cfc0cef Christos Stavrakakis
    The DB model class is declared in ``object_class`` class attribute. Also,
88 7cfc0cef Christos Stavrakakis
    results can be filter using either the ``filters`` and ``excludes``
89 7cfc0cef Christos Stavrakakis
    attribute or the "--filter-by" option.
90 7cfc0cef Christos Stavrakakis

91 7cfc0cef Christos Stavrakakis
    * Display specific fields of the database objects.
92 7cfc0cef Christos Stavrakakis

93 7cfc0cef Christos Stavrakakis
    List of available fields is defined in the ``FIELDS`` class attribute,
94 7cfc0cef Christos Stavrakakis
    which is a dictionary mapping from field names to tuples containing the
95 7cfc0cef Christos Stavrakakis
    way the field is retrieved and a text help message to display. The first
96 7cfc0cef Christos Stavrakakis
    field of the tuple is either a string containing a chain of attribute
97 7cfc0cef Christos Stavrakakis
    accesses (e.g. "machine.flavor.cpu") either a callable function, taking
98 7cfc0cef Christos Stavrakakis
    as argument the DB object and returning a single value.
99 7cfc0cef Christos Stavrakakis

100 7cfc0cef Christos Stavrakakis
    The fields that will be displayed be default is contained in the ``fields``
101 7cfc0cef Christos Stavrakakis
    class attribute. The user can specify different fields using the "--fields"
102 7cfc0cef Christos Stavrakakis
    option.
103 7cfc0cef Christos Stavrakakis

104 7cfc0cef Christos Stavrakakis
    * Handling of user UUIDs and names.
105 7cfc0cef Christos Stavrakakis

106 7cfc0cef Christos Stavrakakis
    If the ``user_uuid_field`` is declared, then "--user" and "--display-mails"
107 7cfc0cef Christos Stavrakakis
    options will become available. The first one allows filtering via either
108 7cfc0cef Christos Stavrakakis
    a user's UUID or display name. The "--displayname" option will append
109 7cfc0cef Christos Stavrakakis
    the displayname of ther user with "user_uuid_field" to the output.
110 7cfc0cef Christos Stavrakakis

111 7cfc0cef Christos Stavrakakis
    * Pretty printing output to a nice table.
112 7cfc0cef Christos Stavrakakis

113 7cfc0cef Christos Stavrakakis
    """
114 7cfc0cef Christos Stavrakakis
115 7cfc0cef Christos Stavrakakis
    # The following fields must be handled in the ListCommand subclasses!
116 7cfc0cef Christos Stavrakakis
117 7cfc0cef Christos Stavrakakis
    # The django DB model
118 7cfc0cef Christos Stavrakakis
    object_class = None
119 7cfc0cef Christos Stavrakakis
    # The name of the field containg the user ID of the user, if any.
120 7cfc0cef Christos Stavrakakis
    user_uuid_field = None
121 7cfc0cef Christos Stavrakakis
    # The name of the field containg the deleted flag, if any.
122 7cfc0cef Christos Stavrakakis
    deleted_field = None
123 7cfc0cef Christos Stavrakakis
    # Dictionary with all available fields
124 7cfc0cef Christos Stavrakakis
    FIELDS = {}
125 7cfc0cef Christos Stavrakakis
    # List of fields to display by default
126 7cfc0cef Christos Stavrakakis
    fields = []
127 7cfc0cef Christos Stavrakakis
    # Default filters and excludes
128 7cfc0cef Christos Stavrakakis
    filters = {}
129 7cfc0cef Christos Stavrakakis
    excludes = {}
130 7cfc0cef Christos Stavrakakis
    # Order results
131 7cfc0cef Christos Stavrakakis
    order_by = None
132 7cfc0cef Christos Stavrakakis
133 7cfc0cef Christos Stavrakakis
    # Fields used only with user_user_field
134 ef57e622 Ilias Tsitsimpis
    astakos_auth_url = None
135 7cfc0cef Christos Stavrakakis
    astakos_token = None
136 7cfc0cef Christos Stavrakakis
137 2052c40e Christos Stavrakakis
    # Optimize DB queries
138 2052c40e Christos Stavrakakis
    prefetch_related = []
139 2052c40e Christos Stavrakakis
    select_related = []
140 2052c40e Christos Stavrakakis
141 7cfc0cef Christos Stavrakakis
    help = "Generic List Command"
142 85ddc6a3 Christos Stavrakakis
    option_list = SynnefoCommand.option_list + (
143 7cfc0cef Christos Stavrakakis
        make_option(
144 7cfc0cef Christos Stavrakakis
            "-o", "--output",
145 7cfc0cef Christos Stavrakakis
            dest="fields",
146 7cfc0cef Christos Stavrakakis
            help="Comma-separated list of output fields"),
147 7cfc0cef Christos Stavrakakis
        make_option(
148 7cfc0cef Christos Stavrakakis
            "--list-fields",
149 7cfc0cef Christos Stavrakakis
            dest="list_fields",
150 7cfc0cef Christos Stavrakakis
            action="store_true",
151 7cfc0cef Christos Stavrakakis
            default=False,
152 7cfc0cef Christos Stavrakakis
            help="List available output fields"),
153 7cfc0cef Christos Stavrakakis
        make_option(
154 7cfc0cef Christos Stavrakakis
            "--filter-by",
155 7cfc0cef Christos Stavrakakis
            dest="filter_by",
156 7cfc0cef Christos Stavrakakis
            metavar="FILTERS",
157 7cfc0cef Christos Stavrakakis
            help="Filter results. Comma separated list of key `cond` val pairs"
158 7cfc0cef Christos Stavrakakis
                 " that displayed entries must satisfy. e.g."
159 7cfc0cef Christos Stavrakakis
                 " --filter-by \"deleted=False,id>=22\"."),
160 7cfc0cef Christos Stavrakakis
        make_option(
161 7cfc0cef Christos Stavrakakis
            "--list-filters",
162 7cfc0cef Christos Stavrakakis
            dest="list_filters",
163 7cfc0cef Christos Stavrakakis
            action="store_true",
164 7cfc0cef Christos Stavrakakis
            default=False,
165 7cfc0cef Christos Stavrakakis
            help="List available filters"),
166 7cfc0cef Christos Stavrakakis
        make_option(
167 7cfc0cef Christos Stavrakakis
            "--no-headers",
168 7cfc0cef Christos Stavrakakis
            dest="headers",
169 7cfc0cef Christos Stavrakakis
            action="store_false",
170 7cfc0cef Christos Stavrakakis
            default=True,
171 7cfc0cef Christos Stavrakakis
            help="Do not display headers"),
172 7cfc0cef Christos Stavrakakis
    )
173 7cfc0cef Christos Stavrakakis
174 7cfc0cef Christos Stavrakakis
    def __init__(self, *args, **kwargs):
175 7cfc0cef Christos Stavrakakis
        if self.user_uuid_field:
176 ef57e622 Ilias Tsitsimpis
            assert(self.astakos_auth_url), "astakos_auth_url attribute is "\
177 ef57e622 Ilias Tsitsimpis
                                           "needed when user_uuid_field "\
178 ef57e622 Ilias Tsitsimpis
                                           "is declared"
179 7cfc0cef Christos Stavrakakis
            assert(self.astakos_token), "astakos_token attribute is needed"\
180 7cfc0cef Christos Stavrakakis
                                        " when user_uuid_field is declared"
181 7cfc0cef Christos Stavrakakis
            self.option_list += (
182 7cfc0cef Christos Stavrakakis
                make_option(
183 7cfc0cef Christos Stavrakakis
                    "-u", "--user",
184 7cfc0cef Christos Stavrakakis
                    dest="user",
185 7cfc0cef Christos Stavrakakis
                    metavar="USER",
186 7cfc0cef Christos Stavrakakis
                    help="List items only for this user."
187 7cfc0cef Christos Stavrakakis
                         " 'USER' can be either a user UUID or a display"
188 7cfc0cef Christos Stavrakakis
                         " name"),
189 7cfc0cef Christos Stavrakakis
                make_option(
190 7cfc0cef Christos Stavrakakis
                    "--display-mails",
191 7cfc0cef Christos Stavrakakis
                    dest="display_mails",
192 7cfc0cef Christos Stavrakakis
                    action="store_true",
193 7cfc0cef Christos Stavrakakis
                    default=False,
194 7cfc0cef Christos Stavrakakis
                    help="Include the user's email"),
195 7cfc0cef Christos Stavrakakis
            )
196 7cfc0cef Christos Stavrakakis
197 7cfc0cef Christos Stavrakakis
        if self.deleted_field:
198 7cfc0cef Christos Stavrakakis
            self.option_list += (
199 7cfc0cef Christos Stavrakakis
                make_option(
200 7cfc0cef Christos Stavrakakis
                    "-d", "--deleted",
201 7cfc0cef Christos Stavrakakis
                    dest="deleted",
202 7cfc0cef Christos Stavrakakis
                    action="store_true",
203 7cfc0cef Christos Stavrakakis
                    help="Display only deleted items"),
204 7cfc0cef Christos Stavrakakis
            )
205 7cfc0cef Christos Stavrakakis
        super(ListCommand, self).__init__(*args, **kwargs)
206 7cfc0cef Christos Stavrakakis
207 7cfc0cef Christos Stavrakakis
    def handle(self, *args, **options):
208 7cfc0cef Christos Stavrakakis
        if len(args) > 0:
209 7cfc0cef Christos Stavrakakis
            raise CommandError("List commands do not accept any argument")
210 7cfc0cef Christos Stavrakakis
211 7cfc0cef Christos Stavrakakis
        assert(self.object_class), "object_class variable must be declared"
212 7cfc0cef Christos Stavrakakis
213 4845dfaa Christos Stavrakakis
        # If an user field is declared, include the USER_EMAIL_FIELD in the
214 4845dfaa Christos Stavrakakis
        # available fields
215 4845dfaa Christos Stavrakakis
        if self.user_uuid_field is not None:
216 4845dfaa Christos Stavrakakis
            self.FIELDS[USER_EMAIL_FIELD] =\
217 4845dfaa Christos Stavrakakis
                ("_user_email", "The email of the owner")
218 4845dfaa Christos Stavrakakis
219 7cfc0cef Christos Stavrakakis
        if options["list_fields"]:
220 7cfc0cef Christos Stavrakakis
            self.display_fields()
221 7cfc0cef Christos Stavrakakis
            return
222 7cfc0cef Christos Stavrakakis
223 7cfc0cef Christos Stavrakakis
        if options["list_filters"]:
224 7cfc0cef Christos Stavrakakis
            self.display_filters()
225 7cfc0cef Christos Stavrakakis
            return
226 7cfc0cef Christos Stavrakakis
227 7cfc0cef Christos Stavrakakis
        # --output option
228 7cfc0cef Christos Stavrakakis
        if options["fields"]:
229 7cfc0cef Christos Stavrakakis
            fields = options["fields"]
230 7cfc0cef Christos Stavrakakis
            fields = fields.split(",")
231 7cfc0cef Christos Stavrakakis
            self.validate_fields(fields)
232 7cfc0cef Christos Stavrakakis
            self.fields = options["fields"].split(",")
233 7cfc0cef Christos Stavrakakis
234 4845dfaa Christos Stavrakakis
        # --display-mails option
235 4845dfaa Christos Stavrakakis
        if options.get("display_mails"):
236 4845dfaa Christos Stavrakakis
            self.fields.append(USER_EMAIL_FIELD)
237 4845dfaa Christos Stavrakakis
238 7cfc0cef Christos Stavrakakis
        # --filter-by option
239 7cfc0cef Christos Stavrakakis
        if options["filter_by"]:
240 48233747 Christos Stavrakakis
            filters, excludes = \
241 48233747 Christos Stavrakakis
                utils.parse_queryset_filters(options["filter_by"])
242 7cfc0cef Christos Stavrakakis
        else:
243 7cfc0cef Christos Stavrakakis
            filters, excludes = ({}, {})
244 7cfc0cef Christos Stavrakakis
245 7cfc0cef Christos Stavrakakis
        self.filters.update(filters)
246 7cfc0cef Christos Stavrakakis
        self.excludes.update(excludes)
247 7cfc0cef Christos Stavrakakis
248 7cfc0cef Christos Stavrakakis
        # --user option
249 7cfc0cef Christos Stavrakakis
        user = options.get("user")
250 7cfc0cef Christos Stavrakakis
        if user:
251 7cfc0cef Christos Stavrakakis
            if "@" in user:
252 ef57e622 Ilias Tsitsimpis
                ucache = UserCache(self.astakos_auth_url, self.astakos_token)
253 7cfc0cef Christos Stavrakakis
                user = ucache.get_uuid(user)
254 7cfc0cef Christos Stavrakakis
            self.filters[self.user_uuid_field] = user
255 7cfc0cef Christos Stavrakakis
256 7cfc0cef Christos Stavrakakis
        # --deleted option
257 7cfc0cef Christos Stavrakakis
        if self.deleted_field:
258 7cfc0cef Christos Stavrakakis
            deleted = options.get("deleted")
259 7cfc0cef Christos Stavrakakis
            if deleted:
260 7cfc0cef Christos Stavrakakis
                self.filters[self.deleted_field] = True
261 7cfc0cef Christos Stavrakakis
            else:
262 7cfc0cef Christos Stavrakakis
                self.filters[self.deleted_field] = False
263 7cfc0cef Christos Stavrakakis
264 7cfc0cef Christos Stavrakakis
        # Special handling of arguments
265 7cfc0cef Christos Stavrakakis
        self.handle_args(self, *args, **options)
266 7cfc0cef Christos Stavrakakis
267 3b6afb38 Christos Stavrakakis
        select_related = getattr(self, "select_related", [])
268 3b6afb38 Christos Stavrakakis
        prefetch_related = getattr(self, "prefetch_related", [])
269 3b6afb38 Christos Stavrakakis
270 7cfc0cef Christos Stavrakakis
        objects = self.object_class.objects
271 7cfc0cef Christos Stavrakakis
        try:
272 787f7372 Giorgos Korfiatis
            if select_related:
273 787f7372 Giorgos Korfiatis
                objects = objects.select_related(*select_related)
274 787f7372 Giorgos Korfiatis
            if prefetch_related:
275 787f7372 Giorgos Korfiatis
                objects = objects.prefetch_related(*prefetch_related)
276 7cfc0cef Christos Stavrakakis
            objects = objects.filter(**self.filters)
277 c8922d01 Giorgos Korfiatis
            for key, value in self.excludes.iteritems():
278 51e5aa11 Christos Stavrakakis
                objects = objects.exclude(**{key: value})
279 7cfc0cef Christos Stavrakakis
        except FieldError as e:
280 7cfc0cef Christos Stavrakakis
            raise CommandError(e)
281 7cfc0cef Christos Stavrakakis
        except Exception as e:
282 7cfc0cef Christos Stavrakakis
            raise CommandError("Can not filter results: %s" % e)
283 7cfc0cef Christos Stavrakakis
284 7cfc0cef Christos Stavrakakis
        order_key = self.order_by if self.order_by is not None else 'pk'
285 7cfc0cef Christos Stavrakakis
        objects = objects.order_by(order_key)
286 7cfc0cef Christos Stavrakakis
287 4845dfaa Christos Stavrakakis
        if USER_EMAIL_FIELD in self.fields:
288 4845dfaa Christos Stavrakakis
            if '_user_email' in self.object_class._meta.get_all_field_names():
289 7cfc0cef Christos Stavrakakis
                raise RuntimeError("%s has already a 'user_mail' attribute")
290 7cfc0cef Christos Stavrakakis
            uuids = [getattr(obj, self.user_uuid_field) for obj in objects]
291 ef57e622 Ilias Tsitsimpis
            ucache = UserCache(self.astakos_auth_url, self.astakos_token)
292 7cfc0cef Christos Stavrakakis
            ucache.fetch_names(list(set(uuids)))
293 7cfc0cef Christos Stavrakakis
            for obj in objects:
294 7cfc0cef Christos Stavrakakis
                uuid = getattr(obj, self.user_uuid_field)
295 4845dfaa Christos Stavrakakis
                obj._user_email = ucache.get_name(uuid)
296 7cfc0cef Christos Stavrakakis
297 7cfc0cef Christos Stavrakakis
        # Special handling of DB results
298 7cfc0cef Christos Stavrakakis
        objects = list(objects)
299 7cfc0cef Christos Stavrakakis
        self.handle_db_objects(objects, **options)
300 7cfc0cef Christos Stavrakakis
301 7cfc0cef Christos Stavrakakis
        headers = self.fields
302 7cfc0cef Christos Stavrakakis
        columns = [self.FIELDS[key][0] for key in headers]
303 7cfc0cef Christos Stavrakakis
304 7cfc0cef Christos Stavrakakis
        table = []
305 7cfc0cef Christos Stavrakakis
        for obj in objects:
306 7cfc0cef Christos Stavrakakis
            row = []
307 7cfc0cef Christos Stavrakakis
            for attr in columns:
308 7cfc0cef Christos Stavrakakis
                if callable(attr):
309 7cfc0cef Christos Stavrakakis
                    row.append(attr(obj))
310 7cfc0cef Christos Stavrakakis
                else:
311 7cfc0cef Christos Stavrakakis
                    item = obj
312 7cfc0cef Christos Stavrakakis
                    attrs = attr.split(".")
313 7cfc0cef Christos Stavrakakis
                    for attr in attrs:
314 7cfc0cef Christos Stavrakakis
                        item = getattr(item, attr)
315 7cfc0cef Christos Stavrakakis
                    row.append(item)
316 7cfc0cef Christos Stavrakakis
            table.append(row)
317 7cfc0cef Christos Stavrakakis
318 7cfc0cef Christos Stavrakakis
        # Special handle of output
319 7cfc0cef Christos Stavrakakis
        self.handle_output(table, headers)
320 7cfc0cef Christos Stavrakakis
321 7cfc0cef Christos Stavrakakis
        # Print output
322 7cfc0cef Christos Stavrakakis
        output_format = options["output_format"]
323 7cfc0cef Christos Stavrakakis
        if output_format != "json" and not options["headers"]:
324 7cfc0cef Christos Stavrakakis
            headers = None
325 7cfc0cef Christos Stavrakakis
        utils.pprint_table(self.stdout, table, headers, output_format)
326 7cfc0cef Christos Stavrakakis
327 7cfc0cef Christos Stavrakakis
    def handle_args(self, *args, **kwargs):
328 7cfc0cef Christos Stavrakakis
        pass
329 7cfc0cef Christos Stavrakakis
330 7cfc0cef Christos Stavrakakis
    def handle_db_objects(self, objects, **options):
331 7cfc0cef Christos Stavrakakis
        pass
332 7cfc0cef Christos Stavrakakis
333 7cfc0cef Christos Stavrakakis
    def handle_output(self, table, headers):
334 7cfc0cef Christos Stavrakakis
        pass
335 7cfc0cef Christos Stavrakakis
336 7cfc0cef Christos Stavrakakis
    def display_fields(self):
337 7cfc0cef Christos Stavrakakis
        headers = ["Field", "Description"]
338 7cfc0cef Christos Stavrakakis
        table = []
339 7cfc0cef Christos Stavrakakis
        for field, (_, help_msg) in self.FIELDS.items():
340 7cfc0cef Christos Stavrakakis
            table.append((field, help_msg))
341 7cfc0cef Christos Stavrakakis
        utils.pprint_table(self.stdout, table, headers)
342 7cfc0cef Christos Stavrakakis
343 7cfc0cef Christos Stavrakakis
    def validate_fields(self, fields):
344 7cfc0cef Christos Stavrakakis
        for f in fields:
345 7cfc0cef Christos Stavrakakis
            if f not in self.FIELDS.keys():
346 7cfc0cef Christos Stavrakakis
                raise CommandError("Unknown field '%s'. 'Use --list-fields"
347 7cfc0cef Christos Stavrakakis
                                   " option to find out available fields."
348 7cfc0cef Christos Stavrakakis
                                   % f)
349 7cfc0cef Christos Stavrakakis
350 7cfc0cef Christos Stavrakakis
    def display_filters(self):
351 7cfc0cef Christos Stavrakakis
        headers = ["Filter", "Description", "Help"]
352 7cfc0cef Christos Stavrakakis
        table = []
353 7cfc0cef Christos Stavrakakis
        for field in self.object_class._meta.fields:
354 7cfc0cef Christos Stavrakakis
            table.append((field.name, field.verbose_name, field.help_text))
355 7cfc0cef Christos Stavrakakis
        utils.pprint_table(self.stdout, table, headers)
356 c406d7d9 Dionysis Grigoropoulos
357 c406d7d9 Dionysis Grigoropoulos
358 c406d7d9 Dionysis Grigoropoulos
class RemoveCommand(BaseCommand):
359 c406d7d9 Dionysis Grigoropoulos
    help = "Generic remove command"
360 c406d7d9 Dionysis Grigoropoulos
    option_list = BaseCommand.option_list + (
361 c406d7d9 Dionysis Grigoropoulos
        make_option(
362 c406d7d9 Dionysis Grigoropoulos
            "-f", "--force",
363 c406d7d9 Dionysis Grigoropoulos
            dest="force",
364 c406d7d9 Dionysis Grigoropoulos
            action="store_true",
365 c406d7d9 Dionysis Grigoropoulos
            default=False,
366 c406d7d9 Dionysis Grigoropoulos
            help="Do not prompt for confirmation"),
367 c406d7d9 Dionysis Grigoropoulos
    )
368 c406d7d9 Dionysis Grigoropoulos
369 c406d7d9 Dionysis Grigoropoulos
    def confirm_deletion(self, force, resource='', args=''):
370 c406d7d9 Dionysis Grigoropoulos
        if force is True:
371 c406d7d9 Dionysis Grigoropoulos
            return True
372 c406d7d9 Dionysis Grigoropoulos
373 c406d7d9 Dionysis Grigoropoulos
        ids = ', '.join(args)
374 c406d7d9 Dionysis Grigoropoulos
        self.stdout.write("Are you sure you want to delete %s %s?"
375 0f89715b Dionysis Grigoropoulos
                          " [Y/N] " % (resource, ids))
376 c406d7d9 Dionysis Grigoropoulos
        try:
377 c406d7d9 Dionysis Grigoropoulos
            answer = distutils.util.strtobool(raw_input())
378 c406d7d9 Dionysis Grigoropoulos
            if answer != 1:
379 c406d7d9 Dionysis Grigoropoulos
                raise CommandError("Aborting deletion")
380 c406d7d9 Dionysis Grigoropoulos
        except ValueError:
381 d27b16cc Dionysis Grigoropoulos
            raise CommandError("Unaccepted input value. Please choose yes/no"
382 d27b16cc Dionysis Grigoropoulos
                               " (y/n).")