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


Attachment: 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         



Reply via email to