Code

Ticket #11005: query.patch

File query.patch, 4.6 KB (added by dennis@…, 5 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])