Ticket #11005: query.patch

File query.patch, 4.6 KB (added by dennis@…, 6 years ago)

Patch that adds ./manage.py query

  • django/core/management/commands/query.py

     
     1from django.db.models import Q
     2from django.core.management import BaseCommand
     3from django.template import loader, Template, Context
     4from optparse import make_option
     5import os.path
     6import sys
     7
     8usage="""The django ORM will be queried with the filters on the commandline. Records
     9will be separated with newlines, fields with the specified separator
     10(the default is a comma). Alternatively, a template can be specified which
     11will be passed the result of the query as the 'objects' variable
     12
     13Query key/value pairs can be prefixed with a '!' to negate it, internally this uses
     14a Q object.
     15
     16Examples:
     17 - Display name and assettag of all mc01 servers
     18   %prog query name__startswith=mc01 -f name,assettag
     19 - Get a list of name, ip, mac for all servers where the does not contain .82.
     20   %prog query -m Interface !ip_address__contains='.82.' -f server.name,ip_address,mac_address
     21 - Use a template to get the roles, depending on mac address
     22   %prog query interface__mac_address=00:17:A4:8D:E6:BC -t '{{ objects.0.role_set.all|join:"," }}'
     23
     24/!\\ Warning /!\\
     25This script does not do much error checking. If you spell your query wrong, or
     26do something wrong with templates, you will get a python traceback and not a
     27nice error message."""
     28
     29class Command(BaseCommand):
     30    option_list = BaseCommand.option_list + (
     31        make_option('-a', '--application', dest="application",
     32                    default=os.environ.get("DJANGO_QUERY_DEFAULT_APPLICATION", None),
     33                    help="Use this application", metavar="APP"),
     34        make_option('-m', '--model', dest="model",
     35                    default=os.environ.get("DJANGO_QUERY_DEFAULT_MODEL", None),
     36                    help="Query this model"),
     37        make_option('-f', '--fields', dest="fields", default=None,
     38                    help="Give these fields"),
     39        make_option('-o', '--order', dest="order", default=None,
     40                    help="Order by this field"),
     41        make_option('-s', '--separator', dest="separator", default=",",
     42                    help="Output separator"),
     43        make_option('-t', '--template', dest="template", default='',
     44                    help="Template in django syntax"),
     45        make_option('-T', '--template-file', dest="template_file", default=None,
     46                    help="File containing the template (abs/rel path or loader path)")
     47    )
     48    help = usage
     49    args = 'filter [filter ...]'
     50
     51    def handle(self, *args, **options):
     52        if not options['application']:
     53            print "You must specify which application to use"
     54            sys.exit(1)
     55        if not options['model']:
     56            print "You must specify which model to use"
     57            sys.exit(1)
     58        if not options['fields'] and not options['template'] and not options['template_file']:
     59            print "You must specify a list of fields or a template"
     60            sys.exit(1)
     61
     62        # Import the model
     63        models = options['application'] + '.models'
     64        __import__(models)
     65        models = sys.modules[models]
     66        model = getattr(models, options['model'])
     67
     68        # Create queryset
     69        qargs = []
     70        for x in args:
     71            key, val = x.split('=',1)
     72            if key.startswith('!') or key.startswith('~'):
     73                qargs.append(~Q(**{key[1:]: val}))
     74            else:
     75                qargs.append(Q(**{key: val}))
     76        queryset = model.objects.filter(*qargs)
     77        if options['order']:
     78            queryset = queryset.order_by(options['order'])
     79
     80        # Generate output
     81        if options['template'] or options['template_file']:
     82            template = Template(options['template'])
     83            tf = options['template_file']
     84            if tf == '-':
     85                template = Template(sys.stdin.read())
     86            elif tf and os.path.exists(tf):
     87                template = Template(open(tf).read())
     88            elif tf:
     89                template = loader.get_template(tf)
     90            print template.render(Context({'objects': queryset}))
     91        else:
     92            def getattr_r(obj, attr):
     93                if '.' in attr:
     94                    me, next = attr.split('.',1)
     95                    return getattr_r(getattr(obj, me), next)
     96                return getattr(obj, attr)
     97            fields = options['fields'].split(',')
     98            for record in queryset:
     99                print options['separator'].join([unicode(getattr_r(record, x)) for x in fields])
Back to Top