我的环境是windows7 + python34 + django1.8

下面两篇文章提到了django的scaffold,感觉是一个挺不错的功能:

Django实战(3):Django也可以有scaffold

Django1.5+Python3.3下groundwork的使用

于是去Github下载了django-groundwork(居然是四年以前更新过-_-!!!),解压后复制整个django-groundwork文件夹到当前项目文件夹下。

再设置settings.py:

INSTALLED_APPS = (
# ...
'django-groundwork',
)

然后运行:

$ python manage.py groundwork depot Product

出现了如下错误:

E:\workspace\depot>python manage.py groundwork depotapp Product
usage: manage.py groundwork [-h] [--version] [-v {0,1,2,3}]
[--settings SETTINGS] [--pythonpath PYTHON
[--traceback] [--no-color]
manage.py groundwork: error: unrecognized arguments: depotapp Product

查看django官方文档,发现django1.8的manage.py的命令行参数解析模块已经由optparse换成了argparse

所以,四年前写的groundwork自然是不能运行了。好吧,自己动手,丰衣足食。

我把里面的两个文件做了必要的修改:

# -------------------- #
# project/urls.py file section #
# -------------------- # PROJECT_URL_CONFIG = """
"\nurlpatterns += [url(r'^%(app)s/', include('%(app)s.urls', namespace='%(app)s')),\n]\n"
""" # -------------------- #
# urls.py file section #
# -------------------- # URL_IMPORTS = """
from django.conf.urls import url
from .models import *
from .views import * urlpatterns =[
""" URL_CRUD_CONFIG = """
url(r'^%(model)s/create/$', create_%(model)s, name='create_%(model)s'),
url(r'^%(model)s/list/$', list_%(model)s, name='list_%(model)s'),
url(r'^%(model)s/edit/(?P<id>[^/]+)/$', edit_%(model)s, name='edit_%(model)s'),
url(r'^%(model)s/view/(?P<id>[^/]+)/$', view_%(model)s, name='view_%(model)s'),
""" URL_END = """
]
""" # --------------------- #
# forms.py file section #
# --------------------- # FORMS_IMPORTS = """
from django import forms
from .models import * """ FORMS_MODELFORM_CONFIG = """ class %(modelClass)sForm(forms.ModelForm): class Meta:
model = %(modelClass)s
exclude = [] # uncomment this line and specify any field to exclude it from the form def __init__(self, *args, **kwargs):
super(%(modelClass)sForm, self).__init__(*args, **kwargs) """ # --------------------- #
# views.py file section #
# --------------------- # VIEWS_IMPORTS = """
# Create your views here. from django import forms
from django.template import RequestContext
from django.http import HttpResponse, HttpResponseRedirect
from django.template.loader import get_template
from django.core.paginator import Paginator
from django.core.urlresolvers import reverse # app specific files from .models import *
from .forms import *
""" VIEWS_CREATE = """ def create_%(model)s(request):
form = %(modelClass)sForm(request.POST or None)
if form.is_valid():
form.save()
form = %(modelClass)sForm() t = get_template('%(app)s/create_%(model)s.html')
c = RequestContext(request,locals())
return HttpResponse(t.render(c)) """ VIEWS_LIST = """ def list_%(model)s(request): list_items = %(modelClass)s.objects.all()
paginator = Paginator(list_items ,10) try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1 try:
list_items = paginator.page(page)
except :
list_items = paginator.page(paginator.num_pages) t = get_template('%(app)s/list_%(model)s.html')
c = RequestContext(request,locals())
return HttpResponse(t.render(c)) """ VIEWS_UPDATE = """
def edit_%(model)s(request, id): %(model)s_instance = %(modelClass)s.objects.get(id=id) form = %(modelClass)sForm(request.POST or None, instance = %(model)s_instance) if form.is_valid():
form.save() t=get_template('%(app)s/edit_%(model)s.html')
c=RequestContext(request,locals())
return HttpResponse(t.render(c))
""" VIEWS_VIEW = """ def view_%(model)s(request, id):
%(model)s_instance = %(modelClass)s.objects.get(id = id) t=get_template('%(app)s/view_%(model)s.html')
c=RequestContext(request,locals())
return HttpResponse(t.render(c))
""" # ------------------------- #
# templates.py file section #
# ------------------------- # TEMPLATES_CREATE = """
{%% extends "base.html" %%} {%% block title %%} %(modelClass)s - Create {%% endblock %%} {%% block heading %%}<h1> %(modelClass)s - Create </h1> {%% endblock %%} {%% block content %%}
<table>
<form action="" method="POST"> {%% csrf_token %%}
{{form}}
<tr>
<td colspan="2" align="right"><input type="submit" value="Create"/></td>
</tr>
</form>
</table>
{%% endblock %%}
""" TEMPLATES_LIST = """
{%% extends "base.html" %%} {%% block title %%} %(modelClass)s -- List {%% endblock %%} {%% block heading %%}
<h1> %(modelClass)s</h1>
<h2> List Records</h2>
{%% endblock %%}
{%% block content %%} <table>
<thead>
<tr><th>Record</th><th colspan="3">Actions</th></tr>
{%% for item in list_items.object_list %%}
<tr><td> {{item}}</td> <td><a href="{%% url '%(app)s:view_%(model)s' item.id %%}">Show</a> </td> <td><a href="{%% url '%(app)s:edit_%(model)s' item.id %%}">Edit</a></tr>
{%% endfor %%}
<tr><td colspan="3"> <a href="{%% url '%(app)s:create_%(model)s' %%}">Add New</a></td></tr>
</table> <div align="center">
{%% if list_items.has_previous %%}
<a href="?page={{ list_items.previous_page_number }}">Previous</a>
{%% endif %%} <span class="current">
Page {{ list_items.number }} of {{ list_items.paginator.num_pages }}.
</span> {%% if list_items.has_next %%}
<a href="?page={{ list_items.next_page_number }}">Next</a>
{%% endif %%} </div>
{%% endblock %%}
""" TEMPLATES_EDIT = """
{%% extends "base.html" %%} {%% block title %%} %(modelClass)s - Edit {%% endblock %%} {%% block heading %%} <h1> %(modelClass)s</h1><h2> Edit </h2> {%% endblock %%}
{%% block content %%}
<table>
<form action="" method="POST"> {%% csrf_token %%}
{{form}}
<tr>
<td colspan="2" align="right"><input type="submit" value="Save"/></td>
</tr>
</form>
</table>
{%% endblock %%}
""" TEMPLATES_VIEW = """
{%% extends "base.html" %%} {%% block title %%} %(modelClass)s - View {%% endblock %%} {%% block heading %%} <h1> %(modelClass)s</h1><h2>View</h2> {%% endblock %%}
{%% block content %%}
<table>
{{ %(model)s_instance }}
</table>
{%% endblock %%}
""" TEMPLATES_BASE = """
<!DOCTYPE html>
<html>
<head>
<meta charset=UTF-8"/>
<meta name="description" content=""/>
<meta name="keywords" content="" />
<meta name="author" content="" />
<title>
{% block title %} {% endblock %}
</title>
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
body * * { padding:0; }
body { font:small sans-serif; }
body>div { border-bottom:1px solid #ddd; }
h1 { font-weight:normal; }
h2 { margin-bottom:.8em; }
h2 span { font-size:80% ; color:#666; font-weight:normal; }
h3 { margin:1em 0 .5em 0; }
h4 { margin:0 0 .5em 0; font-weight: normal; }
td {font-size:1em; padding:3px 17px 2px 17px;}
ul { margin-left: 2em; margin-top: 1em; }
#summary { background: #e0ebff; }
#summary h2 { font-weight: normal; color: #666; }
#explanation { background:#eee; }
#content { background:#f6f6f6; }
#summary table { border:none; background:transparent; }
</style>
</head>
<body> <div id="summary">
{% block heading %}
{% endblock %}
</div> <div id="content">
{% block content %} {% endblock %}
</div> <div id="explanation" align="center">
django-groundwork
</div> </body>
</html>
"""

placeholder.py

from django.core.management.base import BaseCommand, CommandError
from django.db import models
from .placeholders import *
import os class Command(BaseCommand):
help = "Usage : manage.py groundwork <app> <model>" def add_arguments(self, parser):
parser.add_argument('app', nargs='+', type=str)
parser.add_argument('model', nargs='+', type=str) def handle(self, *args, **options):
"Usage : manage.py groundwork <app> <model>" app = options['app'][0] model_names = options['model'] PROJECT_ROOT = os.getcwd()
PROJECT_NAME = os.path.basename(PROJECT_ROOT)
TEMPLATE_DIR = os.path.join(PROJECT_ROOT , app, 'templates') model_instances = [ models.get_model(app, x) for x in model_names ] # url config
urls = URL_IMPORTS # Generate CRUD urls for each model
for model_instance in model_instances:
urls += URL_CRUD_CONFIG % {'model':model_instance._meta.object_name.lower(), 'modelClass': model_instance._meta.object_name } urls += URL_END # write to urls.py
f = open( os.path.join (PROJECT_ROOT , app, 'urls.py') , 'w')
f.write(urls)
f.close() # append to root urlconf
f = open( os.path.join(PROJECT_ROOT, PROJECT_NAME, 'urls.py'), 'a')
f.write( PROJECT_URL_CONFIG % {'app': app } )
f.close() # forms
forms_content = FORMS_IMPORTS
for model_instance in model_instances:
forms_content += FORMS_MODELFORM_CONFIG % { 'modelClass' : model_instance._meta.object_name } formspath = os.path.join (PROJECT_ROOT, app, 'forms.py')
f = open( formspath , 'w')
f.write(forms_content)
f.close() # views
views_content = VIEWS_IMPORTS for model_instance in model_instances:
views_content += VIEWS_CREATE
views_content += VIEWS_LIST
views_content += VIEWS_VIEW
views_content += VIEWS_UPDATE views_content = views_content % {'model':model_instance._meta.object_name.lower(), 'modelClass': model_instance._meta.object_name, 'app': app } # write to views.py
viewspath = os.path.join (PROJECT_ROOT, app, 'views.py')
f = open( viewspath, 'w')
f.write(views_content)
f.close() # Templates template_dir = os.path.join(TEMPLATE_DIR, app )
if not os.path.exists(template_dir):
os.makedirs(template_dir) self.stdout.write("Generate base template? [Y/N]?")
yn = input()
if yn.lower() == 'y':
f = open(os.path.join(TEMPLATE_DIR, 'base.html') , 'w')
f.write(TEMPLATES_BASE)
f.close() for model_instance in model_instances:
f = open(os.path.join( TEMPLATE_DIR, app, 'create_%s.html' % (model_instance._meta.object_name.lower()) ) ,'w')
f.write( TEMPLATES_CREATE % { 'modelClass' : model_instance._meta.object_name } )
f.close() f = open(os.path.join( TEMPLATE_DIR, app, 'list_%s.html' % (model_instance._meta.object_name.lower()) ) ,'w')
f.write( TEMPLATES_LIST % { 'modelClass' : model_instance._meta.object_name ,'model' : model_instance._meta.object_name.lower(), 'app' : app} )
f.close() f = open(os.path.join( TEMPLATE_DIR, app, 'edit_%s.html' % (model_instance._meta.object_name.lower()) ) ,'w')
f.write( TEMPLATES_EDIT % { 'modelClass' : model_instance._meta.object_name } )
f.close() f = open(os.path.join( TEMPLATE_DIR, app, 'view_%s.html' % (model_instance._meta.object_name.lower()) ) , 'w')
f.write( TEMPLATES_VIEW % { 'modelClass' : model_instance._meta.object_name, 'model' : model_instance._meta.object_name.lower()} )
f.close()

groundwork.py

保存,然后运行:

$ python manage.py groundwork depot Product

不用再做任何修改,操作。启动服务器:

$ python manage.py runserver

在浏览器地址栏输入:

localhost:8000/depot/product/list

您会看到如下效果图:

点击 Add New,进入create页面

最后为了方便大家使用,我Fork了原来的django-groundwork到我的Github,并做了相应的修改。祝使用愉快!

django-groundwork的更多相关文章

  1. Django实战(3):Django也可以有scaffold

    rails有一个无用的”神奇“功能,叫做scaffold.能够在model基础上,自动生成CRUD的界面. 说它无用,是因为rails的开发者David说,scaffold”不是应用程序开发的目的.它 ...

  2. django中根据模型生成页面的脚手架app-groundwork

    相信做过Asp.net MVC的朋友对在此框架下,根据模型自动生成浏览,编辑,查看,删除的四个页面的脚手架功能记忆尤新,那么我们在用python中的django框架时,有没有此脚手架功能呢,很显然,默 ...

  3. 异步任务队列Celery在Django中的使用

    前段时间在Django Web平台开发中,碰到一些请求执行的任务时间较长(几分钟),为了加快用户的响应时间,因此决定采用异步任务的方式在后台执行这些任务.在同事的指引下接触了Celery这个异步任务队 ...

  4. 《Django By Example》第四章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:祝大家新年快乐,这次带来<D ...

  5. django server之间通过remote user 相互调用

    首先,场景是这样的:存在两个django web应用,并且两个应用存在一定的联系.某些情况下彼此需要获取对方的数据. 但是我们的应用肯经都会有对应的鉴权机制.不会让人家随随便便就访问的对吧.好比上车要 ...

  6. Mysql事务探索及其在Django中的实践(二)

    继上一篇<Mysql事务探索及其在Django中的实践(一)>交代完问题的背景和Mysql事务基础后,这一篇主要想介绍一下事务在Django中的使用以及实际应用给我们带来的效率提升. 首先 ...

  7. Mysql事务探索及其在Django中的实践(一)

    前言 很早就有想开始写博客的想法,一方面是对自己近期所学知识的一些总结.沉淀,方便以后对过去的知识进行梳理.追溯,一方面也希望能通过博客来认识更多相同技术圈的朋友.所幸近期通过了博客园的申请,那么今天 ...

  8. 《Django By Example》第三章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:第三章滚烫出炉,大家请不要吐槽文中 ...

  9. 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...

  10. 《Django By Example》第一章 中文 翻译 (个人学习,渣翻)

    书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:本人目前在杭州某家互联网公司工作, ...

随机推荐

  1. 百度开源的分布式 id 生成器

    UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器.UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于d ...

  2. Jmeter入门--性能测试实战

    测试需求:测试20个用户访问https://www.baidu.com在负载达到30QPS时的平均响应时间. QPS:QueryperSecond,每秒查询率.一台查询服务器每秒能够处理的查询次数.在 ...

  3. [UI] 精美UI界面欣赏[3]

    精美UI界面欣赏[3]

  4. Linux优化远程SSH连接

    优化远程SSH连接 1.Linxu和Window的ssh连接区别 Windom默认3389端口,管理员administartor 普通是guest Linux 默认22端口 管理员root 普通一堆 ...

  5. Spring Boot Mybatis-Plus

    Mybatis-Plus 是对 Mybatis-Plus 的一些扩充. 在 Spring Boot 中进行集成的时候其实基本上和 mybatis 是一致的. 在你的配置文件中.配置 你的 entity ...

  6. 026.2 网络编程 UDP聊天

    实现,通过socket对象 ##############################################################需求建立UDP发送端:###思路:1.建立可以实 ...

  7. Java8新特性 -- Lambda基础语法

    Lambda 表达式的基础语法: Java8引入了一个新的操作符 “->”  该操作符称为箭头操作符或Lambda操作符, 该操作符将Lambda表达式拆分为两部分: 左侧: Lambda表达式 ...

  8. 整合Yolov3到游戏引擎

    这篇其实是前文 CUDA版Grabcut的实现 的后续,和上文一样,先放视频. (博客园好像不支持视频,gif文件太大,视频链接) 在上文用CUDA实现opencv下的grabcut后,当时问题主要是 ...

  9. Yii设置Cache缓存的方法

    先在配置文件components数组中加上: 'cache'=>array( 'class'=>'CFileCache'), 设置Cache: Yii::app()->cache-& ...

  10. js之点击值发生变化

    点击值发生变化,应用场景,比如像阿里云那样我通常密码是以******的形式存在,我必须要点击查看,它才会以明文显示. 在实际开发中,比如以智能门锁为例,安装门锁时,有个叫密码输入框的表单,这个是选填项 ...