2009-08-19 56 views
11

我想要寫在一個文件中一個非常小的Django應用程序,要求所有適當的模塊之類的東西,然後就可以運行,作爲一個普通的Python腳本,像這樣:如何編寫單個文件的Django應用程序?

$ python myapp.py 

你可以假設我不會呈現HTML,所以我不需要模板(我會返回JSON或其他一些自動生成的字符串)。

回答

12

你可能要考慮西蒙·威利森的圖書館:

readme

djng是一個依賴宏框架(Django)的微框架。

我的微架構的定義是:你可以將其在單一模塊中創建一個完整的 Python的Web應用程序:

import djng 

def index(request): 
    return djng.Response('Hello, world') 

if __name__ == '__main__': 
    djng.serve(index, '0.0.0.0', 8888) 

[...]

2

那麼你需要的是不是Django的。 你需要的是micropy

8

這是一個簡單的CMS在Django實施,作爲一個單一的文件。它是由Paul Bissex寫的。其中一些已經「打高爾夫球」,可以做一些擴展,但它仍然相對容易閱讀。

源已經從他的引擎收錄消失了,但是我救了它:

#!/usr/bin/env python 
""" 
jngo -- The unhealthily compressed Django application. 

Usage: ./jngo.py 

Assuming a working install of Django (http://djangoproject.com/) and SQLite 
(http://sqlite.org), this script can be executed directly without any other 
preparations -- you don't have to do `setup.py install`, it doesn't 
need to be on your Python path, you don't need to set DJANGO_SETTINGS_MODULE, 
you don't need a webserver. You don't even need content -- the first time it's 
run, it will create a SQLite database in the same directory as the script 
and populate it with sample pages. 

Features: 

* Editable content on all pages 
* Dynamically generated navigation buttons 
* Optional private-access pages 
* Optional per-page comments 
* RSS feed of latest comments, with autodiscovery 

Author: Paul Bissex <[email protected]> 
URL: http://news.e-scribe.com/ 
License: MIT 

FAQS: 

Q: Should I use this as an example of excellent Django coding practices? 
A: Um, no. This is pretty much the opposite of excellent Django coding practices. 

Q: Why did you do such a terrible thing? 
A: At first, it was just a perverse experiment. It ended up being a 
good way to refresh my memory on some Django internals, by trying all 
kinds of things that broke in weird ways. 
""" 

#--- Settings --- 
NAME = ROOT_URLCONF = "jngo" 
DEBUG = TEMPLATE_DEBUG = True 
SITE_ID = 3000 
HOSTNAME_AND_PORT = "127.0.0.1:8000" 
DATABASE_ENGINE = "sqlite3" 
DATABASE_NAME = NAME + ".db" 
INSTALLED_APPS = ["django.contrib.%s" % app for app in "auth admin contenttypes sessions sites flatpages comments".split()] 
TEMPLATE_LOADERS = ('django.template.loaders.app_directories.load_template_source', NAME + '.template_loader') 
MIDDLEWARE_CLASSES = ('django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 
'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware') 
TEMPLATE_CONTEXT_PROCESSORS = (NAME + '.context_processor', "django.core.context_processors.auth", "django.core.context_processors.request") 

#--- Template loader and templates --- 
def template_loader(t, _): 
    from django.template import TemplateDoesNotExist 
    try: 
     return { 
      'base.html': """<html><head><title>{{ flatpage.title }}</title><link rel='alternate' type='application/rss+xml' href='/feed/'><style type="text/css">body { margin: 15px 50px; background: #eee; color: #343; font-family: sans-serif; } ul { padding: 0; } li { display: inline; background: #383; padding: 4px 8px; margin: 3px; } li:hover { background: #252; } dd { border-bottom: 1px dotted #666; } a { color: #383; text-decoration: none; } li a { color: #fff; } .anav { background: #141; } .rnav a { color: #ff4; } .error { color: #e22; } #footer { border-top: 1px dotted #555; font-size: 80%; color: #555; margin-top: 15px } #comments { background: #ddd; margin-top: 20px; padding: 10px; } dt { font-weight: bold; margin-top: 1em; }</style></head><body><ul>{% for nav in navs %}<li class="{% ifequal nav.url flatpage.url %}anav {% endifequal %}{% if nav.registration_required %}rnav {% endif %}"><a href="{{ nav.url }}">{{ nav.title }}</a></li>{% endfor %}</ul>{% block content %}{% endblock %}<div id="footer">{% if request.user.is_staff %}<a href="javascript:(function(){if(typeof%20ActiveXObject!='undefined'){var%20x=new%20ActiveXObject('Microsoft.XMLHTTP')}else%20if(typeof%20XMLHttpRequest!='undefined'){var%20x=new%20XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{var%20type=x.getResponseHeader('x-object-type');var%20id=x.getResponseHeader('x-object-id');}catch(e){return;}document.location='/admin/'+type.split('.').join('/')+'/'+id+'/';})()">Edit this page</a> (as staff user <a href="/admin/">{{ request.user }}</a>)<br>{% endif %}Powered by <a href="http://djangoproject.com/">Django</a> {{ version }}<br></div></body></html>""", 
      'flatpages/default.html': """{% extends "base.html" %}{% load comments %}{% block content %}<h1>{{ flatpage.title }}</h1>{{ flatpage.content }}{% if flatpage.enable_comments %}<div id="comments">{% get_free_comment_list for flatpages.flatpage flatpage.id as comments %}<h3>Comments!</h3><dl>{% for comment in comments %}{% include "comment.html" %}{% endfor %}</dl>{% free_comment_form for flatpages.flatpage flatpage.id %}</div>{% endif %}{% endblock %}""", 
      'comments/free_preview.html': """{% extends "base.html" %}{% block content %}<h1>Comment preview</h1><dl>{% include "comment.html" %}</dl><form action='.' method='post'><input type='hidden' name='gonzo' value='{{ hash }}'><input type='hidden' name='options' value='{{ options }}'><input type='hidden' name='comment' value='{{ comment.comment }}'><input type='hidden' name='person_name' value='{{ comment.person_name }}'><input type='hidden' name='target' value='{{ target }}'><input type='submit' name='post' value='Post comment'></form>{% endblock %}""", 
      'comments/posted.html': """{% extends "base.html" %}{% block content %}<h1>Comment posted</h1><p>Thanks for posting!</p> <p><a href='{{ object.get_absolute_url }}'>Continue</a></p>{% endblock %}""", 
      'comment.html': """<dt>{{ comment.person_name }} said:</dt> <dd>{{ comment.comment }}</dd>""", 
      'registration/login.html': """{% extends "base.html" %}{% block content %}{% if form.has_errors %}<h2 class="error">Wrong!</h2>{% endif %}<p>This page is top secret, so you need to log in.</p><form method="post" action=".">Username: {{ form.username }}<br>Password: {{ form.password }}<br><input type="submit" value="login"><input type="hidden" name="next" value="{{ next }}"></form>{% endblock %}""" 
      }[t], '' 
    except KeyError: 
     raise TemplateDoesNotExist 
template_loader.is_usable = True 

#--- Context processor --- 
def context_processor(request): 
    from django.contrib.flatpages.models import FlatPage 
    navs = FlatPage.objects.all().values("url", "title", "registration_required") 
    from django import get_version 
    return { 'navs': navs, 'version': get_version() } 

#--- RSS Feed (hacky wrapper function needed because of jngo's one-file setup) --- 
def feed(*args, **kwargs): 
    from django.contrib.comments.feeds import LatestFreeCommentsFeed 
    return LatestFreeCommentsFeed(*args, **kwargs) 

#--- URLconf --- 
from django.conf.urls.defaults import * 
urlpatterns = patterns("", 
    (r"^admin/", include("django.contrib.admin.urls")), 
    (r"^comments/", include("django.contrib.comments.urls.comments")), 
    (r"^accounts/login/$", "django.contrib.auth.views.login"), 
    (r"^(feed)/$", "django.contrib.syndication.views.feed", {'feed_dict': {'feed': feed}}), 
    ) 

#--- Execution --- 
if __name__ == "__main__": 
    import os, sys 
    from django.core.management import call_command 
    here = os.path.dirname(__file__) 
    sys.path.append(here) 
    os.environ["DJANGO_SETTINGS_MODULE"] = NAME 
    if not os.path.isfile(os.path.join(here, DATABASE_NAME)): 
     from django.contrib.auth.create_superuser import createsuperuser 
     from django.contrib.flatpages.models import FlatPage 
     from django.contrib.sites.models import Site 
     call_command("syncdb") 
     createsuperuser() 
     site_obj = Site.objects.create(id=SITE_ID, domain=HOSTNAME_AND_PORT) 
     FlatPage.objects.create(url="/", title="Home", content="Welcome to %s!" % NAME).sites.add(site_obj) 
     FlatPage.objects.create(url="/stuff/", enable_comments=True, title="Stuff", content="This is a page about stuff.").sites.add(site_obj) 
     FlatPage.objects.create(url="/topsecret/", title="Top Secret", content="Now you know.", registration_required=True).sites.add(site_obj) 
    call_command("runserver", HOSTNAME_AND_PORT) 
0

您可能還需要看看web.py。 (Tutorial

這是另一種結構緊湊,但功能強大的Web框架。從主網頁

樣品:

import web 

urls = ('/(.*)', 'hello') 
app = web.application(urls, globals()) 

class hello:   
    def GET(self, name): 
     if not name: 
      name = 'world' 
     return 'Hello, ' + name + '!' 

if __name__ == "__main__": 
    app.run() 
1

好,要做到這一點最簡單的方法就是模仿Django項目ARBO在一個文件中。因此,在一個模塊中,保證有:

Root_module : 
    Root_module.settings 
    Root_module.urls 
    Root_module.app_in_the_module 
    Root_module.app_in_the_module.models 
    Root_module.app_in_the_module.views 

然後碼作爲普通的Django項目。你必須知道的是,Django不需要任何東西在某個特定的地方。標準名稱和路徑處於節拍,慣例,最壞的情況下,以防止您定義設置。

如果你知道Django的非常好,你甚至不需要模仿ARBO,只寫你Django應用程序使所有從上面的模塊的數據互連,那麼它們應該是這樣。

+0

測試你能細說了?如何在模塊文件中定義模塊? – Allanrbo 2012-04-30 23:37:34

+0

@Allanrbo:當要求反思時,alex martelli永遠不會:http://stackoverflow.com/questions/2315044/how-to-generate-a-module-object-from-a-code-object-in-python – 2012-05-01 05:48:45

10

開始使用Django的可以很容易的事。這是一張10行單文件Django的web應用程序:

import os 
from django.conf.urls.defaults import patterns 
from django.http import HttpResponse 
filepath, extension = os.path.splitext(__file__) 
ROOT_URLCONF = os.path.basename(filepath) 

def yoohoo(request): 
    return HttpResponse('Yoohoo!') 

urlpatterns = patterns('', (r'^hello/$', yoohoo)) 

看看我的博客文章Minimal Django瞭解詳情。

+0

謝謝!這正是我想要開始使用Django的原因。在我看來,比Django的官方教程要好得多。 – Nobody 2016-10-24 17:28:27

2

大多數通過網絡找到的單個文件django示例缺乏對模型的支持,因爲django以某種方式需要在models.py文件中聲明每個INSTALLED_APP中的模型。最後,我找到了一個例子,包括對模型的支持: -

http://fahhem.com/blog/2011/10/django-models-without-apps-or-everything-django-truly-in-a-single-file/

到Django的維基鏈接模型創作也值得一讀。而完整的代碼其中也包括管理: -

https://gist.github.com/2219751

1

John's answer引述jngo app保羅Bissex令人印象深刻,但它的Django 1.7下黯然破碎。

我做了一堆挖掘和created Django來展示如何在一個Python文件SQLite數據庫運行模型類。我打算用它發佈有關Django模型類的問題。如果你想要jngo的其他部分,你可以將它們移植到它上面。 Fahrzin Hemmati發佈了an example,看起來很相似,幷包含完整的Django:web服務器,模型,管理命令。我還沒有嘗試過。

# Tested with Django 1.9.2 
import sys 

import django 
from django.apps import apps 
from django.apps.config import AppConfig 
from django.conf import settings 
from django.db import connections, models, DEFAULT_DB_ALIAS 
from django.db.models.base import ModelBase 

NAME = 'udjango' 


def main(): 
    setup() 

    class Person(models.Model): 
     first_name = models.CharField(max_length=30) 
     last_name = models.CharField(max_length=30) 

    syncdb(Person) 

    p1 = Person(first_name='Jimmy', last_name='Jones') 
    p1.save() 
    p2 = Person(first_name='Bob', last_name='Brown') 
    p2.save() 

    print ', '.join([p.first_name for p in Person.objects.all()]) 


def setup(): 
    DB_FILE = NAME + '.db' 
    with open(DB_FILE, 'w'): 
     pass # wipe the database 
    settings.configure(
     DEBUG=True, 
     DATABASES={ 
      DEFAULT_DB_ALIAS: { 
       'ENGINE': 'django.db.backends.sqlite3', 
       'NAME': DB_FILE}}, 
     LOGGING={'version': 1, 
       'disable_existing_loggers': False, 
       'formatters': { 
        'debug': { 
         'format': '%(asctime)s[%(levelname)s]' 
            '%(name)s.%(funcName)s(): %(message)s', 
         'datefmt': '%Y-%m-%d %H:%M:%S'}}, 
       'handlers': { 
        'console': { 
         'level': 'DEBUG', 
         'class': 'logging.StreamHandler', 
         'formatter': 'debug'}}, 
       'root': { 
        'handlers': ['console'], 
        'level': 'WARN'}, 
       'loggers': { 
        "django.db": {"level": "WARN"}}}) 
    app_config = AppConfig(NAME, sys.modules['__main__']) 
    apps.populate([app_config]) 
    django.setup() 
    original_new_func = ModelBase.__new__ 

    @staticmethod 
    def patched_new(cls, name, bases, attrs): 
     if 'Meta' not in attrs: 
      class Meta: 
       app_label = NAME 
      attrs['Meta'] = Meta 
     return original_new_func(cls, name, bases, attrs) 
    ModelBase.__new__ = patched_new 


def syncdb(model): 
    """ Standard syncdb expects models to be in reliable locations. 

    Based on https://github.com/django/django/blob/1.9.3 
    /django/core/management/commands/migrate.py#L285 
    """ 
    connection = connections[DEFAULT_DB_ALIAS] 
    with connection.schema_editor() as editor: 
     editor.create_model(model) 

main() 
3

使用Django 1.7

#!/usr/bin/env python 
import os 
import sys 
from django.conf import settings 
from django.conf.urls import patterns, include, url 
from django.http import HttpResponse 

filename = os.path.splitext(os.path.basename(__file__))[0] 

urlpatterns = patterns('', 
    url(r'^$', '%s.home' % filename, name='home'), 
) 

def home(request): 
    return HttpResponse('hello') 

if __name__ == "__main__": 
    settings.configure(
     DEBUG=True, 
     MIDDLEWARE_CLASSES = [], 
     ROOT_URLCONF = filename 
    ) 

    from django.core.management import execute_from_command_line 
    execute_from_command_line([sys.argv[0], 'runserver'])