Es verdient in jedem Fall Respekt, so ein Projekt auf die Beine zu stellen. Einen Screencast als Einführung zu haben, ist auch immer eine gute Wahl. Ich fand ich gut verständlich (sprachlich & inhaltlich). Allerdings würde ich empfehlen, diese "follow the mouse"-Funktion abzuschalten. Ich wurde da fast seekrank

Nimm dir lieber einen 1280x800-Ausschnitt deines Bildschirms, bringe vorher alle deine Fenster auf diese Größe, mache die Schrift im Editor und Browser groß genug und komme mit diesem Platz dann aus.
Die Frage, die du beantworten können solltest, ist was deinen Ansatz besonders macht. Das ist jetzt nicht ersichtlich.
Warum brauche ich einen Rails-Clone auf dem Stand von vor 5 Jahren? Oder wie alt ist Rails schon? Juli 2004 - das wären sogar 8 Jahre. Uff.
Du könntest sagen, es ist jetzt Python statt Ruby, aber zumindest ich finde die konkrete Programmiersprache (solange es nicht PHP ist) relativ egal und somit nur ein schwaches Argument. Was kann PoW, das sonst aufwendiger ist oder schlechter funktioniert?
Auch den Vergleich mit Django musst du dir natürlich gefallen lassen. Dieses ist zwar ebenfalls angestaubt (oder ausgereift, je nach Sichtweise), bietet aber im Prinzip das selbe wie PoW. Ich befürchte, dein Blog-Beispiel lässt sich mit Django sogar noch einfacher umsetzen und man bekommt noch ein Endbenutzer-taugliches Admin-UI dazu und könnte auch gleich noch eine Kommentar-Funktion integrieren.
Es ist meine Überzeugung, dass Web-Anwendungen heutzutage anders geschrieben werden sollten als noch vor 8 Jahren.
Meteor ist ein gutes Beispiel für einen neuen Ansatz. So etwas für Python wäre cool!
Nutzt man MongoDB als Backing-Store, spart man sich einiges an Komplexität. Der Server stellt dann im wesentlichen die Daten per REST-API zur Verfügung und ein Client-Rahmenwerk kümmert sich um die Darstellung. Das verschiebt die Komplexität vom Server auf den Client. Dafür sollte ersterer auch Web-Sockets unterstützen. Client-seitig kommt man zwangsläufig mit JavaScript in Kontakt. Will man serverseitig eine andere Sprache nutzen, muss es dafür einen guten Grund geben. Oder man muss eine Lösung haben, die Sprache vom Server auch irgendwie auf den Client zu bringen.
Diese Art von Web-Anwendungen zu schreiben ist jedenfalls harte Arbeit und auch wenn sich Backbone als Standard durchzusetzen scheint, ist das nicht unbedingt die beste Wahl und auch noch nicht der klare Sieger. Hier Unterstützung zu haben wäre etwas, das kein anderes Python-Rahmenwerk bietet.
Ab hier wird es OT und ich hatte einfach Spaß daran, mal etwas zu schreiben... Sorry...
So könnte das Blog-Beispiel (ohne HTML) mit einem hypothetischen Web-Framework "wfw" für Node.js aussehen:
Code: Alles auswählen
// app.js
var wfw = require("wfw"), Post = require("./Post");
var app = wfw.app()
.get("/blog", wfw.find(Post.limit(5).desc('created')), wfw.render("blog"))
.use(wfw.resource("/blog", Post))
.listen(3000);
In der ersten Zeile lade ich mein Rahmenwerk und mein Model. Als nächstes erzeuge ich mit "app()" das Web-App-Objekt (implementiert mit "express"). Die Funktion "resource()" bindet die üblichen 7 URLs und weiß, wie sie an die Daten aus dem Modell kommt. Ich überschreibe als nächstes die URL "/blog", welche die ersten fünf Blog-Einträge (den neusten zuerst) mit dem Template "blog" darstellen soll. Dann starte ich die App auf Port 3000.
Habe ich jetzt noch ein Kommandozeilen-Programm für das Scaffolding der Templates und der Modell-Beschreibung (die ich auf mongoose abstütze), bin ich dort, wo auch Rails 1.x mal war.
Code: Alles auswählen
wfw scaffold Post title:String content:String created:Date
Dies würde dann mein Modell erzeugen:
Code: Alles auswählen
// Post.js
var wfw = require("wfw");
var Post = wfw.model("Post", { title: String, content: String, created: Date });
Ohne das jetzt ausprobiert zu haben, denke ich, dass "wfw" auch relativ einfach zu implementieren wäre:
Code: Alles auswählen
// wfw.js
var express = require("express"), mongoose = require("mongoose");
exports.model = function model(name, options){
return mongoose.model(name, new mongoose.Schema(options));
}
exports.app = function app(){
return express().use(express.bodyParser()).use(express.favicon());
}
exports.resource = function resource(path, model){
var app = express(), name = path.substring(1) + "_";
app.get(path, find(model), render(name + "list"));
app.get(path + "/new", new(model), render(name + "new"));
app.post(path, create(model), redirect(path));
app.get(path + "/:id", findOne(model), render(name + "show"));
app.get(path + "/:id/edit", findOne(model), render(name + "edit"));
app.put(path + "/:id", update(model), function(...){ ... });
app.delete(path + "/:id", findOne(model), function(...){ ... });
return app;
}
exports.find = function find(model){
return function(req, res, next){
model.find({}, function(err, objects){
if (err){ res.send(500); return; }
req.objects = objects;
next();
})
}
}
exports.findOne = function(model){
return function(req, res, next){
model.findOne({_id: req.params.id}, function(err, object){
if (err){ res.send(500); return; }
req.object = object;
next();
});
}
}
exports.render = function(name){
return function(req, res){
res.render(name, {objects: req.objects, object: req.object});
}
}
...
Ich nutze dabei jede Menge "middleware"-Funktionen für Express und die Konvention, dass diese mir die Objekte in eine Eigenschaft "objects" bzw. "object" des Request-Objekts einträgt, wo ich das dann in "render" wieder auslese und so dem Template übergebe. Das ist zu simpel, wenn ich Formulare dynamisch generieren wollen würde, aber das kann Rails auch nicht. Die Middleware ist praktisch, weil jeder Zugriff auf die DB asynchron ist und ich ansonsten alle Funktion schachteln müsste. Das ist aber egal hier, entscheidend ist, wie es in "app.js" aussieht.
Stefan