My unhappiness with django is growing. I have a model containing the following classes:
class Post: class Tag:
I have a many-to-many relationship between these two classes. Trying to code something, if I do something like the following:
class Post: def DoSmethingWithTags( self): oTags = tags.get_tags()
it fails because it needs:
from django.models.blog import posts,tags
but I cannot put this in the model file or module import starts recursing (or so I believe). This kind of thing is just a pain and I don't want to spend my time working around architectural oddities. I tried creating a library module in the model directory but then it couldn't be found when I tried to import it (?). Python path weirdness, and django is fussy about the python path setup, more so than any other package I can think of, usually everthing is relative to a current directory and is happy.
So I gave Turbogears a look. I watched the wiki in 20 minutes film, seems ok but a lot to learn (like django), including it's own architectural oddities.
I installed it directly onto Windows which was very easy.
Next stumbling block is to get it to run under WingIDE. This was more fiddly. Like django it has autoreload but unlike django there is a config entry to disable it. Next problem is that it is multi-threaded which gives WingIDE a hard time. Here is my solution:
Add the following to the turbogears dev.cfg file:
1 # 2 # Run in a single thread 3 # 4 server.class="_cphttpserver.embedded_server" 5 server.threadPool=1 6 7 # 8 # Disable auto reload. 9 # 10 autoreload.on=0
but this is not enough as it still runs two threads, one to watch the keyboard. Don't care about this if running under a debugger with a stop button: I can't stop it cleanly but this is not a big deal for development. Making it strictly single threaded involves overriding the _cpserver.Server class. I changed my turbogears xxx-start.py file as follows:
1 cherrypy.root = Root() 2 #cherrypy.server.start() 3 4 import cherrypy._cpserver 5 6 class NonThreadedServer( cherrypy._cpserver.Server): 7 def start_http_server(self, blocking=True): 8 """Start the requested HTTP server.""" 9 if self.httpserver is not None: 10 msg = ("You seem to have an HTTP server still running." 11 "Please call server.stop_http_server() " 12 "before continuing.") 13 warnings.warn(msg) 14 15 if self.httpserverclass is None: 16 return 17 18 if cherrypy.config.get('server.socketPort'): 19 host = cherrypy.config.get('server.socketHost') 20 port = cherrypy.config.get('server.socketPort') 21 22 cherrypy._cpserver.wait_for_free_port(host, port) 23 24 if not host: 25 host = 'localhost' 26 onWhat = "http://%s:%s/" % (host, port) 27 else: 28 onWhat = "socket file: %s" % cherrypy.config.get('server.socketFile') 29 30 # Instantiate the server. 31 self.httpserver = self.httpserverclass() 32 33 # HTTP servers MUST be started in a new thread, so that the 34 # main thread persists to receive KeyboardInterrupt's. This 35 # wrapper traps an interrupt in the http server's main thread 36 # and shutdowns CherryPy. 37 def _start_http(): 38 try: 39 self.httpserver.start() 40 except (KeyboardInterrupt, SystemExit), exc: 41 self.interrupt = exc 42 # threading.Thread(target=_start_http).start() 43 44 # 45 # Run in a single thread to make debugging a joy 46 # 47 self.state = cherrypy._cpserver.STARTED 48 # Changing the socket timeout makes WingIDE more responsive 49 self.httpserver.socket.settimeout( 0.1) 50 self.httpserver.start() # Should not return from here!! 51 52 if blocking: 53 self.wait_for_http_ready() 54 55 cherrypy.log("Serving HTTP on %s" % onWhat, 'HTTP') 56 57 # _cphttpserver uses this global variable so have to poke it 58 cherrypy.server = NonThreadedServer() 59 cherrypy.server.start()
I wasn't able to make django debuggable in WingIDE without hacking it's source: it didn't seem to have as many useful hooks as cherrypy/turbogears.


Hi Peter,
We're currently working on removing the magic oddities in Django that got in your way. I've started a "magic-removal" branch of the code and have been working hard on it with the team for the past couple of days. See code.djangoproject.com/wiki/RemovingTheMagic . I suspect this should be done within a week.
Let me know if you have any other concerns!