2009-08-19 17 views
11

Ich mag eine sehr kleine Django-Anwendung in einer einzigen Datei zu schreiben, all geeigneten Module und Material erfordern, und dann in der Lage sein, dass wie ein normaler Python-Skript ausführen, wie folgt aus:Wie schreibe ich eine einzelne Django-Anwendung?

$ python myapp.py 

Sie übernehmen können Ich werde HTML nicht rendern, daher brauche ich keine Vorlagen (ich gebe JSON oder eine andere automatisch generierte Zeichenfolge zurück).

Antwort

12

Sie könnten Simon Willison Bibliothek betrachten wollen:

Vom readme:

djng ist ein Mikro-Framework, das auf einem Makro-Framework (Django) beruht.

Meine Definition eines Mikro-Rahmen: etwas, das Sie eine ganze Python Web-Anwendung in einem einzigen Modul erstellen können:

import djng 

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

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

[...] wollen

2

Dann brauchen Sie nicht Django. Was Sie brauchen, ist genau das, was micropy tut.

8

Dies ist ein einfaches CMS, das in Django als einzelne Datei implementiert ist. Es wurde von Paul Bissex geschrieben. Einige davon wurden "golfed" und könnten etwas erweitert werden, aber es ist immer noch relativ leicht zu lesen.

Die Quelle, aus seiner Pastebin verschwunden, aber ich speicherte es:

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

Sie können auch einen Blick auf web.py werfen. (Tutorial)

Es ist ein weiteres kompaktes, aber leistungsstarkes Web-Framework.

Probe von der Hauptseite:

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

Nun, der einfachste Weg, das zu tun ist, um das django Projekt arbo in einer Datei zu imitieren. Also in einem Modul, versichern Sie sich, gibt es:

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 

Dann ist Code wie ein normales Django-Projekt. Was Sie wissen müssen, ist, dass Django nichts braucht, um an einem bestimmten Ort zu sein. Standardnamen und Pfade sind im Takt, Konvention, im schlimmsten Fall Abkürzung, um zu verhindern, dass Sie eine Einstellung definieren.

Wenn Sie Django sehr gut kennen, brauchen Sie nicht einmal das Arbo nachzuahmen, schreiben Sie einfach eine Django-App, die alle Daten von den oben genannten Modulen so miteinander verbindet, wie sie sein sollten.

+0

Sie näher darauf eingehen könnte? Wie ist es möglich, Module innerhalb einer Moduldatei zu definieren? – Allanrbo

+0

@Allanrbo: Wenn Sie nach Introspektion fragen, ist Alex Martelli nie weit: http://StackOverflow.com/Questions/2315044/how-to-generate-a-module-object-from-a-code-object-in-python –

10

Erste Schritte mit Django können auch ziemlich einfach sein.Hier ist eine 10-Zeilen-Single-Datei 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)) 

Schauen Sie sich mein Blog-Post Minimal Django für weitere Einzelheiten.

+0

Danke! Genau danach habe ich gesucht, um mit Django anzufangen. Viel besser als Djangos offizielles Tutorial, meiner Meinung nach. – Nobody

2

Die meisten Django-Beispiele für einzelne Dateien, die über das Web gefunden werden, fehlen für das Modell, da django irgendwie erfordert, dass Modelle in der Datei models.py in jedem INSTALLED_APP deklariert werden. Schließlich fand ich ein Beispiel, das Unterstützung für das Modell ist: -

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

Der Link zum django Wiki bei Modellen Schöpfung auch lesenswert. Und der vollständige Code, der auch Admin gehören: -

https://gist.github.com/2219751

1

John's answer die jngo app von Paul Bissex zitiert ist beeindruckend, aber es ist leider unter Django 1.7 gebrochen.

Ich habe eine Reihe von Graben und created Django, um zu zeigen, wie Sie eine Modellklasse mit einer SQLite-Datenbank in einer einzigen Python-Datei ausführen. Ich plane, es für das Posten von Fragen über Django-Modellklassen zu verwenden. Wenn Sie einige der anderen Teile von jngo möchten, können Sie sie möglicherweise auf diese übertragen. Fahrzin Hemmati hat gepostet an example, die ähnlich scheint und enthält die vollständige Django: Webserver, Modelle, Management-Befehle. Ich habe es noch nicht ausprobiert.

# 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

mit Django Getestet 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']) 
Verwandte Themen