Time for action implementing a basic CRM

Have a look at the following code (available as crm1.py). It will define the entities identified in the previous section and the result, when run, will have a familiar look:

Time for action implementing a basic CRM

We've added a little bit of CSS styling to order the elements on the page, but in the final revision, we will give it a much more attractive look. Clicking on the Add new button will allow you to add a new entity.

What just happened?

These humble beginnings in implementing CRM were accomplished by the code in crm1.py:

Chapter8/crm1.py

	import os
	import cherrypy
	from entity import AbstractEntity, Attribute, Picklist, 
	AbstractRelation
	from browse import Browse
	from display import Display
	from editor import Editor
	from logondb import LogonDB
	db="/tmp/crm1.db"
	class Entity(AbstractEntity):
		database = db
	class Relation(AbstractRelation):
		database = db
	class User(Entity):
		name = Attribute(notnull=True, unique=True,
				displayname="Name", primary=True)
	class Account(Entity):
		name = Attribute(notnull=True,
				displayname="Name", primary=True)
	class Contact(Entity):
		firstname = Attribute(displayname="First Name")
		lastname = Attribute(displayname="Last Name",
					notnull=True, primary=True)
	gender = Attribute(displayname="Gender",
			notnull=True,
			validate=Picklist(
						Male=1,
						Female=2,
						Unknown=0))
	telephone = Attribute(displayname="Telephone")
class Address(Entity):
	address = Attribute(displayname="Address",
				notnull=True, primary=True)
	city = Attribute(displayname="City")
	zipcode = Attribute(displayname="Zip")
	country = Attribute(displayname="Country")
	telephone = Attribute(displayname="Telephone")
class OwnerShip(Relation):
	a = User
	b = Account
class Contacts(Relation):
	a = Account
	b = Contact
class AccountAddress(Relation):
	a = Account
	b = Address
class ContactAddress(Relation):
	a = Contact
	b = Address

The first part is all about defining the entities and the relations between them according to the data model we sketched earlier. The concept is pretty much the same as for the books application, but for one important detail, the use of a picklist to limit the allowable choices for gender (highlighted). We will study these picklists in detail later in this chapter.

The next part creates the actual CherryPy application, with a Browse page for each entity (highlighted):

Chapter8/crm1.py

logon = LogonDB()
class AccountBrowser(Browse):
	display = Display(Account)
	edit = Display(Account, edit=True, logon=logon,
								columns=Account.columns+[Address,User])
	add = Display(Account, add=True, logon=logon,
								columns=Account.columns+[Address,User])
class UserBrowser(Browse):
	display = Display(User)
	edit = Display(User, edit=True, logon=logon)
	add = Display(User, add=True, logon=logon)
class ContactBrowser(Browse):
	display = Display(Contact)
	edit = Display(Contact, edit=True, logon=logon,
								columns=Contact.
columns+[Account,Address])
	add = Display(Contact, add=True, logon=logon,
								columns=Contact.
columns+[Account,Address])
class AddressBrowser(Browse):
	display = Display(Address)
	edit = Display(Address, edit=True, logon=logon)
	add = Display(Address, add=True, logon=logon)

The final part defines a Root class with an index() method that will force the user to identify himself/herself first (highlighted) and will then redirect the user to the /entities page, served by the entities() method.

This method will serve up a basepage with a navigation section that will allow the user to select a browse page for a type of entity and a content division which is initially empty, but will act as a container for either the chosen browse component or any edit or add page.

Chapter8/crm1.py

with open('basepage.html') as f:
	basepage=f.read(-1)
class Root():
	logon = logon
	user = UserBrowser(User)
	account = AccountBrowser(Account,
						columns=Account.
columns+[User,Address,Contact])
	contact = ContactBrowser(Contact,
						columns=Contact.columns+[Address,Account])
	address = AddressBrowser(Address)
	@cherrypy.expose
	def index(self):
		return Root.logon.index(returnpage='../entities')
	@cherrypy.expose
	def entities(self):
		username = self.logon.checkauth()
		if username is None :
				raise HTTPRedirect('.')
		user=User.list(pattern=[('name',username)])
		if len(user) < 1 :
				User(name=username)
		return basepage%'''
		<div class="navigation">
				<a href="user">Users</a>
				<a href="http://account">Accounts</a>
				<a href="contact">Contacts</a>
				<a href="http://address">Addresses</a>
		</div>
		<div class="content">
		</div>
		<script>
		... Javascript omitted ...
		</script>
		'''
cherrypy.config.update({'server.thread_pool':1})
cherrypy.engine.subscribe('start_thread',
	lambda thread_index: Root.logon.connect())
current_dir = os.path.dirname(os.path.abspath(__file__))
cherrypy.quickstart(Root(),config={
		'/':
		{ 'log.access_file' :
				os.path.join(current_dir,"access.log"),
		'log.screen': False,
		'tools.sessions.on': True
		},
		'/browse.js':
		{ 'tools.staticfile.on':True,
		'tools.staticfile.filename':current_dir+"/browse.js"
		},
		'/base.css':
		{ 'tools.staticfile.on':True,
		'tools.staticfile.filename':current_dir+"/base.css"
		}
})
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.217.17