Statistics
| Branch: | Tag: | Revision:

root / snf-django-lib / snf_django / management / commands / __init__.py @ 4845dfaa

History | View | Annotate | Download (12.7 kB)

1 7cfc0cef Christos Stavrakakis
# Copyright 2012-2013 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 7cfc0cef Christos Stavrakakis
36 7cfc0cef Christos Stavrakakis
from django.core.management.base import BaseCommand, CommandError
37 7cfc0cef Christos Stavrakakis
from django.core.exceptions import FieldError
38 7cfc0cef Christos Stavrakakis
39 7cfc0cef Christos Stavrakakis
from snf_django.management import utils
40 7cfc0cef Christos Stavrakakis
from snf_django.lib.astakos import UserCache
41 7cfc0cef Christos Stavrakakis
42 c406d7d9 Dionysis Grigoropoulos
import distutils
43 c406d7d9 Dionysis Grigoropoulos
44 4845dfaa Christos Stavrakakis
USER_EMAIL_FIELD = "user.email"
45 4845dfaa Christos Stavrakakis
46 7cfc0cef Christos Stavrakakis
47 7cfc0cef Christos Stavrakakis
class SynnefoCommand(BaseCommand):
48 7cfc0cef Christos Stavrakakis
    option_list = BaseCommand.option_list + (
49 7cfc0cef Christos Stavrakakis
        make_option(
50 7cfc0cef Christos Stavrakakis
            "--output-format",
51 7cfc0cef Christos Stavrakakis
            dest="output_format",
52 7cfc0cef Christos Stavrakakis
            metavar="[pretty, csv, json]",
53 7cfc0cef Christos Stavrakakis
            default="pretty",
54 7cfc0cef Christos Stavrakakis
            choices=["pretty", "csv", "json"],
55 85ddc6a3 Christos Stavrakakis
            help="Select the output format: pretty [the default], json, "
56 85ddc6a3 Christos Stavrakakis
                 "csv [comma-separated output]"),
57 7cfc0cef Christos Stavrakakis
    )
58 7cfc0cef Christos Stavrakakis
59 7cfc0cef Christos Stavrakakis
60 85ddc6a3 Christos Stavrakakis
class ListCommand(SynnefoCommand):
61 7cfc0cef Christos Stavrakakis
    """Generic *-list management command.
62 7cfc0cef Christos Stavrakakis

63 7cfc0cef Christos Stavrakakis
    Management command to handle common tasks when implementing a -list
64 7cfc0cef Christos Stavrakakis
    management command. This class handles the following tasks:
65 7cfc0cef Christos Stavrakakis

66 7cfc0cef Christos Stavrakakis
    * Retrieving objects from database.
67 7cfc0cef Christos Stavrakakis

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

72 7cfc0cef Christos Stavrakakis
    * Display specific fields of the database objects.
73 7cfc0cef Christos Stavrakakis

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

81 7cfc0cef Christos Stavrakakis
    The fields that will be displayed be default is contained in the ``fields``
82 7cfc0cef Christos Stavrakakis
    class attribute. The user can specify different fields using the "--fields"
83 7cfc0cef Christos Stavrakakis
    option.
84 7cfc0cef Christos Stavrakakis

85 7cfc0cef Christos Stavrakakis
    * Handling of user UUIDs and names.
86 7cfc0cef Christos Stavrakakis

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

92 7cfc0cef Christos Stavrakakis
    * Pretty printing output to a nice table.
93 7cfc0cef Christos Stavrakakis

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