[Twisted-web] Menu flattening
Donovan Preston
twisted-web@twistedmatrix.com
Thu, 11 Dec 2003 11:53:38 -0500
--Apple-Mail-3-512621281
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
On Dec 11, 2003, at 10:35 AM, Justin Johnson wrote:
> Hi,
>
> I'm trying to write a method that creates a menu given the following
> information.
>
> menu_items = {
> "A": [ "a", "b", "c" ],
> "B": [ "d", "e", "f" ],
> "C": [ "g", "h", {"i": ["x", "y", "z"]} ],
> }
>
> This dict contains the hierarchy of menus.
First, let me start by saying that nevow is all about flexibility. You
have an implementation of a function which does exactly what you want,
except it uses string concatenation instead of stan to generate some
HTML. If it is going to be easier for you to debug and understand this
code, then by all means use it. I have shown an example of using your
string-concatenation code as a nevow renderer, by calling your code and
wrapping the output in an xml object, before returning it.
Second, stan doesn't have to be about huge python expressions. It's
just as easy to use in a standard procedural way, creating objects and
then appending them to lists. I have constructed an example of
rendering your menu structure using stan with clarity and readability
in mind.
dp
--Apple-Mail-3-512621281
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
x-unix-mode=0644;
name="nestedmenus.tac"
Content-Disposition: attachment;
filename=nestedmenus.tac
import random
from twisted.application import service, internet
from twisted.web import server
from nevow import renderer
from nevow import tags
def flatten_menu(data):
html_menu = "<ul>"
for k, v in data.items():
html_menu += "<li>%s</li>" % k
html_menu += "<ul>"
for i in v:
if isinstance(i, dict):
html_menu += flatten_menu(i)
else:
html_menu += "<li>%s</li>" % i
html_menu += "</ul>"
html_menu += "</ul>"
return html_menu
class Menus(renderer.Renderer):
document = tags.html[
tags.head[tags.title["Hello"]],
tags.body[
tags.div(style="border: 1px dotted black; margin: 1em")[
tags.ul(renderer=tags.directive("menu"))
],
tags.div(style="border: 1px dotted black; margin: 1em")[
tags.ul(renderer=tags.directive("stan_menu"))
]
]
]
def render_menu(self, context, data):
return tags.xml(flatten_menu(data))
def render_stan_menu(self, context, data):
"""Render a dictionary of string keys and list of string/dict values."""
menu = context.tag
for k, v in data.items():
# Add a list item with our key as the label
menu.children.append(tags.li[k])
# Add an ul tag to this menu for the submenu
submenu = tags.ul()
menu.children.append(submenu)
# For every element of the value list
for i in v:
# if it's a dict, cause render_stan_menu to be called on it, and the output placed in the submenu tag
if isinstance(i, dict):
submenu.children.append(tags.ul(data=i, renderer=self.render_stan_menu))
# if it's a string, just add a list item with the string to the menu
else:
submenu.children.append(tags.li[ i ])
return menu
menu_items = {
"A": ["a", "b", "c"],
"B": ["d", "e", "f"],
"C": ["g", "h", {"i":
["x", "y", "z"]
}]
}
application = service.Application("nestedmenus")
internet.TCPServer(
8080,
server.Site(
Menus(
menu_items
)
)
).setServiceParent(application)
--Apple-Mail-3-512621281--