0

我想通過以下的Play documentation做一個自定義模板格式(播放2.5_ & _Scala 2.11.11),但我在這裏這樣就意味着它不是爲我工作。在播放創建自定義的模板格式2.5

我希望新的模板有「」文件擴展名(如this video現在是幾歲),所以我創造了這個文件作爲文檔建議:

package ui 

    import akka.NotUsed 
    import akka.stream.scaladsl.{Source} 
    import play.twirl.api._ 

    import scala.collection.immutable 

    case class HtmlStream(source: Source[Html, NotUsed]) extends Appendable[HtmlStream] { 

    def +=(other: HtmlStream): HtmlStream = andThen(other) 
    def andThen(other: HtmlStream): HtmlStream = HtmlStream(source.merge(other.source)) 

    } 

    object HtmlStream { 

    def apply(text: String): HtmlStream = apply(Html(text)) 
    def apply(html: Html): HtmlStream = HtmlStream(Source.single(html)) 

    } 

    object HtmlStreamFormat extends Format[HtmlStream] { 

    def raw(text: String): HtmlStream = HtmlStream(text) 
    def escape(text: String): HtmlStream = raw(HtmlFormat.escape(text).body) 

    override def empty: HtmlStream = ??? 
    override def fill(elements: immutable.Seq[HtmlStream]): HtmlStream = ??? 

    } 

而且已將此添加到build.sbt文件:

TwirlKeys.templateFormats += ("stream" -> "ui.HtmlStreamFormat.instance") 

我看不出哪裏或如何包括以下隱(上預提到Play documentation - 底部);這可能是問題:

Play可以寫一個HTTP響應體用於哪 它存在的隱式play.api.http.Writeable [A]值A型的任何值。所以你需要的是爲你的模板結果類型定義一個這樣的值。對於 例如,下面是如何爲HTTP定義這樣的值:

implicit def writableHttp(implicit codec: Codec): Writeable[Http] = 
    Writeable[Http](result => codec.encode(result.body), Some(ContentTypes.HTTP)) 

當我嘗試創建一個新的文件view,例如稱爲test.scala.stream它不能識別它應該是什麼類型,所以它看起來有些絕對是錯誤的。幫助需要這個!

回答

0

因此,我已經破解了這一個,並在社區精神這裏。

1)創建一個文件(I稱爲礦 「HtmlStream」 爲我尋找到流HTML):

package ui 

    import akka.NotUsed 
    import akka.stream.scaladsl.{Source} 
    import play.twirl.api._ 

    import scala.collection.immutable 
    import scala.concurrent.ExecutionContext 

    case class HtmlStream(source: Source[Html, NotUsed]) extends Appendable[HtmlStream] { 

    def +=(other: HtmlStream): HtmlStream = andThen(other) 
    def andThen(other: HtmlStream): HtmlStream = HtmlStream(source.merge(other.source)) 

    } 

    object HtmlStream { 

    def apply(text: String): HtmlStream = apply(Html(text)) 
    def apply(html: Html): HtmlStream = HtmlStream(Source.single(html)) 

    } 

    object HtmlStreamFormat extends Format[HtmlStream] { 

    def raw(text: String): HtmlStream = HtmlStream(text) 
    def escape(text: String): HtmlStream = raw(HtmlFormat.escape(text).body) 

    override def empty: HtmlStream = raw("") 
    override def fill(elements: immutable.Seq[HtmlStream]): HtmlStream = elements.reduce((agg, curr) => agg.andThen(curr)) 

    } 

    object HtmlStreamImplicits { 

     implicit def toSource(stream: HtmlStream)(implicit ec: ExecutionContext): Source[Html, NotUsed] = { 
     stream.source.filter(_.body.nonEmpty) 

    } 

2)I加入這些行到build.sbt文件:

TwirlKeys.templateFormats += ("stream" -> "ui.HtmlStreamFormat") 
    TwirlKeys.templateImports ++= Vector("ui.HtmlStream", "ui.HtmlStream._", "ui.HtmlStreamFormat._", "ui.HtmlStreamImplicits._") 

3)我添加了一個名爲模板test1.scala.stream(提示時使用HTML的文件關聯):

@(body: HtmlStream) 

    <!DOCTYPE html> 
    <html lang="en"> 
     <head> 
      <title>title</title> 
      <link rel="stylesheet" media="screen" href="assets/stylesheets/main.css"> 
      <link rel="shortcut icon" type="image/png" href="assets/images/favicon.png"> 
      <script src="assets/javascripts/hello.js" type="text/javascript"></script> 
     </head> 
     <body> 
     <h1>Streaming the body</h1> 

     <div> 
      <div> 
       @body 
      </div> 
     </div> 
     </body> 
    </html> 

4)最後,我可以用這個模板,我會通過將其轉化爲新HtmlStream類型的任何其它模板。

def streamHtml = Action { request => 

    val async1: Future[Result] = rr.getAsync(embed = true)(request) // get future 
    val async1Html: Future[Html] = async1.flatMap(x => Pagelet.readBody(x)) // separate function to convert Future[Result] to Future[Html] 
    val htmlStream: HtmlStream = HtmlStream(fromFuture(async1Html)) // c onvert to HtmlStream type 

    Ok.chunked(views.stream.test1(htmlStream)) // chunk the new data type by sending through new template 

    } 

希望這對別人有幫助!

0

這是一個自定義格式,我按照播放規範對CVS和作品進行編碼,包括有關ContentTypes的問題。HTTP:

一些建議:

1,如果你想那部戲的框架可以寫一個HTTP響應身體,你需要定義的主體內容。看看隱含def contentTypeCsv這是你必須做的,但在你的具體內容。

2-其他重要的建議,自定義格式的旋轉模板應該在您的自定義模板所在的built.sbt中定義,如果項目是單個或多個項目,則無關緊要。

class Csv(buffer: immutable.Seq[Csv],text:String,escape:Boolean) extends BufferedContent[Csv](buffer, text) { 

    val contentType = Csv.contentType 

    def this(text: String) = this(Nil, Formats.safe(text),false) 
    def this(buffer: immutable.Seq[Csv]) = this(buffer, "",false) 


    override protected def buildString(builder: StringBuilder) { 
    if (elements.nonEmpty) { 
     elements.foreach { e => 
     e.buildString(builder) 
     } 
    } else if (escape) { 
     // Using our own algorithm here because commons lang escaping wasn't designed for protecting against XSS, and there 
     // don't seem to be any other good generic escaping tools out there. 
     text.foreach { 
     case '"' => builder.append("\"\"") 
     case c => builder += c 
     } 
    } else { 
     builder.append(text) 
    } 
    } 
} 


object Csv { 
    val contentType = "text/csv" 
    implicit def contentTypeCsv(implicit codec: Codec): ContentTypeOf[Csv] = ContentTypeOf[Csv](Some(Csv.contentType)) 

    def apply(text: String): Csv = new Csv(text) 

    def empty: Csv = new Csv("") 
} 
object CsvFormat extends Format[Csv] { 
    def raw(text: String): Csv = Csv(text) 
    def escape(text: String): Csv = { 
    new Csv(Nil, text, true) 
    } 

    def empty: Csv = new Csv("") 

    def fill(elements: Seq[Csv]): Csv = new Csv(elements) 
}