Scaffolding: scaffold.py

File scaffold.py, 8.9 KB (added by javinievas@…, 18 years ago)

scaffold file

Line 
1#!/usr/bin/env python
2
3###################################################################################################
4# Scaffolding
5# Author: Javier Nievas (javinievas@gmail.com)
6# Date: 6th August 2006
7###################################################################################################
8# BASED ON...
9# Script based on the work of:
10# - Lllama
11# - Akaihola
12# - David Warry
13###################################################################################################
14# INTRODUCTION...
15# The original work lives in: http://code.djangoproject.com/wiki/ScaffoldScript
16# I have put together the generation of forms and manipulators in the same file
17###################################################################################################
18#
19# If you choose to use custom templates (-t custom) this script suppose you have three files:
20# templates/scaffold/form.html - the main template, it contains the form tag and a {{ formfields }}
21# templates/scaffold/pre_form.html - this file is prepended to generated template before the form
22# templates/scaffold/post_form.html - this file is appened to generated template after the form
23#
24# This script was tested under Windows XP, using Django 0.96-pre
25# You may have to change some code to match your own installation
26###################################################################################################
27
28from optparse import OptionParser
29import sys
30import os
31from django.shortcuts import render_to_response
32from django.template.loader import get_template
33from django.db.models import get_model
34from django.db import models
35from django.template import Context, Template
36
37
38
39def readfile(file):
40 f = open(file,"r")
41 pre = f.read()
42 f.close()
43
44 return pre
45
46
47def argValue(s, args):
48 if s == 'related_query_name':
49 return "???"
50 else:
51 return args[s]
52
53def field_text(field):
54 d = field.__dict__
55 args = dict([(f, isinstance(d[f], str) and "'%s'" % d[f] or d[f]) for f in d if f not in ['db_index', 'primary_key', 'rel', 'core', 'creation_counter',
56 'editable', 'name', 'default', 'column', 'attname', 'auto_now_add', 'help_text', 'auto_now', 'unique', 'verbose_name']])
57 if args['blank'] is True or args['null'] is True:
58 args['is_required'] = False
59 else:
60 args['is_required'] = True
61 try:
62 del(args['blank'])
63 del(args['null'])
64 except KeyError:
65 pass
66 try:
67 args['validator_list'] = ['%s' % v.__name__ for v in args['validator_list']]
68 except KeyError:
69 pass
70 if field.__class__.__name__ == 'CharField':
71 fieldType = 'TextField'
72 if field.__class__.__name__ == 'TextField':
73 fieldType = 'LargeTextField'
74 elif field.__class__.__name__ == 'ForeignKey':
75 fieldType = 'SelectField'
76 args['choices'] = "[('','-------')] + [(o.id, o) for o in %s.get_list()]" % (field.name.lower() + "s",)
77 elif field.__class__.__name__ == 'BooleanField':
78 fieldType = 'CheckboxField'
79 elif field.__class__.__name__ == 'DateTimeField':
80 fieldType = 'DatetimeField'
81 elif field.__class__.__name__ == 'ManyToManyField':
82 fieldType = 'SelectMultipleField'
83 args['choices'] = "[(o.id, o) for o in %s.get_list()]" % (field.name.lower() + "s",)
84 else:
85 fieldType = field.__class__.__name__
86
87 extra_args = ["%s=%s" % (s, argValue(s, args)) for s in args if args[s] not in [None, '', False, []]]
88 #print field.name, extra_args
89 if extra_args:
90 return '''\
91 forms.%s(field_name='%s', %s),''' % (fieldType, field.name, ', '.join(extra_args))
92 else:
93 return '''\
94 forms.%s(field_name='%s'),''' % (fieldType, field.name)
95
96def value_text(field):
97 return """\
98 %s=new_data['%s']""" % (field.name, field.name)
99
100def m2m_text(field):
101 return """ temp.set_%s(newdata['%s'])""" % (field.name, field.name)
102
103def image_field_html(name):
104 return '''\
105 {{ form.NAME_file }} \
106 {{ form.NAME }}
107 {% if form.NAME.errors %}
108 <div class='div_errors'>
109 {{ form.NAME.errors|join:", " }}
110 </div>
111 {% endif %}'''.replace('NAME', name)
112
113def field_html(name):
114 return '''\
115 {{ form.NAME }}
116 {% if form.NAME.errors %}
117 <div class='div_errors'>
118 {{ form.NAME.errors|join:", " }}
119 </div>
120 {% endif %}'''.replace('NAME', name)
121
122
123def labeled_field_html(field):
124 if isinstance(field, models.DateTimeField):
125 rows = [field_html(field.name + '_' + suffix)
126 for suffix in 'date', 'time']
127 elif isinstance(field, models.ImageField):
128 rows = [image_field_html(field.name)]
129 else:
130 rows = [field_html(field.name)]
131 return '''\
132 <li>
133 <label for="id_%s">%s:</label>
134%s
135 </li>''' % (field.name, field.verbose_name or field.name, '\n'.join(rows))
136
137def renderForm(appname, modelname):
138
139 modelobj = get_model(appname, modelname)
140
141 template = Template(
142"""<form method="POST" action=".">
143<fieldset>
144<legend>{{modelname}}</legend>
145<ul>
146{{ formfields }}
147</ul>
148</fieldset>
149<input type="submit" value="submit" />
150</form>
151""")
152
153 context = Context({'formfields': '\n'.join(labeled_field_html(f) for f in modelobj._meta.fields + modelobj._meta.many_to_many if f.name !='id'), 'modelname':modelname})
154
155 if (options.template == "custom"):
156 t=get_template('scaffold/form.html')
157 out = readfile("../apps/%s/templates/scaffold/pre_form.html" % appname )
158 out += t.render(context)
159 out += readfile("../apps/%s/templates/scaffold/post_form.html" % appname )
160 return out
161 else:
162 return template.render(context)
163
164def renderManipulator(appname, modelname, manipname):
165 modelobj = get_model(appname, modelname)
166
167 template = Template(
168"""class {{ name }}Manipulator(forms.Manipulator):
169 def __init__(self, pk=None):
170 if pk:
171 # change
172 self.original_object = {{model}}.objects.get(id=pk)
173 self.pk = pk
174 else:
175 # add
176 self.original_object = None
177 self.pk = None
178
179 self.fields = (
180{{ fields }}
181 )
182
183 def save(self, new_data):
184 if self.original_object:
185 # update
186 temp = dict(
187{{ values }}
188 )
189 for k,v in temp.iteritems():
190 self.original_object.__setattr__(k, v)
191 self.original_object.save()
192 return {{model}}.objects.get(id=pk)
193
194 else:
195 # insert
196 temp = {{ model }}(
197{{ values }}
198 )
199{{ m2m }}
200 temp.save()
201 return temp
202 """)
203
204 context = Context({'fields': '\n'.join([field_text(f) for f in modelobj._meta.fields + modelobj._meta.many_to_many if f.name !='id']),
205 'name': manipname,
206 'model': modelname,
207 'values': ',\n'.join([value_text(f) for f in modelobj._meta.fields if f.name != 'id']),
208 'm2m': '\n'.join([m2m_text(f) for f in modelobj._meta.many_to_many])})
209
210 if (options.template == "custom"):
211 t=get_template('scaffold/manipulator.py')
212 return t.render(context)
213 else:
214 return template.render(context)
215
216
217if __name__ == "__main__":
218
219 try:
220 import settings
221 except ImportError:
222 print "Settings file not found. Place this file in the same place as manage.py"
223 sys.exit()
224
225 project_directory = os.path.dirname(settings.__file__)
226 project_name = os.path.basename(project_directory)
227 sys.path.append(os.path.join(project_directory, '..'))
228 project_module = __import__(project_name, '', '', [''])
229 sys.path.pop()
230 os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
231
232 p = OptionParser()
233
234 #p.add_option("-p", "--project", dest="project", help="The project which contains the model")
235 p.add_option("-g","--generate", dest="generate", help="Choose between form or manipulator")
236 p.add_option("-a", "--app", dest="app", help="The app which contains the model")
237 p.add_option("-m", "--model", dest="model", help="The model to produce the form for")
238 p.add_option("-n", "--name", dest="name", help="The name of the custom manipulator")
239 p.add_option("-t", "--template", dest="template", help="Type custom to use your template/scaffold directory or leave blank for default template")
240
241 options, args = p.parse_args()
242
243 if not (options.generate and options.model and options.app):
244 p.print_help()
245 sys.exit()
246
247 if not options.name:
248 options.name = "%s%s" % (options.app, options.model)
249
250 m = __import__("%s.models" % (options.app,), '', '', [options.model])
251
252 a = getattr(m, options.model)
253
254 if options.generate == "form":
255 print renderForm(options.app, options.model)
256 elif options.generate == "manipulator":
257 print renderManipulator(options.app, options.model, options.name)
258
Back to Top