2009-08-19 6 views
11

Voglio scrivere una piccola applicazione Django in un unico file, che richiede tutti i moduli e roba appropriate, e quindi in grado di utilizzare questo come uno script Python normale, in questo modo:Come si scrive un'applicazione Django a file singolo?

$ python myapp.py 

Si può supporre non renderò HTML, quindi non ho bisogno di modelli (tornerò JSON o qualche altra stringa generata automaticamente).

risposta

12

Si potrebbe prendere in considerazione biblioteca di Simon Willison:

Dal readme:

djng è un micro-quadro che dipende da un macro-quadro (Django).

La mia definizione di un micro-quadro: qualcosa che permette di creare un intero applicazione web Python in un unico modulo:

import djng 

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

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

[...]

2

Allora che cosa avete bisogno non è Django. Quello che vi serve è esattamente ciò che fa micropy.

8

Questo è un semplice CMS implementato in Django, come un singolo file. È stato scritto da Paul Bissex. Alcuni di essi sono stati "golfati" e potrebbero fare un po 'di espansione, ma è ancora relativamente facile da leggere.

La fonte è sparito dal suo pastebin, ma ho salvato:

#!/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

È inoltre può decidere per dare un'occhiata a web.py. (Tutorial)

È un'altra struttura web compatta ma potente.

di esempio dalla pagina principale:

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

Beh, il modo più semplice per farlo è quello di imitare l'Arbo progetto Django in un unico file. Quindi, in un modulo, assicuratevi che:

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 

Quindi il codice è come un normale progetto Django. Quello che devi sapere è che Django non ha bisogno di nulla per essere in un posto specifico. Nomi e percorsi standard sono a battuta, convenzione, nel peggiore dei casi, scorciatoia per impedirti di definire un'impostazione.

Se conosci Django molto bene, non hai nemmeno bisogno di imitare l'arbo, basta scrivere l'app django per rendere tutti i dati dei moduli sopra collegati tra loro come dovrebbero essere.

+0

Potresti elaborare su questo? Come è possibile definire i moduli all'interno di un file di modulo? – Allanrbo

+0

@Allanrbo: quando si chiede l'introspezione, alex martelli non è mai lontano: http://stackoverflow.com/questions/2315044/how-to-generate-a-module-object-from-a-code-object-in-python –

10

Iniziare con Django può essere abbastanza facile.Ecco un 10-fila indiana Django webapp:

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)) 

controllare il mio post sul blog Minimal Django per i dettagli.

+0

Grazie! Questo è esattamente quello che stavo cercando per iniziare con Django. Molto meglio del tutorial ufficiale di Django, secondo me. – Nobody

2

maggior parte degli esempi singolo file Django trovati sopra il supporto web mancanza per il modello dal Django richiedono qualche modo modelli per essere dichiarato nel file di models.py in ogni INSTALLED_APP. Finalmente ho trovato un esempio che include il supporto per il modello: -

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

Il link al wiki Django sulla creazione di modelli anche la pena di leggere. E il codice completo che includono anche admin: -

https://gist.github.com/2219751

1

John's answer citando il jngo app da Paul Bissex è impressionante, ma è purtroppo rotto sotto Django 1.7.

Ho fatto un po 'di scavo e created Django per mostrare come eseguire una classe del modello con un database SQLite in un singolo file Python. Ho intenzione di usarlo per pubblicare domande sulle classi di modelli di Django. Se vuoi alcune delle altre parti di jngo, potresti essere in grado di innestarle su questo. Fahrzin Hemmati ha pubblicato an example che sembra simile e include l'intero Django: web server, modelli, comandi di gestione. Non l'ho ancora provato.

# 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

testato con 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']) 
Problemi correlati