describe_form.py 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. # -*- coding: utf-8 -*-
  2. from django.apps import apps
  3. from django.core.management.base import CommandError, LabelCommand
  4. from django.utils.encoding import force_str
  5. from django_extensions.management.utils import signalcommand
  6. class Command(LabelCommand):
  7. help = "Outputs the specified model as a form definition to the shell."
  8. def add_arguments(self, parser):
  9. parser.add_argument('label', type=str,
  10. help='application name and model name')
  11. parser.add_argument(
  12. "--fields", "-f", action="append", dest="fields", default=[],
  13. help="Describe form with these fields only"
  14. )
  15. @signalcommand
  16. def handle(self, *args, **options):
  17. label = options['label']
  18. fields = options['fields']
  19. return describe_form(label, fields)
  20. def describe_form(label, fields):
  21. """ Return a string describing a form based on the model """
  22. try:
  23. app_name, model_name = label.split('.')[-2:]
  24. except (IndexError, ValueError):
  25. raise CommandError("Need application and model name in the form: appname.model")
  26. model = apps.get_model(app_name, model_name)
  27. opts = model._meta
  28. field_list = []
  29. for f in opts.fields + opts.many_to_many:
  30. if not f.editable:
  31. continue
  32. if fields and f.name not in fields:
  33. continue
  34. formfield = f.formfield()
  35. if '__dict__' not in dir(formfield):
  36. continue
  37. attrs = {}
  38. valid_fields = ['required', 'initial', 'max_length', 'min_length', 'max_value', 'min_value', 'max_digits', 'decimal_places', 'choices', 'help_text', 'label']
  39. for k, v in formfield.__dict__.items():
  40. if k in valid_fields and v is not None:
  41. # ignore defaults, to minimize verbosity
  42. if k == 'required' and v:
  43. continue
  44. if k == 'help_text' and not v:
  45. continue
  46. if k == 'widget':
  47. attrs[k] = v.__class__
  48. elif k in ['help_text', 'label']:
  49. attrs[k] = str(force_str(v).strip())
  50. else:
  51. attrs[k] = v
  52. params = ', '.join(['%s=%r' % (k, v) for k, v in sorted(attrs.items())])
  53. field_list.append(' %(field_name)s = forms.%(field_type)s(%(params)s)' % {
  54. 'field_name': f.name,
  55. 'field_type': formfield.__class__.__name__,
  56. 'params': params
  57. })
  58. return '''
  59. from django import forms
  60. from %(app_name)s.models import %(object_name)s
  61. class %(object_name)sForm(forms.Form):
  62. %(field_list)s
  63. ''' % {'app_name': app_name, 'object_name': opts.object_name, 'field_list': '\n'.join(field_list)}