2017-04-03 7 views
0

私はラケットWebサーバを使用して少しのブログを書いています(web-server/templates, web-server/servlet-env, web-server/servlet, web-server/dispatchが必要です)。少し手順を定義ラケットWebサーバ/テンプレートインクルードテンプレートは変数に使用できません

(define (render-homeworks-overview-page) 
    (let 
    ([dates 
     (sort 
     (get-all-homework-dates) 
     #:key my-date->string 
     string<?)]) 
    (include-template "templates/homework-overview.html"))) 

、その後、テンプレート内で使用されているこの場合datesで、必要なすべての値を使用して、テンプレートを提供するために:私はテンプレートをレンダリングしたいときはいつでも、私は何か、これを行います。これまでのところうまくいきましたが、すべてのレンダリングプロシージャでを取り除くことができると考えました。これは、より抽象的なrender-templateプロシージャに一度入れてから、すべてのレンダリングプロシージャによって呼び出されます。あるいは、このより抽象的なプロシージャへの呼び出しはとてもシンプルになる可能性があります。これは、もう少しレンダリング手順をすべて必要としないようにするためです。私はキーワード引数として値を提供したいとこれまでのところ、私は次のコードを得た:これはレンダリングと任意取るためにテンプレートに表示されるコンテンツのデフォルト値とテンプレートのデフォルトパスを持っているでしょう

(define render-template 
    (make-keyword-procedure 
    (lambda 
     (keywords keyword-args [content "<p>no content!</p>"] [template-path "template/base.html"]) 
     (let 
     ([content content]) 
     (include-template template-path))))) 

をどのようなレンダリングプロシージャでも、テンプレートとして必要なものをキーワードとして与えることができます。エラーがあるので

しかし、私は、このコードを実行することはできません。

include-at/relative-to/reader: not a pathname string, `file' form, or `lib' form for file 

を呼び出し(include-template template-path)template-pathはエラーがあることを示すために、赤い下線が引かれています。しかし、そのように私は普通の文字列でtemplate-pathを交換するとき:

(define render-template 
    (make-keyword-procedure 
    (lambda 
     (keywords keyword-args [content "<p>no content!</p>"] [template-path "template/base.html"]) 
     (let 
     ([content content]) 
     (include-template "templates/base.html"))))) 

エラーが発生しません。ラケットはどういうわけかinclude-templateに与えられた有効なパスがあることを確実にしたいと思うようです。しかし、私はそれが手技に与えられる価値であることを望んでいます。さもなければ私はこの仕事をしている手続きを書くことができません。

また、プロシージャに提供されたキーワードの値をテンプレートに表示します。私はそれが自動的にケースであるかどうかわからない、またはinclude-templateコールの周りにletを置く必要がある場合、私はまだこれをテストするためにコードを実行することができませんでした。

このような手順はどのように記述できますか?私が持っているしたい理想的な手順の一例として、

  • Jinja2ののrender_template

私は私が望む任意のキーワード引数を与えると私はレンダリングしたい任意のテンプレートをレンダリングすることができます。私はまた、実際に理解していない、なぜ"rm -rf /"のようなものを含めて何かにダメージを与える可能性があります。私にとっては、Webサーバーはファイルが存在する場合にはをチェックしてください。その名前のです。明らかにそれは存在しないので、エラーを投げる。これがどのようにして望ましくない損害をもたらしますか?結果として、文字列へのテンプレートへのパスとして使用できるものを制限する背後にある理由を理解していません(回避策を除く)。しかし、これはあまりにも多くの1つの質問のためかもしれないし、多分物事の "理由"についての別の質問に入れなければならない。

+0

題したドキュメントのセクション[私は「動的 "テンプレートを使用するにはどうすればよい?](http://docs.racket-lang.org/web-server/faq.html#%28part ._。How_do_.I_use_templates__dynamically __%29)はあなたの質問に対処します。 –

答えて

1

あなたは変数 path引数でinclude-templateを適用する場合のように、あなたは、レンダリングの手順を定義することができます。手順は、引数として、任意のテンプレートパスを取り込み、そのテンプレートが含まれて

(define (dynamic-include-template path) 
    (eval #`(include-template #,path))) 

。たとえば、(dynamic-include-template "static.html")static.htmlと表示されます。

次のようにこれは、キーワードの任意の数を受け入れ、レンダリングされているテンプレート内にそれらを利用できるように拡張することができます:ここで

(define render-template 
    (make-keyword-procedure 
    (lambda (kws kw-args 
       [path "templates/base.html"] 
       [content "<p>no content!</p>"]) 
    (for ([i kws] 
      [j kw-args]) 
     (namespace-set-variable-value! 
     (string->symbol (keyword->string i)) j)) 
    (namespace-set-variable-value! 'content content) 
    (dynamic-include-template path)))) 

forブロック内で、新しい識別子とキーワードの値がに設定されていますのようなキーワードと値のパラメータの場合、テンプレートで使用可能になる対応する識別子はfoo@ Syntax@foo)になり、その値はbarになるように、namespace-set-variable-value!を使用する名前空間の最上位環境。あなたが行うことができる。例えば

、宿題-概要テンプレートをレンダリングするために、:

(render-template "templates/homework-overview.html" 
       #:dates (sort (get-all-homework-dates) string<?)) 

が、その後templates/homework-overview.htmlの内側にあなたが持っているでしょう:evalを使用した場合

... 
@dates 
... 

は、しかし、注意してください、と関連する読み取りには次の点を考慮してください。

+0

私はこの解決策に2つの問題しかありません。関数が突然 'path:/ home/xiaolong/development/Racket/blog2/htdocs/templates/base.html'を見て、' htdocs'フォルダがないので当然そのファイルを見つけることができないので、私のプロジェクト全体でこれは奇妙です。なぜなら、この答えには 'htdocs'が全く含まれていないので、どこから突然出てくるのか分かりません。もう一つの問題は、私はこの手続きに任意のキーワード引数を与えることができないということです。 'make-keyword-procedure'を使っても' let 'を使わなければならないときは、どのようにして任意のkeyword-argsの名前を知ることができますか? – Zelphir

+0

私はこのaproachを使ってデフォルトパスを設定する必要がありますか? – Zelphir

+0

最初の問題では、ローカルで再現できませんでした。 'templates'ディレクトリを作成し、その中にいくつかの内容で' static.html'を保存してから '(render-template" templates/static.html ")'を試しました( 'render-template'は同じディレクトリに定義されていますそれは 'templates'フォルダを含んでいます)、期待どおりに動作しますので、あなたの問題を作り出す問題があなたのコードのどこかにあるかもしれません。 – assefamaru

関連する問題