我的环境是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. 3D打印材料的发展现状(1)

    材料是3D打印的物质基础,也是当前制约3D打印发展的瓶颈. 3D打印材料 3D打印材料是3D打印技术发展的重要物质基础,材料的发展对于3D打印的发展有重要的作用. 目前,3D打印材料主要包括工程塑料. ...

  2. EF的连表查询Lambda表达式和linq语句

    select c; ), b=> b.Id, p=> p.BlogId, (b, p) => new {b}); public class Blog { public int Id ...

  3. 【转载】http和socket之长连接和短连接

    TCP/IP TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层. 在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议. 在传输层中有TCP协议与UDP协议. 在应 ...

  4. Linux ntpdate命令详解

    ntpdate命令用于同步更新互联网时间,或者NTP服务器时间 NTP服务器[Network Time Protocol(NTP)]是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源 ...

  5. win中使用cmd杀端口

    最近在win开发时,总是遇到端口占用的情况...可能是跑的程序太多了吧 当你测试一个demo时遇到这个就很恶心.. 记一下 netstat -ano | findstr 80 //列出进程极其占用的端 ...

  6. docker 自制alpine-lnp镜像

    简单粗暴点吧 jenkins 镜像下载:docker pull jenkins:alpine dockfile 原地址:https://gist.github.com/phith0n/373cc078 ...

  7. Java补充内容

      在第一个Java程序中已经提到一些基本的知识点,这里再补充几点. 1. 成员变量和局部变量的区别 成员变量:成员变量定义在类中,默认初始值为0,定义时可以不初始化,在整个类中可见. 局部变量:局部 ...

  8. RAID廉价磁盘冗余阵列介绍

    RAID(廉价磁盘冗余阵列)技术主要是为了改善磁盘的访问延迟,增强磁盘的可用性和容错能力.目前服务器级别的计算机都支持插入多块磁盘(8块或者更多),通过使用RAID技术,实现数据在多块磁盘上的并发读写 ...

  9. 情绪ABC理论

    美国著名心理学家阿尔伯特·艾利斯 [Albert Ellis 1913.09.27]于20世纪50年代创立, 其理论认为引起人们情绪困扰的并不是外界发生的事件,而是人们对事件的态度.看法.评价等认知内 ...

  10. springMVC參数传递

    本文是本人在学习网络视屏springMVC的过程中的学习笔记. 为了更便于理解我决定从实际使用的角度解释. 我们在浏览器输入地址 http://localhost:8080/springMVC6/us ...