38

私は、静的ファイルとその中の更新に関する問題の普遍的な解決策に取り組んでいます。

例:/static/styles.cssファイルのあるサイトがあり、そのサイトが長期間使用されていたため、多くの訪問者がこのファイルをブラウザにキャッシュしたとします。

現在、このcssファイルに変更を加えてサーバーで更新していますが、一部のユーザーはまだ古いバージョンを持っています(サーバーから変更日が返されたにもかかわらず)

明白な解決策は、ファイルに何らかのバージョンを追加することです/static/styles.css?v=1.1が、この場合、開発者はこのファイルの変更を追跡し、手動でバージョンを上げる必要があります

2 番目の解決策は、ファイルの md5 ハッシュをカウントし、それを URL に追加すること/static/styels.css/?v={mdp5hashvalue}です。

彼らは私がそれを見る方法を考えています - このようなテンプレートタグを作成してください

{% static_file  "style.css" %}

レンダリングする

<link src="/static/style.css?v=md5hash">

しかし、私はこのタグがすべてのページの読み込みで md5 を計算したくありません。また、ハッシュを django-cache に保存したくありません。ファイルを更新した後にクリアする必要があるからです...

何かご意見は ?

4

10 に答える 10

40

Django 1.4には、CachedStaticFilesStorage必要なことを正確に実行するものが含まれるようになりました(まあ...ほぼ)。

ManifestStaticFilesStorageの代わりにDjango 2.2を使用する必要があるためですCachedStaticFilesStorage

タスクで使用しmanage.py collectstaticます。通常どおり、すべての静的ファイルはアプリケーションから収集されますが、このストレージ マネージャーは、名前に MD5 ハッシュが追加された各ファイルのコピーも作成します。たとえば、css/styles.cssファイルがあるとします。次のようなものも作成されますcss/styles.55e7cbb9ba48.css

もちろん、あなたが述べたように、問題は、生成する適切な URL を見つけるために、常にビューとテンプレートで MD5 ハッシュを計算したくないということです。解決策はキャッシングです。わかりました、あなたはキャッシュなしで解決策を求めました。申し訳ありませんが、それが私がほとんどと言った理由です。しかし、実際にはキャッシングを拒否する理由はありません。 CachedStaticFilesStorageという名前の特定のキャッシュを使用しstaticfilesます。デフォルトでは、既存のキャッシュ システムが使用されます。ただし、通常のキャッシュを使用したくない場合は、おそらく分散 memcache であり、静的ファイル名を取得するためだけにネットワーク クエリのオーバーヘッドを回避したいため、staticfiles. 思ったより簡単です:この素晴らしいブログ投稿をチェックしてください. これは次のようになります。

CACHES = {
  'default': {
    'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
    'LOCATION': '127.0.0.1:11211',
  },
  'staticfiles': {
    'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    'LOCATION': 'staticfiles-filehashes'
  }
}
于 2013-02-15T16:21:23.283 に答える
16

django-compressorのようなものを使用することをお勧めします。このタイプのものを自動的に処理することに加えて、ファイルを自動的に結合して縮小し、ページの読み込みを高速化します。

完全に使用しなくても、同様の設定のガイダンスとしてコードを調べることができます。単純なStackOverflowの回答から得られるものよりも、十分に精査されています。

于 2012-02-03T15:52:50.923 に答える
8

ファイルの変更日を URL に追加する独自の templatetag を使用します: https://bitbucket.org/ad3w/django-sstatic

于 2012-03-16T18:02:12.470 に答える
7

Django 1.7が追加されました。キャッシュ システムを使用せず、実行時に計算されるハッシュの問題を解決するManifestStaticFilesStorageより良い代替手段です。CachedStaticFilesStorage

ドキュメントからの抜粋は次のとおりです。

CachedStaticFilesStorage はお勧めしません。ほとんどの場合、ManifestStaticFilesStorage の方が適しています。CachedStaticFilesStorage を使用すると、実行時にキャッシュ ミスが発生するとファイルのハッシュが必要になるため、パフォーマンスが低下します。ネストされたファイル パスの場合にファイル ハッシュが正しいことを確認するには、複数のファイル アクセスが必要になるため、リモート ファイル ストレージでは、キャッシュ ミス時にファイルをハッシュするために数回のラウンドトリップが必要です。

使用するには、次の行を に追加するだけですsettings.py

STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

そして、実行しpython manage.py collectstaticます。MD5 を各静的ファイルの名前に追加します。

于 2018-07-18T10:25:05.833 に答える
2

URL には常にバージョン付きの URL パラメータがあり、メジャー リリースがあるときはいつでも URL パラメータのバージョンを変更するのはどうでしょうか。DNSでも。したがって、www.yourwebsite.com読み込まれる場合www.yourwebsite.com/index.html?version=1.0、メジャー リリース後にブラウザが読み込まれるはずですwww.yourwebsite.com/index.html?version=2.0

これはソリューション 1 に似ていると思います。ファイルを追跡する代わりに、ディレクトリ全体を追跡できますか? たとえば、/static/style/css?v=2.0できることよりもレートを上げ/static-2/style/cssたり、さらに細かくしたりします/static/style/cssv2/

于 2012-02-03T15:08:48.137 に答える
1

@deathangel908 コードの更新があります。今では、S3 ストレージ (および私が考えるその他のストレージ) でもうまく機能します。違いは、ファイル コンテンツを取得するために静的ファイル ストレージを使用することです。オリジナルは S3 では動作しません。

appname/templatetags/md5url.py:

import hashlib
import threading
from django import template
from django.conf import settings
from django.contrib.staticfiles.storage import staticfiles_storage

register = template.Library()


class UrlCache(object):
    _md5_sum = {}
    _lock = threading.Lock()

    @classmethod
    def get_md5(cls, file):
        try:
            return cls._md5_sum[file]
        except KeyError:
            with cls._lock:
                try:
                    md5 = cls.calc_md5(file)[:8]
                    value = '%s%s?v=%s' % (settings.STATIC_URL, file, md5)
                except OSError:
                    value = settings.STATIC_URL + file
                cls._md5_sum[file] = value
                return value

    @classmethod
    def calc_md5(cls, file_path):
        with staticfiles_storage.open(file_path, 'rb') as fh:
            m = hashlib.md5()
            while True:
                data = fh.read(8192)
                if not data:
                    break
                m.update(data)
            return m.hexdigest()


@register.simple_tag
def md5url(model_object):
    return UrlCache.get_md5(model_object)
于 2016-04-03T03:08:02.917 に答える
1

このソリューションの主な利点は、テンプレートを変更する必要がないことです。

これにより、ビルド バージョンが に追加されSTATIC_URL、Web サーバーはそれをRewriteルールで削除します。

設定.py

# build version, it's increased with each build
VERSION_STAMP = __versionstr__.replace(".", "")
# rewrite static url to contain the number
STATIC_URL = '%sversion%s/' % (STATIC_URL, VERSION_STAMP)

したがって、最終的な URL は、たとえば次のようになります。

/static/version010/style.css

そして、Nginxにはそれを書き直すルールがあります/static/style.css

location /static {
    alias /var/www/website/static/;
    rewrite ^(.*)/version([\.0-9]+)/(.*)$ $1/$3;
}
于 2016-04-03T03:21:00.177 に答える