2009-08-19 18 views
11

Tôi muốn viết một ứng dụng Django rất nhỏ trong một tập tin duy nhất, yêu cầu tất cả các module thích hợp và các công cụ, và sau đó có thể chạy mà như một kịch bản Python bình thường, như thế này:Làm cách nào để viết một ứng dụng Django một tệp?

$ python myapp.py 

Bạn có thể giả định Tôi sẽ không hiển thị HTML, vì vậy tôi không cần mẫu (tôi sẽ trả lại JSON hoặc một số chuỗi được tạo tự động khác).

Trả lời

12

Bạn có thể muốn xem xét thư viện Simon Willison của:

Từ readme:

djng là một khung vi mô phụ thuộc vào một khung công tác vĩ mô (Django).

định nghĩa của tôi về một khuôn khổ-vi: một cái gì đó cho phép bạn tạo một toàn bộ ứng dụng web Python trong một mô-đun duy nhất:

import djng 

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

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

[...]

2

Sau đó, những gì bạn cần không phải là Django. Những gì bạn cần là chính xác những gì micropy làm.

8

Đây là một CMS đơn giản được triển khai ở Django, dưới dạng một tệp. Nó được viết bởi Paul Bissex. Một số đã được "chơi golf" và có thể làm với một chút mở rộng, nhưng nó vẫn tương đối dễ đọc.

Nguồn đã biến mất khỏi pastebin của mình, nhưng tôi lưu nó:

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

Bạn cũng có thể muốn để xem web.py. (Tutorial)

Đó là một khung công tác web nhỏ gọn nhưng mạnh mẽ khác.

mẫu từ trang chính:

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

Vâng, cách dễ nhất để làm điều đó là để bắt chước Arbo dự án django trong một tập tin. Vì vậy, trong một mô-đun, hãy đảm bảo có:

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 

Sau đó, mã là một dự án Django bình thường. Những gì bạn phải biết là Django không cần bất cứ điều gì để được ở một nơi cụ thể. Tiêu chuẩn tên và đường dẫn đang ở đánh bại, quy ước, tồi tệ nhất, phím tắt để ngăn chặn bạn xác định một thiết lập.

Nếu bạn biết Django rất tốt, bạn thậm chí không cần phải bắt chước arbo, chỉ cần viết bạn django ứng dụng làm cho tất cả các dữ liệu từ các mô-đun trên kết nối với nhau như thế nào.

+0

có thể xây dựng về vấn đề này? Làm thế nào là nó có thể xác định các mô-đun trong một tập tin mô-đun? – Allanrbo

+0

@Allanrbo: khi yêu cầu mâu thuẫn, alex martelli không bao giờ xa: http://stackoverflow.com/questions/2315044/how-to-generate-a-module-object-from-a-code-object-in-python –

10

Bắt đầu với Django cũng có thể khá dễ dàng.Đây là một ứng dụng web đơn Django gồm 10 dòng:

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

Kiểm tra bài đăng trên blog của tôi Minimal Django để biết chi tiết.

+0

Cảm ơn! Đó là chính xác những gì tôi đang tìm kiếm để bắt đầu với Django. Tốt hơn nhiều so với hướng dẫn chính thức của Django, theo ý kiến ​​của tôi. – Nobody

2

Hầu hết các tệp django ví dụ đơn được tìm thấy trên web thiếu hỗ trợ cho mô hình vì django bằng cách nào đó yêu cầu mô hình phải được khai báo trong tệp models.py trong mỗi INSTALLED_APP. Cuối cùng tôi tìm thấy một ví dụ bao gồm hỗ trợ cho các mô hình: -

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

Các liên kết đến wiki django trên các mô hình sáng tạo cũng đáng đọc. Và đầy đủ các mã mà cũng bao gồm quản trị: -

https://gist.github.com/2219751

1

John's answer trích dẫn jngo app bởi Paul Bissex là ấn tượng, nhưng nó buồn bã chia dưới Django 1.7.

Tôi đã thực hiện một loạt việc đào và created Django để hiển thị cách chạy một lớp mô hình với một cơ sở dữ liệu SQLite trong một tệp Python duy nhất. Tôi dự định sử dụng nó để đăng câu hỏi về các lớp mô hình Django. Nếu bạn muốn một số phần khác từ jngo, bạn có thể ghép chúng vào cái này. Fahrzin Hemmati đã đăng an example mà có vẻ tương tự và bao gồm đầy đủ Django: máy chủ web, mô hình, lệnh quản lý. Tôi chưa thử nó.

# 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

Thử nghiệm với 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']) 
Các vấn đề liên quan