I have a product with a number of classes that have subclasses. It seems natural to make the screens for the subclasses by extending those of the superclass. Can anyone suggest a good way to do that? The naive approach is that I have a manage_edit_A.dtml that gives a management screen for A. If B subclasses A, I create manage_edit_B.dtml by copying from the first file and then fiddling with it. Obviously, it would be desirable for a change in A to only require changing a single file. I would prefer a more elegant approach. Perhaps I can define some method in A that the dtml will reference, and then B can override the method to add some extra stuff (the method would return a DTML snippet). First, I'm not exactly sure how to pick up the method from the DTML. Second, I'm not sure if this is the best solution. For one thing, I would prefer to keep all my dtml in separate files, rather than defining it into my methods. Any suggestions? P.S. I'd like to thank Toby Dickenson, Casey Duncan, and R. David Murray for their very helpful responses to my previous question.
One approach might be to create a generic dtml (or zpt) template that has several placeholders (in the form of <dtml-var> or tal:replace) for the areas of the form that will vary. Then each subclass can override what goes in these placeholders if it chooses. Something like: class A(Acquisition.Implicit): main = DTMLFile('foo', globals()) sect1 = DTMLFile('Asect1', globals()) sect2 = DTMLFile('Asect2', globals()) class B(A): sect1 = DTMLFile('Bsect1', globals()) class C(B): sect2 = DTMLFile('Csect2', globals()) class D(A): sect2 = DTMLFile('Dsect2', globals()) where main.dtml looks like: <dtml-var standard_html_header> ... <dtml-var sect1> ... <dtml-var sect2> ... <dtml-var standard_html_footer> The DTMLFile should acquire the correct version of sect1 and sect2 from its parent instance above. Asect1.dtml, Asect2.dtml, Bsect1.dtml, Csect2.dtml and Dsect2.dtml would all be separate files. hth, Casey On Wednesday 17 July 2002 05:50 pm, Ross Boylan wrote:
I have a product with a number of classes that have subclasses. It seems natural to make the screens for the subclasses by extending those of the superclass. Can anyone suggest a good way to do that?
The naive approach is that I have a manage_edit_A.dtml that gives a management screen for A. If B subclasses A, I create manage_edit_B.dtml by copying from the first file and then fiddling with it. Obviously, it would be desirable for a change in A to only require changing a single file.
I would prefer a more elegant approach. Perhaps I can define some method in A that the dtml will reference, and then B can override the method to add some extra stuff (the method would return a DTML snippet).
First, I'm not exactly sure how to pick up the method from the DTML. Second, I'm not sure if this is the best solution. For one thing, I would prefer to keep all my dtml in separate files, rather than defining it into my methods.
Any suggestions?
P.S. I'd like to thank Toby Dickenson, Casey Duncan, and R. David Murray for their very helpful responses to my previous question.
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
Is there a way to get inheritance, so that, for example, class C(B): sect1 = DTMLFile("CSect2",globals())+B.sect1(self)? I don't think that syntax will work, but perhaps you see what I'm driving at--I want to include all the previous stuff. On Thu, Jul 18, 2002 at 09:11:13AM -0400, Casey Duncan wrote:
One approach might be to create a generic dtml (or zpt) template that has several placeholders (in the form of <dtml-var> or tal:replace) for the areas of the form that will vary.
Then each subclass can override what goes in these placeholders if it chooses. Something like:
class A(Acquisition.Implicit): main = DTMLFile('foo', globals()) sect1 = DTMLFile('Asect1', globals()) sect2 = DTMLFile('Asect2', globals())
class B(A): sect1 = DTMLFile('Bsect1', globals())
class C(B): sect2 = DTMLFile('Csect2', globals())
class D(A): sect2 = DTMLFile('Dsect2', globals())
where main.dtml looks like:
<dtml-var standard_html_header> ... <dtml-var sect1> ... <dtml-var sect2> ... <dtml-var standard_html_footer>
The DTMLFile should acquire the correct version of sect1 and sect2 from its parent instance above.
Asect1.dtml, Asect2.dtml, Bsect1.dtml, Csect2.dtml and Dsect2.dtml would all be separate files.
hth,
Casey
On Wednesday 17 July 2002 05:50 pm, Ross Boylan wrote:
I have a product with a number of classes that have subclasses. It seems natural to make the screens for the subclasses by extending those of the superclass. Can anyone suggest a good way to do that?
The naive approach is that I have a manage_edit_A.dtml that gives a management screen for A. If B subclasses A, I create manage_edit_B.dtml by copying from the first file and then fiddling with it. Obviously, it would be desirable for a change in A to only require changing a single file.
I would prefer a more elegant approach. Perhaps I can define some method in A that the dtml will reference, and then B can override the method to add some extra stuff (the method would return a DTML snippet).
First, I'm not exactly sure how to pick up the method from the DTML. Second, I'm not sure if this is the best solution. For one thing, I would prefer to keep all my dtml in separate files, rather than defining it into my methods.
Any suggestions?
P.S. I'd like to thank Toby Dickenson, Casey Duncan, and R. David Murray for their very helpful responses to my previous question.
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://lists.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope )
On Thursday 18 July 2002 02:06 pm, Ross Boylan wrote:
Is there a way to get inheritance, so that, for example, class C(B): sect1 = DTMLFile("CSect2",globals())+B.sect1(self)?
I don't think that syntax will work, but perhaps you see what I'm driving at--I want to include all the previous stuff.
Please explain what you mean by "include". + to me implies append, surely not what you were after. Perhaps a specific use case would make this clear. -Casey
On Thu, Jul 18, 2002 at 02:18:43PM -0400, Casey Duncan wrote:
On Thursday 18 July 2002 02:06 pm, Ross Boylan wrote:
Is there a way to get inheritance, so that, for example, class C(B): sect1 = DTMLFile("CSect2",globals())+B.sect1(self)?
I don't think that syntax will work, but perhaps you see what I'm driving at--I want to include all the previous stuff.
Please explain what you mean by "include". + to me implies append, surely not what you were after.
Perhaps a specific use case would make this clear.
-Casey
I think append would be OK. In most obvious case, the screen for A looks like foo bar xxx yyyy And for B it would be foo bar xxx yyyy zzz aaa And then for C foo bar xxx yyyy zzz aaa qqq tttt And then if I extend A by adding some more data or info on the screen foo bar new stuff xxx yyyy C ends up looking like foo bar new stuff xxx yyyy zzz aaa qqq tttt
Ross Boylan writes:
... I would prefer a more elegant approach. Perhaps I can define some method in A that the dtml will reference, and then B can override the method to add some extra stuff (the method would return a DTML snippet). That sounds good. It is how the ZMI works...
First, I'm not exactly sure how to pick up the method from the DTML. There are two cases:
* view of an existing object then the object is the client of the primary view. Make all you snippets attributes of the object and you can simply access them by name. The ZMI does this. If necessary, look how it does. * object creation form That's much more difficult. ZMI does not reuse fragments for this case. There is a partial solution for DTMLFiles, but it is not nice and restricted to DTML. "DTMLFile" constructors accept a dictionary with default name bindings. This way, you can customize your DTMLFile with different bindings according to context, e.g. addAForm= DTMLFile('dtml/addForm', globals(), comp1= AComp1 comp2= AComp2 ...) addBForm= DTMLFile('dtml/addForm', globals(), comp1= BComp1 comp2= BComp2 ...)
Second, I'm not sure if this is the best solution. For one thing, I would prefer to keep all my dtml in separate files, rather than defining it into my methods. You can have separate files and do something like:
class YourProduct: .... mySnippet= DTMLFile('dtml/mySnippetFile',globals()) .... Dieter
On Thu, Jul 18, 2002 at 08:41:02PM +0200, Dieter Maurer wrote:
Ross Boylan writes:
... I would prefer a more elegant approach. Perhaps I can define some method in A that the dtml will reference, and then B can override the method to add some extra stuff (the method would return a DTML snippet). That sounds good. It is how the ZMI works...
ZMI = Zope Management Interface (i.e., in the core app), or is this something else? At any rate, I'm not sure what you're referring to, or where to look.
First, I'm not exactly sure how to pick up the method from the DTML. There are two cases:
* view of an existing object
then the object is the client of the primary view. Make all you snippets attributes of the object and you can simply access them by name.
The ZMI does this. If necessary, look how it does.
The problem isn't just accessing them, but combining them. Say C is a subclass of B is a subclass of A. Each subclass has the entire user interface of its base class (aka superclass) and some extra stuff. Either each class implements its novel stuff with a unique name. In that case, I still have to make a separate dtml file for each, referencing the appropriate names (though your suggestion below helps on that). Or each has the same name. Then the problem is how to get the subclasses method to return its unique stuff plus everything in its base class. For vanilla methods that's not a big deal, but if each is a DTMLFile, I don't think it will work. More about that at the very bottom.
* object creation form
That's much more difficult. ZMI does not reuse fragments for this case.
There is a partial solution for DTMLFiles, but it is not nice and restricted to DTML.
"DTMLFile" constructors accept a dictionary with default name bindings. This way, you can customize your DTMLFile with different bindings according to context, e.g.
addAForm= DTMLFile('dtml/addForm', globals(), comp1= AComp1 comp2= AComp2 ...) addBForm= DTMLFile('dtml/addForm', globals(), comp1= BComp1 comp2= BComp2 ...)
This suggests one semi-refined strategy: the file defines the maximal interface, and then parts of it are guarded by <dtml-if ... > tests on these extra variables I pass in. I could even pass the class in, but I suppose if I try to do issubclass(PassedInClass, MyApplicationClass) in the dtml-if I will find that I lack security to access PassedInClass, issubclass, or MyApplicationClass.
Second, I'm not sure if this is the best solution. For one thing, I would prefer to keep all my dtml in separate files, rather than defining it into my methods. You can have separate files and do something like:
class YourProduct: .... mySnippet= DTMLFile('dtml/mySnippetFile',globals()) ....
The problem comes if I stick the different interface segments in different files, so A.dtml has the user interface for A and B.dtml has just the added interface for B, a subclass of A. But I want the user interface for B to be the combination of the A and B parts.
Dieter
Ross Boylan writes:
On Thu, Jul 18, 2002 at 08:41:02PM +0200, Dieter Maurer wrote:
Ross Boylan writes:
... I would prefer a more elegant approach. Perhaps I can define some method in A that the dtml will reference, and then B can override the method to add some extra stuff (the method would return a DTML snippet). That sounds good. It is how the ZMI works...
ZMI = Zope Management Interface (i.e., in the core app), or is this something else? At any rate, I'm not sure what you're referring to, or where to look. Yes.
... The problem isn't just accessing them, but combining them. As pages are two dimensional, this is indeed not trivial.
I would expect, you have a total design with wholes (slots) that can be filled by definitions of your classes. Dieter
On Wednesday 17 Jul 2002 10:50 pm, Ross Boylan wrote:
I have a product with a number of classes that have subclasses. It seems natural to make the screens for the subclasses by extending those of the superclass. Can anyone suggest a good way to do that?
The naive approach is that I have a manage_edit_A.dtml that gives a management screen for A. If B subclasses A, I create manage_edit_B.dtml by copying from the first file and then fiddling with it. Obviously, it would be desirable for a change in A to only require changing a single file.
I would prefer a more elegant approach. Perhaps I can define some method in A that the dtml will reference, and then B can override the method to add some extra stuff
That sounds ideal.
(the method would return a DTML snippet).
Do you mean dtml or html?
First, I'm not exactly sure how to pick up the method from the DTML.
just <dtml-var my_method>
Second, I'm not sure if this is the best solution.
I cant think of anything better
For one thing, I would prefer to keep all my dtml in separate files, rather than defining it into my methods.
In your example, manage_edit_A is a method defined by dtml in a seperate file. my_method.dtml could use the same technique.
participants (4)
-
Casey Duncan -
Dieter Maurer -
Ross Boylan -
Toby Dickenson