2010-05-25 12 views
10

मैं टेम्पलेट टैग का एक सेट लिखने की कोशिश कर रहा हूं जो आपको टेम्पलेट फ़ाइलों के भीतर से जेएस और सीएसएस फ़ाइलों को आसानी से निर्दिष्ट करने की अनुमति देता है। {% requires global.css %} की लाइनों के साथ कुछ और बाद में अनुरोध में, {% get_required_css %}Django templatetag "प्रसंस्करण का आदेश"

मेरे पास यह अधिकतर काम कर रहा है, लेकिन कुछ मुद्दे हैं। हम 'समय' मुद्दों से शुरू करेंगे।

प्रत्येक टेम्पलेट टैग दो चरणों से बना है, कॉल/इनिट और प्रस्तुत करें। किसी भी रेंडर प्रक्रिया को बुलाए जाने से पहले प्रत्येक कॉल/इनिट होता है। यह गारंटी देने के लिए कि {% get_required_css %} प्रस्तुत करने से पहले सभी फ़ाइलों को कतारबद्ध किया गया है, मुझे कॉल/इनिट प्रक्रियाओं में आवश्यक फ़ाइलों की अपनी सूची बनाने की आवश्यकता है।

तो, मुझे सभी फ़ाइलों को एक बंडल प्रति अनुरोध में एकत्र करने की आवश्यकता है। context dict जाहिर है इसके लिए जगह है, लेकिन दुर्भाग्य से, कॉल/init में संदर्भ चर तक पहुंच नहीं है।

क्या यह समझ में आता है? कोई भी इस के आसपास एक रास्ता देखता है (एक हैक-वाई वैश्विक request ऑब्जेक्ट का उपयोग किए बिना)?

स्थानीय स्कूल में इन्हें स्टोर करने की एक और संभावना है लेकिन उन्हें अभी भी अनुरोध से बंधे रहने की आवश्यकता होगी ... संभवतः {% start_requires %} टैग का कुछ प्रकार? लेकिन मुझे कोई संकेत नहीं है कि यह काम कैसे करें।

+0

संक्षिप्त रूप से 'मिडलवेयर' की क्षमताओं की जांच करने के बाद, मैं जेनरेट किए गए HTML को सम्मिलित करने के लिए इसका उपयोग करने पर विचार कर रहा हूं। इसके साथ समस्या यह है कि विभिन्न स्थिर संपीड़न ऐप्स को बिना किसी काम के लिए प्राप्त करना अधिक कठिन होता है। –

+0

यदि कोई दिलचस्पी लेता है, तो मेरे पास जिथब पर एक ऐप है जो इस विशिष्ट समस्या का एक बिल्कुल अनूठा समाधान है - http://github.com/pappy74/django-requires_js_css। यह जैक के जवाब के समान ही है, लेकिन एक अच्छा, साफ ऐप के रूप में पैक किया गया है। –

उत्तर

2

मैं ऐसा करने के लिए एक तरीका आया हूं जो आपकी आवश्यकताओं के अनुरूप है। सर्वर पर इसका थोड़ा अधिक भार होगा, लेकिन उचित कैशिंग उसमें से अधिकांश को कम करने में मदद कर सकती है। नीचे मैंने एक तरीका रेखांकित किया है जो काम करना चाहिए यदि सीएसएस में प्रत्येक पथ के लिए समान हैं। इन सभी फ़ाइलों को शामिल करने के लिए आपको एक एकल दृश्य बनाना होगा, लेकिन आप वास्तव में इस विधि का उपयोग करके अपने सीएसएस को अनुकूलित कर सकते हैं, जिससे प्रत्येक पृष्ठ के लिए केवल एक ही सीएसएस कॉल किया जा सके।

import md5 
class LoadCss(template.Node): 
    def __init__(self, tag_name, css): 
     self.css = css 
     self.tag_name = tag_name 
    def render(self, context): 
     request = context['request'] 
     md5key = md5.new(request.path).hexdigest() 
     if md5key not in request.session: 
      request.session[md5key] = list() 
     ## This assumes that this method is being called in the correct output order. 
     request.session[md5key].append(self.css) 
     return '<!-- Require %s -->' % self.css 
def do_load_css(parser, token): 
    tag_name, css = token.split_contents() 
    return LoadCss(tag_name, key) 
register.tag('requires', do_load_css) 

class IncludeCss(template.Node): 
    def __init__(self, tag_name): 
     self.tag_name = tag_name 
    def render(self, context): 
     request = context['request'] 
     md5key = md5.new(request.path).hexdigest() 
     return '<link rel="stylesheet" href="/path/to/css/view/%s">' % md5key 
def do_include_css(parser, token): 
    return IncludeCss(token) 
register.tag('get_required_css', do_include_css) 

views.py:

from django.conf import settings 
from django.views.decorators.cache import cache_page 
import os 

@cache_page(60 * 15) ## 15 Minute cache. 
def css_view(request, md5key): 
    css_requires = request.session.get(md5key, list()) 
    output = list() 
    for css in css_requires: 
     fname = os.path.join(settings.MEDIA_ROOT, 'css', css) ## Assumes MEDIA_ROOT/css/ is where the CSS files are. 
     f = open(fname, 'r') 
     output.append(f.read()) 
    HttpResponse(''.join(output), mimetype="text/css") 

यह आपको सत्र में तो संदर्भ में सीएसएस जानकारी स्टोर करने के लिए, और (कैशिंग इसे बनाने के लिए के साथ एक दृश्य से उत्पादन की सेवा की अनुमति देता है और तेज)। यह निश्चित रूप से, थोड़ा अधिक सर्वर ओवरहेड होगा।

यदि आपको केवल पथ से अधिक सीएसएस को अलग करने की आवश्यकता है, तो आप अपनी आवश्यकताओं के अनुसार md5 लाइनों को बस संशोधित कर सकते हैं। आपके पास संपूर्ण अनुरोध ऑब्जेक्ट और संदर्भ तक पहुंच है, इसलिए लगभग सबकुछ वहां होना चाहिए।

सावधान: दूसरी समीक्षा करने पर यह एक रेस स्थिति पैदा हो सकती है ब्राउज़र सीएसएस को हासिल करेगा अगर पहले सत्र भर जाने के बाद। मुझे विश्वास नहीं है कि Django इस तरह से काम करता है, लेकिन मुझे अभी इसे देखने की तरह महसूस नहीं होता है।

+0

इस तरह मैंने इसे शुरू में लागू किया था, लेकिन समस्या ऑर्डर करने में से एक है। इसके साथ, आपको यह सुनिश्चित करना होगा कि 'get_required' को पार्स किए जाने से पहले आपके सभी 'आवश्यक' को पार्स किया गया हो।यह विशेष रूप से स्पष्ट होता है जब एक समावेश टेम्पलेट टैग स्वयं को एक सीएसएस फ़ाइल की आवश्यकता होती है। यदि आप वास्तव में __init__ के दौरान फ़ाइलों को जोड़ सकते हैं, तो आप उस समस्या के आसपास आते हैं। –

+0

मैंने इसे पूरा करने के लिए एक और संभावित तरीका जोड़ा जो आंतरिक आदेश पर भरोसा नहीं करता है। यह थोड़ा पतला है, लेकिन यह काम करना चाहिए। –

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