I'd love it if someone made an intelligent startapp call for manage.py. At the moment, it looks like Rails... but doesn't DO an awful lot.... This is my very crude attempt, which first calls startapp, then does standard stuff that ALWAYS seem to have to do and ALWAYS forget like: Add a urls.py for my app... Add a URL pattern to load static images Create the folder to host the static images Put some examples in the views calls and add standard imports Create all the classes in models.py that I think I'm gonna need (but not call syncdb yet) Add __str__ calls to all classes, and Admin classes (it's easier to delete them than to add them by hand later) Docstrings, one day I may comment my code. I deliberately don't want to do any kind of auto-build wizard, because that would end up with code that I couldn't hack, or simply get ridiculously complicated, this is a simple "this is the stuff I get bored, or forget to type every time I start a project". I also don't want this to tell me how I HAVE to do things, but it'd be nice to have some polite suggestions in how to organise my folders, classes, views etc... I think this idea is ok... or.. it works for me... I'd love it if someone could make it a bit fabber... I have made a teensy weensy video so you can laugh at my accent as I try to explain what I'd like startapp to do... my code is also made available for your amusement :-) regards tom |
startapp.py
Description: application/applefile
#!/usr/bin/env python """This is meant to show how I think startapp should be a bit more helpful with regard to us novice users, adding examples, adding common imports, adding stuff that can be added quicker from the command-line than when coding in python (perhaps)
The idea here is that, IF there is a "good" way to do things then let's adopt it but not force it on people. And that it's easier to delete stuff you don't need, than create it from scratch. This file is also meant to be deliberately non-clever, so that it's easy to hack from top to bottom, to work the way you work, rather than the way Ithink you should work... because to be honest I haven't a clue. If someone could make this work properly, I'd be very grateful tom, http://www.theotherblog.com """ import sys, os, traceback def do(cmd): f = os.popen(cmd) result = f.read() f.close() return result.strip() if __name__ == '__main__': app = sys.argv[1] #get enclosing folder name path_to_here = os.getcwd() project = os.getcwd().split("/")[-1] print "Starting app:", app cmd = "python manage.py startapp %s" % app print "doing: ", cmd, "..." os.system(cmd) #DO MODELS f = open("./" + app + "/models.py", 'w') #data = f.read() we could do a search and replace here... ############################ START MODELS.PY ############################ class_str = ''' # standard import urllib2, urllib, traceback, logging from string import * # django from django.conf import settings from django.db import models,connection, backend from django.core.exceptions import ObjectDoesNotExist # my imports # Create your models here. ''' #ASK ABOUT INDIVIDUAL CLASSES class_name = 'y' classes = [] # A list of classes we define along the way extras = ''' def __str__(self): return repr(self) class Admin: search_fields = [] list_display = ( ) list_filter = [] class Meta: ordering = () #################################################################### ''' while class_name != 'n': print "Would you like to add a class to your model? ClassName or n\r" class_name = raw_input() class_name.strip() if class_name == 'n' or '': print break classes.append(class_name) class_str += "\rclass %s(models.Model):\r" % class_name class_str += '\t""\r' #add attributes attr_name = 'y' while attr_name != 'n': print 'Add an attribute to class "%s"? attribute_name or n' % class_name attr_name = raw_input().strip() if attr_name == 'n' or '': class_str += extras print break print '...of type fk, char, text, int, datetime, url?' attr_type = raw_input().strip() if attr_type == 'fk': # ask which class from classes? class_str += "\t" + attr_name + " = models.ForeignKey(???)\r" elif attr_type == 'char': #ask how long? class_str += "\t" + attr_name + " = models.Charfield(maxlength=200, blank=True)\r" elif attr_type == 'text': class_str += "\t" + attr_name + " = models.TextField(default='', blank=True)\r" elif attr_type == 'int': #ask default? class_str += "\t" + attr_name + " = models.IntegerField(default=0)\r" elif attr_type == 'datetime': class_str += "\t" + attr_name + " = models.DateTimeField(auto_now_add=True, blank=True)\r" class_str += extras print "writing models.py....." f.write(class_str ) f.close() ############### END MODELS ############################ ############### START VIEWS ############################ f = open("./" + app + "/views.py", 'w') view_str = '''# django from django.template import Context, loader from django.shortcuts import * from django.contrib.sessions.models import Session from django.db import models, connection from django.core.paginator import ObjectPaginator, InvalidPage from django.conf import settings from django.conf.urls.defaults import * from django.http import HttpResponseRedirect, HttpResponse, Http404 from '''+ app + '''.models import * # standard import sys, pickle, traceback from string import * from random import randint from pprint import pprint from pydoc import help from time import sleep def add_defaults(request, the_dict): #do any default adding here... hacky I know... return the_dict def hello_world(request): return HttpResponse("Hello World") def stylesheet(request): #might want to add a few variables for colours, fonts etc here. t = loader.get_template('stylesheet.css') c = Context( add_defaults(request, {} ) ) css = t.render( c ) response = HttpResponse(css, mimetype="text/css" ) return response def example(request, template='default.html'): #This is just here as a reminder... needs exceptions etc... paginate_by = 100 page = int(request.GET.get('page',0)) p = MyClass.objects.filter(title__icontains="example") paginator = ObjectPaginator(p, paginate_by) paged_object_list = paginator.get_page(page) return render_to_response(template, {'objects':paged_object_list , 'is_paginated': paginator.pages > 1, 'results_per_page': paginate_by, 'has_next': paginator.has_next_page(page), 'has_previous':has_previous, "last_page": paginator.pages - 1, 'page': page + 1, 'next': page + 1, 'previous': page - 1, 'pages': paginator.pages, 'hits' :paginator.hits,} ) ''' ############### END VIEWS ############################ print "adding defaults to views.py...." f.write(view_str) f.close() ############### START URLS ############################ # create a urls file just for this app print "creating urls.py..." f = open("./" + app + "/urls.py", 'w') urls_str = """from django.conf.urls.defaults import * import """ + project + """.""" + app + """.views import sys urlpatterns = patterns('', (r'^helloworld/$', '""" + project + """.""" + app + """.views.hello_world'), (r'^stylesheet/$', '""" + project + """.""" + app + """.views.stylesheet'), (r'^admin/', include('django.contrib.admin.urls')), (r'^static/(.*)$', 'django.views.static.serve', {'document_root': '""" + path_to_here + """/static'}), ) """ print "adding examples to urls.py..." f.write(urls_str) f.close() ############### END URLS ############################ ############### CREATING FOLDERS AND FILES ############################ print "creating template folder, static folder (to serve pictures from)..." do("mkdir " + app + "/" + "templates") # create the stylesheet f = open( app + "/" + "templates/stylesheet.css" , 'w') f.write('''body{ }''') f.close() # create a base template that has links to style sheet and all the meta base tags I need. fname = app + "/" + "templates/base.html" print "creating a base.html and example.html template...." f = open( fname , 'w') f.write('<?xml version="1.0"?>') f.write('''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/2000/REC-xhtml1-20000126/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>{%block page_title%}Untitled{%endblock%}</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="DESCRIPTION" content="" /> <meta name="KEYWORDS" content="" /> <link rel="stylesheet" href="stylesheet.css" type="text/css" media="screen" /> </head> <body> <div id="header"> {%block header%}Navigation goes here{%endblock%} </div> <div id="content"> {%block content%}{%endblock%} </div> </body> </html>''') f.close() # create a template that extends that template, not used anywhere... f = open( app + "/" + "templates/example.html" , 'w') f.write('''{% extends "base.html" %} {% load humanize %} {%block header%} {%endblock%} {%block content%} <h3> Bla bla</h3> {%endblock%} ''') f.close() do("mkdir " + app + "/" + "static") #DO URLS ############### CREATING FOLDERS AND FILES ############################ print r"remember to add... (r'^"+ app +"/', include('"+project+"." + app + ".urls'))," print " to your main urls.py file!" print print "Now edit your models and views and urls before running python manage.py syncdb"
-------------------------------------------------------------------------------- Tom Smith |