Re: [Modeling-users] Customizing autogenerated classes
Status: Abandoned
Brought to you by:
sbigaret
|
From: <so...@la...> - 2003-03-27 01:18:37
|
On Wed, Mar 26, 2003 at 05:10:15PM -0600, Brad Bollenbach wrote:
> Hello,
Hy ;)=20
>=20
> How do I customize the business logic validation routines without my
> customizations getting blown away the next time I autogenerate the
> Python package (e.g. when I decide two months down the line that the
> app needs to be extended and five more tables need to be added)?
Hum, i want to point you that this problem isn't validation centric.
Look at this example:
--------------------------------------------------
class RssFeed(CustomObject):
__implements__ =3D CustomObject.__implements__
=20
def __init__(self):
self._title =3D 'unknow feed'
self._url =3D ''
---------------------------------------------------
As you can see i have a entity RssFeed with an url and a title,
not really a big deal. I want this object to handle the rss from=20
a website. I think the best way to go that is to have a getFeed()
method on the RssFeed object. So I just added something like that
to the generated class=20
....
def getFeed(self):
if not getattr(self,'_feed',None):
self._feed =3D rssparser.parse(self.getUrl())
return self._feed
....
So this kind of wrapping against ModelingObject can't be generated.
=20
> I've read through many of your unit tests, and a few relevant bits of
> the code and come up with what I see being the four realistic options:
>=20
> 1. The obvious one: add code directly to autogenerated Python
> code. The problem here though, is that it's difficult to do the whole
> backup-and-merge dance when I autogenerate again in the future. It's
> also tedious to take the other route of only exporting the XML model
> every time, and maintaining the classes (and/or adding new ones, if
> applicable) to keep up with it.
This is really a bad idea, cause=20
1) You can't handle all the variant you will need to build real app=20
2) How would you stay update w/ the modeling if you change the
"bricks" (template used to generate code)
But i think this is a piece of the tool. I think you can use this
"bricks" to generate some custom class
> 2. Write an adoption utility function, e.g. def adoptByClass(adopter,
> entities) that will iterate over a list of entities (e.g. those
> fetched from an editing context) and map them to the class specified
> as the "adopter". The "adopter" could be a class that I've created
> that inherits from one of the auto-generated classes and overrides its
> validation methods with my custom logic. It's good because I can
> autogenerate again and again, but it's bad because then I'm always
> making calls to adoptByClass.
This is perhaps a good idea, but i don't feel it really pythonic=20
Perhaps using interface will fix that . (Hum .. I don't feel interface
pythonic too in fact :))
> 3. Manually validate (e.g. using MySQLdb directly). This would ignore
> a significant piece of functionality that's already been created as
> part of the Modeling framework, so this isn't reasonable.
This won't work, because=20
1) you will have to handle specials db connections for that (=3D> overhea=
d)
2) my experience with SQL in modeling say that this is a bad habbit cause=
you
will have some big trouble with object carring some values in the edit=
ing
context, and not in the DB (remember that you can't store a object=20
ec.saveChanges() if one object isn't valid. I think S=E9bastian will=20
say the same.=20
Another trick, always keep in mind how the modeling works while
working on the model. Sometimes, building the model as you should
do in OO, or even in SQL way isn't a good choice.=20
Let take a example, think about a Folder/Article mapping, and for=20
statistics reasons we need to count the number of Article for a object
--------------------------------------------------------
In OO you will find something like this
Folder:
- name(string)
- articles(list)=20
Article:
- name(string)
- text(string)
- parent =3D folder
so counting the number of articles in a folder :=20
len(folder.articles())=20
--------------------------------------------------------
SQL =20
Folder:
- id=20
- name=20
Article:
- name
- text
- FK_FOLDER
so count will to something like that :
SELECT count(+1) as total from Article WHERE FK_FOLDER =3D ....=20
--------------------------------------------------------
So now in the modeling you will have a mix of this too methods.
If you use the OO model, counting articles in a folder by a=20
len( folder.articles()) will fetch all the articles in the EC=20
and that really can be a CPU waste.=20
Using ec.objectsCountWithFetchSpecification(fetchSpec) is a bit=20
like SQL method, but this can force you to have a strange API=20
in your code (read not working on object directly)=20
Perhaps in modeling i will do something like this:
Folder:
- id=20
- name
- number of article
Article:
...=20
=20
This is perhaps not the best example, but I hope you will
understand my meanings.
=20
> 4. Change an Entity's description so that it can have, perhaps both a
> baseclass *and* class attribute, where the baseclass attribute is the
> one that will get autogenerated and the class attribute is the only
> that I will code myself, overriding and extending the baseclass's
> methods as necessary.
The last, but not the least. I really think this is the best way to=20
solve the problem. This remember me how Corba (OmnyORB for example)=20
solve this kind of problem.=20
I think this *should* be handle by the bricks by default in fact.=20
Something like this:
Article_mdl.py=20
--------------------------------------------------------
# generated code never use this directly=20
class Article_mdl(CustomObject):
def __init__(self):
.....
def entityName(self):
return 'Article'
....=20
Article.py=20
--------------------------------------------------------
from Article_mdl import Article_mdl
class Article(Article_mdl):=20
=20
def __init__(self):
Article_mdl.__init__(self):
... my code go here ...
I think i will modify the bricks to handle this, during the week i
hope.=20
Bye Bye :)
I hope you understand my awfull english :)
|