2013-05-30 7 views
9

के साथ शुरू करना यह मेरी पहली बार पाइथन में वेब विकास में डीलिंग है। मेरा एकमात्र अन्य अनुभव PHP है, और मैंने पहले कभी ढांचा का उपयोग नहीं किया, इसलिए मुझे यह बहुत डरावना और भ्रमित लगता है।चेरीपी और जिनजा 2

मुझे अपने NAS के लिए जेएफएस मॉनिटर बनाने के लिए चेरीपी/जिनजा 2 सीखने में रूचि है। मैंने चेरीपी/जिनजा 2 पर दस्तावेज़ों की मूल बातें पढ़ी हैं, लेकिन मुझे लगता है कि नमूने अलग-अलग हैं और बहुत सरल हैं, मैं वास्तव में समझ नहीं पा रहा हूं कि इन 2 चीजों को "एक साथ आना" कैसे बनाया जाए।

कुछ सवाल मेरे पास है:

  1. वहाँ आप कैसे CherryPy और Jinja2 एक साथ अच्छी तरह से काम करने के पता चलता है एक सरल ट्यूटोरियल? मैं या तो नमूने ढूंढ रहा हूं जो बहुत आसान हैं, जैसे चेरीपी/जिनजा 2 डॉक्स पर नमूने, या जटिल तरीके से। (उदाहरण: https://github.com/jovanbrakus/cherrypy-example)।

  2. क्या चेरीपी के लिए वेब अनुप्रयोग बनाने के लिए एक मानक या "अपेक्षित" तरीका है? (उदाहरण: मेरी निर्देशिका संरचना क्या दिखनी चाहिए? क्या स्थैतिक चीजों की घोषणा करने का कोई तरीका है; क्या यह भी आवश्यक है?)

  3. क्या किसी ने इसके लिए साहित्य की सिफारिश की है या ऑनलाइन दस्तावेज़ीकरण सर्वोत्तम संसाधन है? अजगर चुनने पर

उत्तर

26

बधाई हो, मुझे लगता है मैं एक विशेषज्ञ नहीं हूँ यकीन है कि आप इसे प्यार करता हूँ के रूप में CherryPy के बारे में है मैं

जानेंगे हूँ,, लेकिन आप के रूप में ही नाव में भी था कुछ दिन पहले और मैं इस बात से सहमत हूं कि ट्यूटोरियल भागों में थोड़ा अलग हैं।

Jinja2 को एकीकृत करने के लिए, उनके doc page में, HTML के स्निपेट को निर्दिष्ट किया जाना चाहिए था कि यह टेम्पलेट फ़ाइल है और जैसे पथ /templates/index.html में सहेजी गई है। उन्होंने वैरिएबल का भी उपयोग किया जो टेम्पलेट कोड नमूना और नियंत्रक नमूना में मेल नहीं खाता था।

import cherrypy 
from jinja2 import Environment, FileSystemLoader 
env = Environment(loader=FileSystemLoader('templates')) 

class Root: 
    @cherrypy.expose 
    def index(self): 
     tmpl = env.get_template('index.html') 
     return tmpl.render(salutation='Hello', target='World') 

cherrypy.config.update({'server.socket_host': '127.0.0.1', 
         'server.socket_port': 8080, 
         }) 

cherrypy.quickstart(Root()) 

/templates/index.html:

नीचे के बजाय CherryPy और Jinja2

/main.py का उपयोग कर एक सरल हैलो दुनिया की एक पूरी काम कर नमूना है

<h1>{{ salutation }} {{ target }}</h1> 

फिर अपने खोल/कमांड प्रॉम्प्ट में, ऐप का उपयोग करके:

python main.py 

और आपके ब्राउज़र में आप http://localhost:8080

पर यह देखने के लिए उम्मीद है कि मदद करता है कि आप अपने CherryPy एप्लिकेशन को Jinja2 templating कनेक्ट करने के लिए सक्षम होना चाहिए। चेरीपी वास्तव में एक हल्का और बहुत लचीला ढांचा है, जहां आप अपने कोड और फ़ाइल संरचनाओं को ढांचे के कई अलग-अलग तरीकों का चयन कर सकते हैं।

+2

मुझे एक अच्छी परियोजना संरचना के साथ-साथ इस पोस्ट को समझने में परेशानी थी और लिंक में कुछ चीजों को स्पष्ट करने में मदद मिली। https://groups.google.com/forum/?fromgroups#!topic/cherrypy-users/L7YXZD_55ec –

+0

अच्छा! चेरीपी और मको के लिए शुरू करने के लिए यह परिचय मेरे लिए पर्याप्त है। –

+0

उपरोक्त, लेकिन कृपया मदद करें, क्योंकि मेरी समस्या Nginx http://stackoverflow.com/questions/23359095/how-to-put-cherrypy-wsgi-behind-nginx के साथ जारी है। – Alex

10

आवेदन संरचना

एक परियोजना के मानक निर्देशिका संरचना के बारे में सबसे पहले। कोई भी नहीं है, क्योंकि चेरीपी इसे जरूरी नहीं है, न तो यह आपको बताता है कि डेटा लेयर, फॉर्म सत्यापन या टेम्पलेट इंजन का उपयोग करने के लिए क्या है। यह सब आप और आपकी आवश्यकताओं पर निर्भर है।और निश्चित रूप से यह एक बड़ी लचीलापन है क्योंकि इससे शुरुआती लोगों को कुछ भ्रम पैदा होता है। यहां बताया गया है कि रीयल-वर्ड एप्लिकेशन निर्देशिका संरचना के करीब कैसा दिख सकता है।

.   — Python virtual environment 
└── website — cherryd to add this to sys.path, -P switch 
    ├── application 
    │ ├── controller.py — request routing, model use 
    │ ├── model.py  — data access, domain logic 
    │ ├── view   — template 
    │ │ ├── layout 
    │ │ ├── page 
    │ │ └── part 
    │ └── __init__.py — application bootstrap 
    ├── public 
    │ └── resource — static 
    │  ├── css 
    │  ├── image 
    │  └── js 
    ├── config.py — configuration, environments 
    └── serve.py — bootstrap call, cherryd to import this, -i switch 

फिर virtual environment की जड़ आप आमतौर पर विकास के वातावरण में CherryPy शुरू करने के लिए निम्न उपाय अपनाते हैं में खड़े। cherryd चेरीपी का आवेदन चलाने का सुझाव है।

. bin/activate 
cherryd -i serve -P website 

Templating

अब टेम्पलेट निर्देशिका के करीब नजर डालते हैं और यह कैसा देख सकते हैं।

. 
├── layout 
│ └── main.html 
├── page 
│ ├── index 
│ │ └── index.html 
│ ├── news 
│ │ ├── list.html 
│ │ └── show.html 
│ ├── user 
│ │ └── profile.html 
│ └── error.html  
└── part 
    └── menu.html 

template inheritance का अच्छा Jinja2 की सुविधा का उपयोग करने के लिए यहां लेआउट जो एक पेज की संरचना को परिभाषित, स्लॉट्स एक विशेष पेज में भरा जा सकता है कि कर रहे हैं। ईमेल सूचनाओं के लिए आपके पास वेबसाइट और लेआउट के लिए लेआउट हो सकता है। अलग-अलग पृष्ठों में उपयोग किए जाने वाले भाग, पुन: प्रयोज्य स्निपेट के लिए एक निर्देशिका भी है। अब उपरोक्त संरचना से मेल खाने वाले कोड को देखते हैं।

मैंने निम्नलिखित को a runnable के रूप में भी उपलब्ध कराया है जो फ़ाइलों को नेविगेट करना आसान है, आप इसे चला सकते हैं और खेल सकते हैं। पथ पहले सेक्शन के पेड़ की तरह . के साथ शुरू होते हैं।

वेबसाइट/config.py

# -*- coding: utf-8 -*- 


import os 


path = os.path.abspath(os.path.dirname(__file__)) 
config = { 
    'global' : { 
    'server.socket_host' : '127.0.0.1', 
    'server.socket_port' : 8080, 
    'server.thread_pool' : 8, 

    'engine.autoreload.on' : False, 

    'tools.trailing_slash.on' : False 
    }, 
    '/resource' : { 
    'tools.staticdir.on' : True, 
    'tools.staticdir.dir' : os.path.join(path, 'public', 'resource') 
    } 
} 

वेबसाइट/serve.py

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 


from application import bootstrap 


bootstrap() 


# debugging purpose, e.g. run with PyDev debugger 
if __name__ == '__main__': 
    import cherrypy 
    cherrypy.engine.signals.subscribe() 
    cherrypy.engine.start() 
    cherrypy.engine.block() 

वेबसाइट/आवेदन/__ init__.py

एक

उल्लेखनीय यहाँ हिस्सा है चेरीपी उपकरण जो रेंडरिन से संबंधित बॉयलरप्लेट से बचने में मदद करता है जी टेम्पलेट्स। टेम्पलेट के डेटा के साथ आपको चेरीपी पेज हैंडलर से dict वापस करने की आवश्यकता है। सम्मेलन-ओवर-कॉन्फ़िगरेशन सिद्धांत के बाद, उपकरण जब टेम्पलेट नाम के साथ प्रदान नहीं किया जाता है तो classname/methodname.html उदा। user/profile.html। डिफ़ॉल्ट टेम्पलेट को ओवरराइड करने के लिए आप @cherrypy.tools.template(name = 'other/name') का उपयोग कर सकते हैं। यह भी ध्यान रखें उपकरण स्वचालित रूप से एक विधि को उजागर करता है, तो आप शीर्ष

# -*- coding: utf-8 -*- 


import os 
import types 

import cherrypy 
import jinja2 

import config 


class TemplateTool(cherrypy.Tool): 

    _engine = None 
    '''Jinja environment instance''' 


    def __init__(self): 
    viewLoader = jinja2.FileSystemLoader(os.path.join(config.path, 'application', 'view')) 
    self._engine = jinja2.Environment(loader = viewLoader) 

    cherrypy.Tool.__init__(self, 'before_handler', self.render) 

    def __call__(self, *args, **kwargs): 
    if args and isinstance(args[0], (types.FunctionType, types.MethodType)): 
     # @template 
     args[0].exposed = True 
     return cherrypy.Tool.__call__(self, **kwargs)(args[0]) 
    else: 
     # @template() 
     def wrap(f): 
     f.exposed = True 
     return cherrypy.Tool.__call__(self, *args, **kwargs)(f) 
     return wrap 

    def render(self, name = None): 
    cherrypy.request.config['template'] = name 

    handler = cherrypy.serving.request.handler 
    def wrap(*args, **kwargs): 
     return self._render(handler, *args, **kwargs) 
    cherrypy.serving.request.handler = wrap 

    def _render(self, handler, *args, **kwargs): 
    template = cherrypy.request.config['template'] 
    if not template: 
     parts = [] 
     if hasattr(handler.callable, '__self__'): 
     parts.append(handler.callable.__self__.__class__.__name__.lower()) 
     if hasattr(handler.callable, '__name__'): 
     parts.append(handler.callable.__name__.lower()) 
     template = '/'.join(parts) 

    data  = handler(*args, **kwargs) or {} 
    renderer = self._engine.get_template('page/{0}.html'.format(template)) 

    return renderer.render(**data) if template and isinstance(data, dict) else data 


def bootstrap(): 
    cherrypy.tools.template = TemplateTool() 

    cherrypy.config.update(config.config) 

    import controller 

    cherrypy.config.update({'error_page.default': controller.errorPage}) 
    cherrypy.tree.mount(controller.Index(), '/', config.config) 

वेबसाइट/आवेदन/controller.py

पर @cherrypy.expose संलग्न करने के लिए आप उपकरण के उपयोग के साथ देख सकते हैं की जरूरत नहीं है पेज हैंडलर अपेक्षाकृत साफ दिखते हैं और अन्य उपकरणों के साथ संगत होंगे, उदाहरण के लिए json_out

# -*- coding: utf-8 -*- 


import datetime 

import cherrypy 


class Index: 

    news = None 
    user = None 


    def __init__(self): 
    self.news = News() 
    self.user = User() 

    @cherrypy.tools.template 
    def index(self): 
    pass 

    @cherrypy.expose 
    def broken(self): 
    raise RuntimeError('Pretend something has broken') 


class User: 

    @cherrypy.tools.template 
    def profile(self): 
    pass 


class News: 

    _list = [ 
    {'id': 0, 'date': datetime.datetime(2014, 11, 16), 'title': 'Bar', 'text': 'Lorem ipsum'}, 
    {'id': 1, 'date': datetime.datetime(2014, 11, 17), 'title': 'Foo', 'text': 'Ipsum lorem'} 
    ] 


    @cherrypy.tools.template 
    def list(self): 
    return {'list': self._list} 

    @cherrypy.tools.template 
    def show(self, id): 
    return {'item': self._list[int(id)]} 


def errorPage(status, message, **kwargs): 
    return cherrypy.tools.template._engine.get_template('page/error.html').render() 

इस डेमो एप्लिकेशन में मैं कैसे स्थिर संसाधन से निपटने काम करता है प्रदर्शित करने के लिए blueprint सीएसएस फ़ाइल का उपयोग किया,। इसे website/application/public/resource/css/blueprint.css में रखें। बाकी कम दिलचस्प है, केवल पूर्णता के लिए Jinja2 टेम्पलेट्स।

वेबसाइट/आवेदन/देखें/लेआउट/main.html

<!DOCTYPE html> 
<html> 
    <head> 
    <meta http-equiv='content-type' content='text/html; charset=utf-8' /> 
    <title>CherryPy Application Demo</title> 
    <link rel='stylesheet' media='screen' href='/resource/css/blueprint.css' /> 
    </head> 
    <body> 
    <div class='container'> 
     <div class='header span-24'> 
     {% include 'part/menu.html' %} 
     </div> 
     <div class='span-24'>{% block content %}{% endblock %}</div>  
    </div> 
    </body> 
</html> 

वेबसाइट/आवेदन/देखें/पेज/सूचकांक/सूचकांक।एचटीएमएल

{% extends 'layout/main.html' %} 
{% block content %} 
    <div class='span-18 last'> 
     <p>Root page</p>  
    </div> 
{% endblock %} 

वेबसाइट/आवेदन/देखें/पेज/समाचार/list.html

{% extends 'layout/main.html' %} 
{% block content %} 
    <div class='span-20 last prepend-top'> 
    <h1>News</h1> 
    <ul> 
    {% for item in list %} 
     <li><a href='/news/show/{{ item.id }}'>{{ item.title }}</a> ({{ item.date }})</li> 
    {% endfor %} 
    </ul> 
    </div> 
{% endblock %} 

वेबसाइट/आवेदन/देखें/पेज/समाचार/show.html

{% extends 'layout/main.html' %} 
{% block content %} 
    <div class='span-20 last prepend-top'> 
    <h2>{{ item.title }}</h2> 
    <div class='span-5 last'>{{ item.date }}</div> 
    <div class='span-19 last'>{{ item.text }}</div> 
    </div> 
{% endblock %} 

वेबसाइट/एप्लिकेशन/दृश्य/पृष्ठ/उपयोगकर्ता/प्रोफ़ाइल.html

{% extends 'layout/main.html' %} 
{% block content %} 
    <div class='span-18'> 
    <table> 
     <tr><td>First name:</td><td>John</td></tr> 
     <tr><td>Last name:</td><td>Doe</td></tr> 
    <table> 
    </div> 
{% endblock %} 

वेबसाइट/आवेदन/देखें/पेज/error.html

यह 404 पन्ने की है।

{% extends 'layout/main.html' %} 
{% block content %} 
    <h1>Error has happened</h1> 
{% endblock %} 

वेबसाइट/आवेदन/देखें/भाग/menu.html

<div class='span-4 prepend-top'> 
    <h2><a href='/'>Website</a></h2> 
</div> 
<div class='span-20 prepend-top last'> 
    <ul> 
     <li><a href='/news/list'>News</a></li> 
     <li><a href='/user/profile'>Profile</a></li> 
     <li><a href='/broken'>Broken</a></li> 
    </ul> 
</div> 

संदर्भ

कोड ऊपर qooxdoo-website-skeleton की बैकएंड अनुभाग के साथ मिलकर चला जाता है। इस तरह के आवेदन के पूर्ण उग्र डेबैन परिनियोजन के लिए, cherrypy-webapp-skeleton उपयोगी हो सकता है।

+0

अपने टेम्पलेट टूल का उपयोग करके, क्या फ़ंक्शन के भीतर से टेम्पलेट को ओवरराइड करना संभव होगा? उदाहरण के लिए, यदि मैं ज्यादातर मामलों में डिफ़ॉल्ट टेम्पलेट व्यवहार चाहता था, लेकिन [यदि शर्तों का एक निश्चित सेट किसी अन्य टेम्पलेट पथ पर स्विच किया गया है] (https://gist.github.com/anonymous/a0bebdac4245a564c1a5)? –

+1

@ जस्टिन हां। चूंकि उपकरण हैंडलर को लपेटता है, इसलिए आपको इसे थोड़ा बदलना होगा ताकि आपके हैंडलर का साइड इफेक्ट ओवरराइड न हो। बस 'data = हैंडलर (* args, ** kwargs) या {} '' TemplateTool._render' में पहली पंक्ति पर बनें और आपका कोड काम करेगा। – saaj

संबंधित मुद्दे