B
bwaha
I'd appreciate some experience from the gurus out there to help me
understand how to implement MVC design in python code.
Entry number 5 on the wxpython wiki at
http://wiki.wxpython.org/index.cgi/BuildingControls discusses MVC design in
building reusable controls. The author (Terrel Shumway) suggests that
instead of:
quote:
class MyCoolListControl(...):
def __init__(self,parent,id,choices):
...
def InsertItem(...):
def AppendItem(...):
where choices is a static list, do something like this
class ListDataModel:
""" a minimal model interface to be used by MyCoolListControl """
def __len__(self):
""" return the number of items in the list """
def __getitem__(self,index):
""" return the specified item """
# consider notifications for observers (e.g. the list control)
# allow the user to define whatever mutators are appropriate
class MyCoolListControl(...):
def __init__(self,parent,id,model):
...
def [GS]etModel(self,model):
...
This allows the user (programmer) to store the data the way he thinks is
best, rather than having to copy the data into your structure whenever it
changes. It also reduces the need for kludges like [GS]etItemData for
maintaining association of the real data with its currently displayed string
representation.
endquote
The author refers to mvctree.py in wxPython as an example of MVC design.
However I'm still too green so I find that particular example too complex
and I'm not understanding the separation the author is recommending.
Can anyone explain to me further the simple example above and/or supply a
simple example of their own? At some level I feel like there's a benefit but
I'm failing to grasp it, and how to implement it. If I understand correctly
then in the future for example I could completely change how data is stored
in the class ListDataModel and not require a change in class
MyCoolListControl. Say, hypothetically, I wanted to implement ListDataModel
using a dictionary rather than, more naturally, a list, where the "list"
data structure is implemented as a dictionary and the list entries
correspond to dictionary keys (dictionary values are not used in this case).
Then if I understand the MVC concept, class MyCoolListControl need not
change at all. If that's true then that's really cool. But I don't get how
that works.
I think I need a little further expansion of the example or an alternative
(20-30 liner) that I can work through.
The question arises in the context of wanting to build a dialog with a tree
control that presents projects and studys as a tree and allows selection of
projects and studies as required by the user. I want to parse a file with
contents as follows:
BEGIN PROJECT "mpi6_0"
STUDY "Cyc0302_0" cyc0302_beanoz_x1.sdy
STUDY "Cyc0305_0" cyc0305_beanoz_x1.sdy
STUDY "Cyc0308_0" cyc0308_beanoz_x1.sdy
STUDY "Cyc0311_0" cyc0311_beanoz_x1.sdy
STUDY "Cyc0314_0" cyc0314_beanoz_x1.sdy
END PROJECT
BEGIN PROJECT "mpi6_1"
STUDY "Cyc0302_1" cyc0302_beanoz_x1.sdy
STUDY "Cyc0305_1" cyc0305_beanoz_x1.sdy
STUDY "Cyc0308_1" cyc0308_beanoz_x1.sdy
STUDY "Cyc0311_1" cyc0311_beanoz_x1.sdy
STUDY "Cyc0314_1" cyc0314_beanoz_x1.sdy
END PROJECT
....
I have wriiten a class as follows that extracts the data from the file.
import os
class ProjectFileDecoder:
"""
parse project file to obtain project names and associated studies and
study files
"""
def __init__(self, file):
self.projects = {}
self.parse_file(file)
def parse_file(self, file):
f = open(file, 'r')
dir = os.path.split(file)
while 1:
line = f.readline()
if 'BEGIN PROJECT' in line:
proj_name = line.strip().split('"')[1]
self.projects[proj_name] = {}
elif 'STUDY' in line:
study_name = (line.strip().split('"'))[1].strip()
study_file = dir[0] + '/' +
(line.strip().split('"'))[2].strip()
self.projects[proj_name][study_name] = study_file
elif not len(line):
f.close()
break
def getProjectNames(self):
return self.projects.keys()
def getStudyNames(self):
return [self.projects.keys() for i in self.getProjectNames()]
def getStudyFiles(self):
return [self.projects.values() for i in self.getProjectNames()]
At some level this seems to me like the class ListDataModel above. I just
need to make a MyTreeControl class. However here GS(et) routines are
implemented in the ProjectFileDecoder class (data model?) whereas in the
earlier advice they are in class MyCoolListControl. So I'm not understanding
how data gets from the DataModel class to the ListControl class. After all
the words I've said, I think that's the core misunderstanding I have.
Hope someone can help clear that up for me.
Chris
understand how to implement MVC design in python code.
Entry number 5 on the wxpython wiki at
http://wiki.wxpython.org/index.cgi/BuildingControls discusses MVC design in
building reusable controls. The author (Terrel Shumway) suggests that
instead of:
quote:
class MyCoolListControl(...):
def __init__(self,parent,id,choices):
...
def InsertItem(...):
def AppendItem(...):
where choices is a static list, do something like this
class ListDataModel:
""" a minimal model interface to be used by MyCoolListControl """
def __len__(self):
""" return the number of items in the list """
def __getitem__(self,index):
""" return the specified item """
# consider notifications for observers (e.g. the list control)
# allow the user to define whatever mutators are appropriate
class MyCoolListControl(...):
def __init__(self,parent,id,model):
...
def [GS]etModel(self,model):
...
This allows the user (programmer) to store the data the way he thinks is
best, rather than having to copy the data into your structure whenever it
changes. It also reduces the need for kludges like [GS]etItemData for
maintaining association of the real data with its currently displayed string
representation.
endquote
The author refers to mvctree.py in wxPython as an example of MVC design.
However I'm still too green so I find that particular example too complex
and I'm not understanding the separation the author is recommending.
Can anyone explain to me further the simple example above and/or supply a
simple example of their own? At some level I feel like there's a benefit but
I'm failing to grasp it, and how to implement it. If I understand correctly
then in the future for example I could completely change how data is stored
in the class ListDataModel and not require a change in class
MyCoolListControl. Say, hypothetically, I wanted to implement ListDataModel
using a dictionary rather than, more naturally, a list, where the "list"
data structure is implemented as a dictionary and the list entries
correspond to dictionary keys (dictionary values are not used in this case).
Then if I understand the MVC concept, class MyCoolListControl need not
change at all. If that's true then that's really cool. But I don't get how
that works.
I think I need a little further expansion of the example or an alternative
(20-30 liner) that I can work through.
The question arises in the context of wanting to build a dialog with a tree
control that presents projects and studys as a tree and allows selection of
projects and studies as required by the user. I want to parse a file with
contents as follows:
BEGIN PROJECT "mpi6_0"
STUDY "Cyc0302_0" cyc0302_beanoz_x1.sdy
STUDY "Cyc0305_0" cyc0305_beanoz_x1.sdy
STUDY "Cyc0308_0" cyc0308_beanoz_x1.sdy
STUDY "Cyc0311_0" cyc0311_beanoz_x1.sdy
STUDY "Cyc0314_0" cyc0314_beanoz_x1.sdy
END PROJECT
BEGIN PROJECT "mpi6_1"
STUDY "Cyc0302_1" cyc0302_beanoz_x1.sdy
STUDY "Cyc0305_1" cyc0305_beanoz_x1.sdy
STUDY "Cyc0308_1" cyc0308_beanoz_x1.sdy
STUDY "Cyc0311_1" cyc0311_beanoz_x1.sdy
STUDY "Cyc0314_1" cyc0314_beanoz_x1.sdy
END PROJECT
....
I have wriiten a class as follows that extracts the data from the file.
import os
class ProjectFileDecoder:
"""
parse project file to obtain project names and associated studies and
study files
"""
def __init__(self, file):
self.projects = {}
self.parse_file(file)
def parse_file(self, file):
f = open(file, 'r')
dir = os.path.split(file)
while 1:
line = f.readline()
if 'BEGIN PROJECT' in line:
proj_name = line.strip().split('"')[1]
self.projects[proj_name] = {}
elif 'STUDY' in line:
study_name = (line.strip().split('"'))[1].strip()
study_file = dir[0] + '/' +
(line.strip().split('"'))[2].strip()
self.projects[proj_name][study_name] = study_file
elif not len(line):
f.close()
break
def getProjectNames(self):
return self.projects.keys()
def getStudyNames(self):
return [self.projects.keys() for i in self.getProjectNames()]
def getStudyFiles(self):
return [self.projects.values() for i in self.getProjectNames()]
At some level this seems to me like the class ListDataModel above. I just
need to make a MyTreeControl class. However here GS(et) routines are
implemented in the ProjectFileDecoder class (data model?) whereas in the
earlier advice they are in class MyCoolListControl. So I'm not understanding
how data gets from the DataModel class to the ListControl class. After all
the words I've said, I think that's the core misunderstanding I have.
Hope someone can help clear that up for me.
Chris