2013-10-19 50 views
3

我試圖使用CSS和Jinja和Flask的媒體查詢來確定設備類型並根據設備提供適當大小的圖像。來自手機的請求將獲得比桌面,平板電腦等更小的圖像。使用CSS媒體查詢和Flask/Jinja進行設備檢測

問題是{{ post|get_image(post, 480) }}的評估獨立於媒體查詢,因此會觸發每個實例的get_image自定義模板過濾器。 get_image也是爲設備呈現正確圖像的地方,因此可能不必要的多次呼叫可能會對性能產生負面影響。

理想情況下,只有一個媒體查詢是通過一次調用get_image制定的,但挑戰在於媒體查詢和Jinja完全相互獨立,因爲一個人對另一個不瞭解。

我真的很感激替代方法或建議,以改善我的方法。提前致謝!

這裏的媒體查詢的一個例子:

@media only screen and (max-device-width: 480px) { 
    .post { 
     background: url("{{ post|get_image(post, 480) }}") no-repeat center center fixed; 
    } 
    } 

    @media only screen and (max-device-width: 1224px) { 
    .post { 
     background: url("{{ post|get_image(post, 1224) }}") no-repeat center center fixed; 
    } 
    } 
+0

您正在尋求「改善」的方法,但就我而言,您正在做的事情沒有問題。你真的關心什麼?你認爲模板渲染速度太慢,多次調用'get_image'? –

+0

是的,可能會有4-5次調用get_image(每個媒體查詢一次),這實際上是生成適當的圖像。 – Raj

+0

有什麼辦法可以讓'get_image' _不生成圖像? –

回答

1

更改您的設置是這樣的:

/posts/<int:post_id>/background?s=NNNN 

.post { 
    background: none no-repeat center center fixed; 
} 

@media only screen and (max-device-width: 480px) { 
    .post { 
     background-image: url("{{ get_image_url(post, 480) }}"); 
    } 
} 

@media only screen and (max-device-width: 1224px) { 
    .post { 
     background-image: url("{{ get_image_url(post, 1224) }}"); 
    } 
} 

你生成可能是這個樣子的網址

然後,設置您的代理服務器以便將這些映像從緩存目錄中提取出來並轉發他們到您的圖像生成器,如果不存在圖像:

# Fake server configuration 
# for no server known to man 
location /posts/(:post-id:\d+)/background { 
    try_files /cache/:post-id:_\d+\.png or @flask-server 
} 

最後,在瓶器生成圖像,將其保存到緩存目錄,並送達回請求:

@app.route("/posts/<int:post_id>/background") 
def generate_image(post_id): 
    # Assume that if we got here the image does not yet exist 
    dimensions = int(request.args.get("s", 800), 10) 

    image_data = generate_image(post_id, dimensions) 

    image_name = "{}_{}.png".format(post_id, dimensions) 
    image_path = os.path.join("/cache", image_name) 

    with open(image_path, "wb") as image: 
     image.write(image_data) 

    return Response(image_data, content_type="image/png") 

如果圖像生成部分太昂貴,甚至無法考慮在控制器中執行操作,則可以返回204將No-Content與Cache-Control設置爲private並在過去設置Expires,並將圖像生成任務放入out-of進程隊列。然後只需在JavaScript代碼中輪詢該端點,直至圖像準備好由代理服務器提供服務。

+0

在你的例子中,get_image_url()會在模板被渲染時被多次調用嗎? – Raj

+0

@Raj - 是的,但它只是生成一個字符串,而不是構建實際的圖像。圖像生成被推遲到請求時間,當瀏覽器(理論上)只會要求它實際需要的圖像時。 –

+1

非常感謝你。我並沒有最終實現這一點,但我確實使用了這種通用模式,所以它非常有用。所以我將其標記爲正確的答案!再次感謝! – Raj