db: change ForeignKey columns to use _id suffix; start using SQLAlchemy ORM for Order model
--- a/svv/application.py Thu Dec 30 23:54:38 2010 +0200
+++ b/svv/application.py Fri Dec 31 01:05:24 2010 +0200
@@ -83,3 +83,13 @@
self.engine.execute(sql, **values)
+ # XXX: rename this to something else, conflicts, to some degree, with web session with cookies (although using
+ # SQL transctions at that level would be pretty cool..)
+ # orm orm_session objects dbsession dbmapping dbmaps
+ def session (self) :
+ """
+ Return a new SQLAlchemy database session, for use with ORM mapped objects.
+ """
+
+ return db.session_factory(bind=self.engine)
+
--- a/svv/database.py Thu Dec 30 23:54:38 2010 +0200
+++ b/svv/database.py Fri Dec 31 01:05:24 2010 +0200
@@ -6,6 +6,12 @@
from sqlalchemy import *
+# for ORM definitions; outside of this module
+from sqlalchemy.orm import mapper, sessionmaker
+
+# used by Application.session
+session_factory = sessionmaker()
+
# our schema
schema = MetaData()
@@ -33,7 +39,7 @@
Column('id', Integer, primary_key=True),
# reference to contact being primary for specified customer (organization or themselves)
- Column('customer', None, ForeignKey('customers.id'), nullable=True),
+ Column('customer_id', None, ForeignKey('customers.id'), nullable=True),
# person's natural name
Column('name', Unicode, nullable=True),
@@ -55,10 +61,10 @@
Column('id', Integer, primary_key=True),
# ordering customer, if entered (i.e. who to bill)
- Column('customer', None, ForeignKey('customers.id'), nullable=True),
+ Column('customer_id', None, ForeignKey('customers.id'), nullable=True),
# active contact at customer side for order (i.e. who to call)
- Column('contact', None, ForeignKey('contacts.id'), nullable=True),
+ Column('contact_id', None, ForeignKey('contacts.id'), nullable=True),
# short description of customer event where these items are going
Column('event_name', Unicode, nullable=True),
--- a/svv/orders.py Thu Dec 30 23:54:38 2010 +0200
+++ b/svv/orders.py Fri Dec 31 01:05:24 2010 +0200
@@ -22,6 +22,62 @@
log = logging.getLogger('svv.orders')
+class Customer (object) :
+ """
+ Data-mapping for the customers table
+ """
+
+ # customer name (organization or natural person)
+ name = None
+
+class Contact (object) :
+ """
+ Data-mapping for the contacts table
+ """
+
+ # human-readable details
+ name = None
+ phone = None
+ email = None
+
+ # relation to Customer
+ customer = None
+
+
+class Order (object) :
+ """
+ Data-mapping for orders table.
+ """
+
+ # relation to Customer
+ customer = None
+
+ # relation to Contact
+ contact = None
+
+ # event info
+ event_name = None
+ event_description = None
+ event_start = None
+ event_end = None
+
+ def __init__ (self) :
+ """
+ Construct an Order with default values
+ """
+
+ ## Set default values
+ tomorrow = datetime.date.today() + datetime.timedelta(days=1)
+
+ # default to tomorrow afternoon
+ self.event_start = datetime.datetime.combine(tomorrow, datetime.time(16, 00))
+ self.event_end = None # determined by UI behaviour
+
+# bind against database schema
+db.mapper(Customer, db.customers)
+db.mapper(Contact, db.contacts)
+db.mapper(Order, db.orders)
+
class FormError (Exception) :
"""
A user-level error in a form field
@@ -395,7 +451,7 @@
('contact_name', db.contacts.c.name, contact_name),
('contact_phone', db.contacts.c.phone, contact_phone),
('contact_email', db.contacts.c.email, contact_email),
- ('contact_customer', db.contacts.c.customer, contact_customer),
+ ('contact_customer', db.contacts.c.customer_id, contact_customer),
),
)
@@ -463,7 +519,7 @@
"""
# query tables from db
- sql_from = db.orders.join(db.customers).join(db.contacts, (db.orders.c.contact == db.contacts.c.id))
+ sql_from = db.orders.join(db.customers).join(db.contacts, (db.orders.c.contact_id == db.contacts.c.id))
sql = db.select(
[
db.orders,
@@ -513,7 +569,7 @@
sql = db.select([db.contacts.c.id, db.contacts.c.name, db.contacts.c.phone, db.contacts.c.email])
if customer_id :
- sql = sql.where((db.contacts.c.customer == customer_id))
+ sql = sql.where((db.contacts.c.customer_id == customer_id))
return self.app.query(sql)
@@ -812,14 +868,14 @@
tuples, ordered by event_start, per default
"""
- sql_from = db.orders.join(db.customers).join(db.contacts, (db.contacts.c.id == db.orders.c.contact))
+ sql_from = db.orders.join(db.customers).join(db.contacts, (db.contacts.c.id == db.orders.c.contact_id))
sql = db.select(
[
db.orders.c.id,
- db.orders.c.customer,
+ db.orders.c.customer_id,
db.customers.c.name,
db.orders.c.event_name,
- db.orders.c.contact,
+ db.orders.c.contact_id,
db.contacts.c.name,
db.orders.c.event_start,
db.orders.c.event_end,
@@ -934,9 +990,9 @@
# Tilaaja
tags.td(
- tags.a(href=self.url_for(urls.CustomerView, id=row[db.orders.c.customer]))(
+ tags.a(href=self.url_for(urls.CustomerView, id=row[db.orders.c.customer_id]))(
row[db.customers.c.name]
- ) if row[db.orders.c.customer] else "-"
+ ) if row[db.orders.c.customer_id] else "-"
),
# Tapahtuma
@@ -950,7 +1006,7 @@
tags.td(
tags.a(href='#')(
row[db.contacts.c.name]
- ) if row[db.orders.c.contact] else "-"
+ ) if row[db.orders.c.contact_id] else "-"
),
# Ajankohta
@@ -1023,47 +1079,53 @@
Render form for database object, let the user make updates, update the database.
"""
- def update (self, id, form) :
- """
- Update database values from form
+ def update (self, order, form) :
"""
-
- sql = db.orders.update().where((db.orders.c.id == id)).values(
- {
- db.orders.c.customer : form.customer_id,
- db.orders.c.contact : form.contact_id,
- db.orders.c.event_name : form.event_name,
- db.orders.c.event_description : form.event_description,
- db.orders.c.event_start : form.event_start,
- db.orders.c.event_end : form.event_end,
- }
- )
-
- # execute it
- self.app.execute(sql)
+ Update order values from submitted form data
+ """
+
+ # modify
+ order.customer_id = form.customer_id
+ order.contact_id = form.contact_id
+ order.event_name = form.event_name
+ order.event_description = form.event_description
+ order.event_start = form.event_start
+ order.event_end = form.event_end
+
+ # commit
+ self.session.commit()
def process (self, id) :
"""
- Set up our form.
+ Set up our object form.
+
+ Process incoming POST data.
"""
+ # db session
+ self.session = self.app.session()
+
+ # order object
+ self.order = self.session.query(Order).get(id)
+
+ # form
self.form = OrderForm(self.app)
- # use either POST data or database data
+ # load object data
+ self.form.load(id)
+
+ # update order?
if self.POST :
+
# feed form our POST data
if self.form.process(self.POST) :
- # submit data OK
- self.update(id, self.form)
+ # submit data was OK, update order from form
+ self.update(self.order, self.form)
else :
# errors
pass
- else :
- # fetch data from database
- self.form.load(id)
-
def render_contract_form (self, id) :
"""
Render the contract panel for our view
@@ -1104,22 +1166,27 @@
Create the new order from the given form data, returning the new order's ID
"""
- # if we've gotten this far, then we can create it!
- sql = db.insert(db.orders).values(
- customer = form.customer_id,
- contact = form.contact_id,
-
- event_name = form.event_name,
- event_description = form.event_description,
- event_start = form.event_start,
- event_end = form.event_end,
- )
+ # db session
+ session = self.app.session()
- # go!
- order_id, = self.app.insert(sql)
+ # order model
+ order = Order()
- # great
- return order_id
+ # set attrs
+ order.customer_id = form.customer_id
+ order.contact_id = form.contact_id
+
+ order.event_name = form.event_name
+ order.event_description = form.event_description
+ order.event_start = form.event_start
+ order.event_end = form.event_end
+
+ # add and commit
+ session.add(order)
+ session.commit()
+
+ # return with new id
+ return order.id
def process (self) :
"""