Seite 1 von 1

prob mit ORM marke eigenbau

Verfasst: Montag 20. August 2007, 01:36
von Costi
ich schreib mir grad ein eigenes ORM dings fuer sql->python
allerdings krieg ich wenn ich die spalte eines meiner objekte mit ``__getitem__`` beantragen will den spaltenamen zurueckgegeben, statt den dazugehoerigen wert. Das passiert auch bei nich vorhandenen spaltennamen
warum?


Code: Alles auswählen

#
#ein orm
#noch laengst nit fertig
#
#die erste spalte einer tabelle muss die primary key sein!!
#

#import cherrypy as ch
import sqlite3

conn = sqlite3.connect(':memory:')
def debug():
	while True:
		print eval(raw_input('>>>'))

#class cursor:
#	@staticmethod
#	def execute(*args):
#		print args


def cursor2result_objects(find, cursor):
	return [find(i[0]) for i in cursor.fetchall()] #die methode find wird erst in der methode fusion "hinzugefuegt"
def cursor2plain(cursor):
	return cursor.fetchone()[0]

class BasicSQLQueries(object):
	def __init__(self, primary_key_name, table_name):
		self.primary_key = primary_key_name
		self.table_name = table_name

	def exe(self, *args):
		query = args[0].replace('*table*', self.table_name).replace('*primary_key*', self.primary_key)
		print 'EXECUTING:', query, args[1:]
		cursor = conn.cursor() #conn muss vorgegeben sein
		cursor.execute(query, args[1:])
		return cursor

	def all(self):
		return cursor2result_objects(cursor=self.exe("SELECT *primary_key* FROM *table*"), find=self.find)
		
class BasicSQLResult(object):
	def __init__(self, QueryObject, primary_key, create):
		self.QueryObject = QueryObject
		self.primary_key = primary_key
		if create:
			self.QueryObject.exe('INSERT INTO *table* (*primary_key*) VALUES (?)', self.primary_key)
	def __getitem__(self, item):
		return cursor2plain(self.QueryObject.exe('SELECT ? FROM *table* WHERE *primary_key*=?', item, self.primary_key))
	def __setitem__(self, item, value):
		return self.update(**{item: value})
		#KLAPPT NICH self.QueryObject.exe('UPDATE *table* SET ? = ? WHERE *primary_key* = ?', item, value, self.primary_key)
	def update(self, **data):
		arg = data.values()
		arg.append(self.primary_key)
		self.QueryObject.exe('UPDATE *table* SET ' + ''.join([key + ' = ?, ' for key in data])[:-2] + ' WHERE *primary_key*=?', *arg)# why is foo(1, *t, 6) invalid?


		
def fusion(QueryObject, ResultClass):
	class Tmp(QueryObject):
		def __init__(self):
			QueryObject.__init__(self)
		def create(self, primary_key_val):
			return ResultClass(QueryObject=self, primary_key=primary_key_val, create=True)
		def find(self, primary_key_val):#exactly like create but did not create the row
			return ResultClass(QueryObject=self, primary_key=primary_key_val, create=False)
	return Tmp()

#==========================TEST================		


conn.cursor().execute('''CREATE TABLE users
(nickname char(50),
firstname char(50),
lastname char(50),
age int)''')
class UsersResult(BasicSQLResult):
	def __init__(self, **kw):
		BasicSQLResult.__init__(self, **kw)
	def write_post(self, text):
		post = Posts.create('foo goes bike')
		post['text'] = text
class UsersQueries(BasicSQLQueries):
	def __init__(self):
		BasicSQLQueries.__init__(self, primary_key_name='nickname', table_name='users')
	def bla(self):
		self.exe('FROM users do bullshit AND FUCK SQL')
Users = fusion(UsersQueries, UsersResult)



horst = Users.create('Horst')
horst['lastname'] = 'Allendorf'

a_user = Users.all()[0]
print a_user.QueryObject.exe('SELECT * FROM *table* where *primary_key*=?', a_user.primary_key).fetchone() #hat funktional kein sinn, gibt aber ein guten einblick

print horst['lastname'] #-> "lastname"  (WTF?)
print horst['X'] #-> "X" (und warum kein  ``OperationalError``?)


der output ist auch hilfreich:

Code: Alles auswählen

C:\Dokumente und Einstellungen\sc>"C:\Dokumente und Einstellungen\sc\Desktop\ira
e\domino.py"
EXECUTING: INSERT INTO users (nickname) VALUES (?) ('Horst',)
EXECUTING: UPDATE users SET lastname = ? WHERE nickname=? ('Allendorf', 'Horst')

EXECUTING: SELECT nickname FROM users ()
EXECUTING: SELECT * FROM users where nickname=? (u'Horst',)
(u'Horst', None, u'Allendorf', None)
EXECUTING: SELECT ? FROM users WHERE nickname=? ('lastname', 'Horst')
lastname
EXECUTING: SELECT ? FROM users WHERE nickname=? ('X', 'Horst')
X

EDIT
und noch was:
wieso geht meine ueberaus komplexe ``debug`` function nicht?

Re: prob mit ORM marke eigenbau

Verfasst: Montag 20. August 2007, 09:21
von Leonidas
Costi hat geschrieben:warum?
Die gleiche Frage habe ich mir auch gestellt: Warum? Warum noch ein ORM? Was kann dein ORM, was andere nicht können?
Ein ORM ist keine so einfache Sache, selbst wenn ein ORM jahrelang im Einsatz ist finden sich immer noch Fehler, wie das bei Djangos ORM immer wieder der Fall ist. Der Python-Markt an ORMs ist mit Djangos ORM, SQLAlchemy,SQLObject, Storm, PyDO, etc. eher übersättigt.

Übrigens, ``eval(raw_input())`` ist genau das gleiche wie ``input()``.

Verfasst: Montag 20. August 2007, 12:47
von Joghurt
Ich würde dir auch raten, es stattdessen mal mit SQLAlchemy zu versuchen. Es ist super dokumentiert, hat ein gutes Tutorial und ist sogar sinnvoll in zwei Teile aufgeteilt, den ORM und die SQL Construction Language. Diese Ternnung ist sehr praktisch, wenn es zu komplizierten Datenbank-Modellen kommt, wo du lieber selber die Kontrolle haben willst, welche Statements abgesetzt werden, anstatt es den ORM machen zu lassen.

Verfasst: Montag 20. August 2007, 14:39
von Costi
ich habs schon mit verschiedenen ORMs ausprobiert,
aber es kommt immer wieder zu unerwarteten fehlern
und wenn ich die implementation kenne und sie nicht so overkilling ist kann ich mehr tun als mir die haare auszureisen

ausserdem machts mir einfach spass ein ORM zu schreiben :lol:


EDIT
ich fass es nur nicht bei zeile 100,
dort wird dann wie erwartet,

Code: Alles auswählen

("SELECT ? FROM users WHERE nickname=?" ('X', 'Horst'))
an cursor.execute mitgegeben aber warum liefert mir sqlite3 dafuer den wert ``"x"`` zurueck

[/code]

Verfasst: Montag 20. August 2007, 15:41
von Leonidas
Costi hat geschrieben:ich habs schon mit verschiedenen ORMs ausprobiert,
aber es kommt immer wieder zu unerwarteten fehlern
und wenn ich die implementation kenne und sie nicht so overkilling ist kann ich mehr tun als mir die haare auszureisen
Was sind "unerwartete Fehler"? Du kannst auch so mehr tun als dir die Haare auszureißen - du kannst auch SQLAlchemy nehmen und bei Problemen in #sqlalchemy fragen - die Leute sind meist sehr schnell da um Hilfe zu leisten. Zugegeben, SQLAlchemy ist nicht das simpelste ORM (mit Elixir wirds aber etwas einfacher) aber warscheinlich das solideste, was es derzeit für Python gibt.

Verfasst: Montag 20. August 2007, 16:25
von BlackJack
Ich denke mal das sind keine Fehler sondern Costi bekommt in den meisten Fällen nur richtige Antworten, die er nicht versteht. Wie das "x" bei der SQL-Abfrage. Wenn man sagt man möchte ein "x" dann bekommt man halt auch eines. Platzhalter sind für Werte, nicht für Bezeichner. D.h. in diese Abfrage wird der Wert "x" hinter das ``SELECT`` gesetzt.

Verfasst: Montag 20. August 2007, 17:50
von Costi
Platzhalter sind für Werte, nicht für Bezeichner.
ahhh das ergibt sinn, jetzt klappt alles.

bin ich jetzt nachdem ich das "foreign key"- und many-to-many-dingsbums
implementiert habe etwa schon fertig??

das werden ja deutlich weniger als 200 lines werden :lol:

Verfasst: Montag 20. August 2007, 23:11
von Leonidas
Costi hat geschrieben:bin ich jetzt nachdem ich das "foreign key"- und many-to-many-dingsbums
implementiert habe etwa schon fertig??

das werden ja deutlich weniger als 200 lines werden :lol:
Planst du mit TinyP2P zu konkurrieren?

Ich habe mir mal angesehen wie SQLAlchemy im Vergleich dazu abschneidet:

Code: Alles auswählen

$ wc -l `find sqlalchemy-0.4.0beta3 -regex '.*py$' -printf '%p '`
[...]
  31607 total
:roll: