我的环境是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. [WSUS] [Windows 10 Upgrade 1607/1703] 升级出错,出现 0xC1800118 或者卡在下载中…… 0%后失败

    1. 安装 KB3159706 ,并进行安装后维护操作:https://support.microsoft.com/en-us/help/3159706/update-enables-esd-decr ...

  2. [翻译] M13ProgressSuite

    M13ProgressSuite https://github.com/Marxon13/M13ProgressSuite A set of classes used to display progr ...

  3. 使用SDWebImage淡入淡出的方式加载图片

    使用SDWebImage淡入淡出的方式加载图片 效果: 请通过以下方式下载源码: 找到它修改文件的地方: 以下是使用源码: // // ViewController.m // SDWebImageFa ...

  4. U-Mail详解邮件营销优势及应用领域

    最近频频有营销人员向U-Mail小编咨询:邮件营销到底有什么好处呢?与此同时,还有不少人对邮件营销存在一定的误解:邮件营销是不是只给潜在消费者发送邮件推广商品呢?其实邮件群发的应用面非常广泛,可不仅仅 ...

  5. U-Mail:多方面因素避免EDM邮件进垃圾箱

    有很多做邮件营销的企业客户给U-Mail来电或来函咨询一件困扰他们的事:群发邮件时,要怎么样才能降低被收件人列入垃圾邮件的概率呢?其实关于这个问题,U-Mail小编已经请资深营销专家解答过多次了,经常 ...

  6. redis开启远程连接访问和需要密码的方法

    redis默认是不能远程访问的,如果希望多台机子共用redis数据库,那就需要开启redis远程连接访问.既然可以远程连接了,那就需要密码登陆,否则不安全.下面是具体的方法,按照步骤一步一步来就OK了 ...

  7. Android 高级UI设计笔记24:Android 夜间模式之 WebView 实现白天 / 夜间阅读模式 (使用JavaScript)

    1. 问题引入: 前面我们是使用方法 降低屏幕亮度(不常用) 和 替换theme,两者都是针对Activity的背景进行白天.夜间模式的交换,但是如果我们显示的是Html的内容,这个时候改怎么办? 分 ...

  8. PHPExcel 导入

    首先: //包含excel的类库require APPPATH . 'third_party/PHPExcel.php';require APPPATH . 'third_party/PHPExcel ...

  9. BZOJ4571:[SCOI2016]美味(主席树,贪心)

    Description 一家餐厅有 n 道菜,编号 1...n ,大家对第 i 道菜的评价值为 ai(1≤i≤n).有 m 位顾客,第 i 位顾客的期望值为 bi,而他的偏好值为 xi . 因此,第 ...

  10. Python学习之路 (三)爬虫(二)

    通用爬虫和聚焦爬虫 根据使用场景,网络爬虫可分为 通用爬虫 和 聚焦爬虫 两种. 通用爬虫 通用网络爬虫 是 捜索引擎抓取系统(Baidu.Google.Yahoo等)的重要组成部分.主要目的是将互联 ...