我的环境是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. 关于SQL Server 2017中使用json传参时解析遇到的多层解析问题

    开发新的系统,DB部分使用了SQL Server从2016版开始自带的Json解析方式. 用了快半年,在个人项目,以及公司部分项目上使用了,暂时还没遇到大的问题,和性能问题. 今天在解析Json的多级 ...

  2. Linux学习之路-2017/12/25

    三章  命令通配符 .PATH变量 支持多种文本的通配符 通配符                   含义 * 匹配零个或多个字符    ?   匹配任意单个字符 [0-9]   匹配范围内的数字 [ ...

  3. 阿里云CentOS 7服务器挂载数据盘

    本次使用的是centOS 7.4 64位操作系统 第一步:查看磁盘情况 我们发现,我总共有三个磁盘,分别为/dev/vda(100G)./dev/vdb(200G)./dev/vdc(100G),而被 ...

  4. casperjs,phantomjs,slimerjs and spooky

    1.casperjs http://casperjs.org/ CasperJS is a navigation scripting & testing utility for Phantom ...

  5. CSS控制边界、边框与外轮廓

    一.CSS控制边界 1.内边距 padding(内边距也叫内填充) padding-bottom 长度/百分比 元件下端边线的空隙 padding-left 长度/百分比 元件左端边线的空隙 padd ...

  6. 2668: [cqoi2012]交换棋子

    Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Input 第一行 ...

  7. NPOI保存到服务器和导出到客户端

    保存到服务器 <a class="easyui-linkbutton" href="javascript:void(0);" onclick=" ...

  8. kukubeadm 1.6.1 + docker1.2.6 安装问题

    kubeadm init --apiserver-advertise-address=192.168.20.229 --pod-network-cidr=10.244.0.0/16 kubelet: ...

  9. java web开发环境配置系列(二)安装tomcat

    在今天,读书有时是件“麻烦”事.它需要你付出时间,付出精力,还要付出一份心境.--仅以<java web开发环境配置系列>来祭奠那逝去的…… 1.下载tomcat压缩包,进入官网http: ...

  10. kendo ui - DatePicker 日期时间系列

    kendo-ui 官网:https://www.telerik.com/documentation 初始化 grid: 引入文件: <link rel="stylesheet" ...