只用python也可以开发时尚的网站 😎😎😎
我们用javascript编写了一个简单但高效的python运行环境,让你无须使用javascript就可以编写网页。
你也无须直接使用html和css,我们提供一个python的库,里面提供基于谷歌 material design lite (MDL http://getmdl.io) 的布局和控件类,让你简单地组合它们就可以动态地产生最时尚的网站。
我们还自带了一个网页服务器,你的网站无须安装任何python依赖就可以跑起来 😎😎😎
展示
按钮
Column(
Container(
Row(
Text(text=Icons.account_box, badge=Badge(text='1', overlap=True)),
Text(text=Icons.account_box, badge=Badge(text='♥', overlap=True)),
Text(text='Inbox', badge=Badge('4')),
Text(text='Mood', badge=Badge('♥')),
),
margin=EdgeInsets.only(top=20),
),
Text(text='This link contains a badge', href='#', badge=Badge('7')),
Row(
Text(text='This link is followed by a badge', href='#'),
Text(text='', badge=Badge('12')),
),
Text('This badge has too many characters.', href='#', badge=Badge('123456')),
Text('This badge has no background color.', href='#', badge=Badge('123', no_background=True)),
Button(Icons.add, fab=True, colored=True, action=action),
Button(Icons.add, fab=True, ripple_effect=True, colored=True),
Button(Icons.add, fab=True),
Button(Icons.add, fab=True, ripple_effect=True),
Button(Icons.add, fab=True, disabled=True),
Button('Button', raised=True),
Button('Button', raised=True, ripple_effect=True),
Button('Button', raised=True, disabled=True),
Button('Button', raised=True, colored=True),
Button(Icons.add, 'Button', raised=True, accent=True),
Button('Button', Icons.add, raised=True, accent=True, ripple_effect=True),
Button('Button'),
Button('Button', ripple_effect=True),
Button('Button', disabled=True),
Button('Button', primary=True),
Button('Button', accent=True),
Button(Icons.mood, icon=True),
Button(Icons.mood, icon=True, colored=True),
Button(Icons.mood, icon=True, accent=True),
Button(Icons.add, mini_fab=True),
Button(Icons.add, mini_fab=True, colored=True),
Chip('Basic Chip'),
Chip('Deletable Chip', close_button=True, action=action),
Chip('Button Chip', button_chip=True, action=action),
Chip('Contact Chip', contact='A'),
Chip('Deletable Contact Chip', image='dog.png', close_button=True),
)
卡片
Column(
Card(CardTitle('Update', image='dog.png', image_right=0.15),
CardText('Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenan convallis.'),
CardAction('View Updates', open_dialog1),
width=420, height=320,
color=Colors.black,
background_color=Colors.green[100],
shadow=2,
),
Card(CardTitle('Featured event:\nMay 24, 2016\n7-11pm'),
CardAction('Add To Calendar', open_dialog2, Icons.event),
width=256, height=256,
color=Colors.white,
background_color=Colors('#3E4EB8'),
shadow=2,
),
)
表格
head = ['Material','Quantity','Unit price']
data = [
['Acrylic (Transparent)', 25, '$2.90'],
['Plywood (Birch)', 50, '$1.25'],
['Laminate (Gold on Blue)', 10, '$2.35'],
]
container = Container(
Table(head, data),
padding=EdgeInsets.only(bottom=20),
)
def onchange(r,c,val1,val2):
print('Table:',r,c,val1,val2)
container.replace_child(Table(head, data))
Center(
Container(
Column(
container,
Table(head, data, editable=True, onchange=onchange),
),
padding=EdgeInsets.all(20),
bg_color=Colors.grey[100],
),
)
列表
Center(
Container(
Column(
List(
ListItem('Bryan Cranston'),
ListItem('Aaron Paul'),
ListItem('Bob Odenkirk'),
),
List(
ListItem('Bryan Cranston', icon=Icons.person),
ListItem('Aaron Paul', icon=Icons.person),
ListItem('Bob Odenkirk', icon=Icons.person),
),
List(
ListItem('Bryan Cranston', avatar=Icons.person,
action=Button(Icons.star, icon=True, primary=True)),
ListItem('Aaron Paul', avatar=Icons.person,
action=Button(Icons.star, icon=True, colored=True)),
ListItem('Bob Odenkirk', avatar=Icons.person,
action=Button(Icons.star, icon=True, accent=True)),
),
List(
ListItem('Bryan Cranston', avatar=Icons.person,
action=Checkbox(checked=True)),
ListItem('Aaron Paul', avatar=Icons.person,
action=RadioButton('item_name', checked=True)),
ListItem('Bob Odenkirk', avatar=Icons.person,
action=Switch(checked=True)),
),
List(
ListItem('Bryan Cranston', sub_title='62 Episodes', avatar=Icons.person,
action=IconToggle(Icons.star, checked=True)),
ListItem('Aaron Paul', sub_title='62 Episodes', avatar=Icons.person,
action=IconToggle(Icons.star)),
ListItem('Bob Odenkirk', sub_title='62 Episodes', avatar=Icons.person,
action=IconToggle(Icons.star)),
),
List(
ListItem('Bryan Cranston', avatar=Icons.person,
text_body='Bryan Cranston played the role of Walter in Breaking Bad. He is also known for playing Hal in Malcom in the Middle.',
action=IconToggle(Icons.star, checked=True)),
ListItem('Aaron Paul', avatar=Icons.person,
text_body='Aaron Paul played the role of Jesse in Breaking Bad. He also featured in the "Need For Speed" Movie.',
action=IconToggle(Icons.star)),
ListItem('Bob Odenkirk', avatar=Icons.person,
text_body='Bob Odinkrik played the role of Saul in Breaking Bad. Due to public fondness for the character, Bob stars in his own show now, called "Better Call Saul"',
action=IconToggle(Icons.star)),
),
),
width=600,
padding=EdgeInsets.all(20),
bg_color=Colors.grey[100],
),
)
输入控件
slider = Slider(disabled=True)
progress = Progress(disabled=True)
def slider_change(value):
slider.change(value)
progress.set_progress(value)
progress.set_buffer(100-((100-value)//2))
def check_toast(value):
print(f'value: {value}')
toast(f'value: {value}')
Tab(sections=[
Section('滑动条+进度条', Center(
Container(
Column(
slider,
Slider(value=50, onchange=slider_change),
progress,
),
width=300,
margin=EdgeInsets.all(30),
),
)),
Section('复选框', Center(
Column(
Checkbox('Disabled', disabled=True),
Checkbox('Control', onchange=check_toast),
),
)),
Section('单选按钮', Center(
Column(
RadioButton('choice-1', 'First', onchange=check_toast),
RadioButton('choice-1', 'Second', onchange=check_toast),
RadioButton('choice-1', 'Third', onchange=check_toast),
),
)),
Section('开关', Center(
Column(
Switch('First', checked=True, onchange=check_toast),
Switch('Second', onchange=check_toast),
Switch(disabled=True, onchange=check_toast),
IconToggle(Icons.format_bold, checked=True, onchange=check_toast),
IconToggle(Icons.format_italic, onchange=check_toast),
IconToggle(Icons.format_bold, disabled=True, onchange=check_toast),
),
)),
Section('文本框', Center(
Column(
Textfield('初始内容', label='文本...', onchange=check_toast),
Textfield(label='数字...', onchange=check_toast,
pattern='-?[0-9]*(\\.[0-9]+)?',
error='输入不是数字!'),
Textfield(label='文本...', onchange=check_toast,
floating_label=True),
Textfield(label='数字...', onchange=check_toast,
pattern='-?[0-9]*(\\.[0-9]+)?',
error='输入不是数字!',
floating_label=True),
Textfield(label='多行文本...', rows=3, onchange=check_toast),
Textfield(label='多行文本...', rows=1, onchange=check_toast,
floating_label=True),
Textfield(label='多行文本 (最多6行)', rows=3, maxrows=6,
onchange=check_toast),
),
)),
Section('下拉菜单', Center(
Container(
Column(
Dropdown(['Some Action','Another Action','Yet Another Action'],
onchange=check_toast,
textfield=Textfield(onchange=check_toast),
),
Dropdown(['Some Action','Another Action','Yet Another Action'],
onchange=check_toast,
),
),
),
)),
])
图标
from mdl_ import icons
import random
_icons = icons._icons
def sample_icons():
# icons1 = random.sample(_icons, 200)
icons1 = _icons
return Grid([GridCell(Button(Icon(icon), icon=True, colored=True, action=_action(icon)), col=1) for icon in icons1])
def _action(icon):
def action():
toast('Icons.'+icon)
# container.replace_child(sample_icons())
return action
container = Container(sample_icons())
主题
Themes(primary='deep_orange', accent='yellow').apply()
模版
项目内容
1. 一个简单的用js实现的python执行环境: web/lib/jswrt/py_full.js
- web/index.html
- 调用python执行环境
- 来运行主程序 web/main.py
2. 一个用python写的调用MDL的库: web/py_lib/*
3. 一个简单的http服务器,启动方法:
- 命令行 python3 -m serv
- 第一次运行的时候会下载40MB的css文件到 web/lib/mdl/css
- 为避免"删库跑路"的影响,这个项目的所有依赖都在本地
- 浏览器 http://localhost:8000
在网页上运行 Python
关于我们用js实现的python执行环境:
- 编译和运行信息会显示在浏览器的控制台
- 打开控制台的方法: 用google chrome的话可以点击:设置/更多工具/开发者工具
- 我们的简单python执行环境不包含所有python的功能
- 包含 web/lib/jswrt/ 中两个pdf中介绍的内容,带笑脸符号的部分除外
- 没有定义任何的操作符优先级
- x+y+z 必须写成 (x+y)+z
- x is not None and x>0 必须写成 (x is not None) and (x>0)
- x<y<z 必须写成 (x<y) and (y<z)
- 没有定义大部分的魔法函数,能使用
- 算数相关的魔法函数
- __init__, __repr__, __hash__, __setattr__, __getattr__
- __iter__, __next__
- __enter__, __exit__
- __setitem__, __getitem__
- 注意: 不支持 __del__
- 要了解是否支持特定功能,可以使用我们的提供的调试网页
- 命令行 python3 -m serv
- 浏览器 http://localhost:8000/web/lib/jswrt/py_full.html
如何在网页上运行的python程序
- 入口程序 web/main.py
- 当在web/main.py上import模块时,执行环境会在web/py_lib中查找
- 在这个web/main.py中,调用的是web/py_lib/mdl_test.py的run_app()
MDL 库的结构
- web/py_lib/mdl.py是如果要使用MDL的话,需要先import的模块
- mdl.py中进而import了py_lib/mdl_中定义的所有模块
- web/py_lib/mdl_test.py中演示了mdl.py中定义的所有类的用法
- web/py_lib/mdl_test_portfolio.py 重现了 https://getmdl.io/templates/portfolio/index.html 中的html+js例子
- web/py_lib/mdl_test_icons.py 被使用于 web/py_lib/mdl_test_portfolio.py
- web/py_lib/mdl_test_android.py 重现了 https://getmdl.io/templates/android-dot-com/index.html 中的html+js例子
- 上面两个模块在 mdl_test.py 中的 299-305 行中被调用