web-dev-qa-db-fra.com

Django n'actualisera pas les staticfiles

C'est énervant. J'ai un fichier javascript référencé sur un template Django:

 <script src="{% static 'js/login.js' %} "></script>

J'ai apporté des modifications à ce fichier JS. Ensuite, j'actualise la page et je ne vois pas les changements se produire.

Si je supprime le javascript du fichier et le mets dans le code HTML, cela fonctionne correctement, mais si j'essaie de le faire en utilisant le fichier js externe, il ne le fait pas. J'ai essayé de fermer le serveur et d'exécuter plusieurs fois le serveur d'exécution. J'ai également essayé de passer de Firefox à Chrome. Cela n'a aucun sens. S'il vous plaît, aidez-moi à comprendre, je peux me permettre d'inclure tous les fichiers js dans le code HTML, mais cela me dérange de ne plus pouvoir le faire normalement.

Plus de détails sur cette erreur (la chose la plus étrange que j'ai trouvée # $ &% #):

Le javascript ressemble à ceci:

old_sentence = "Dig that hole, forget the Sun"  // this is what I want to change
$("#jqselector").text(old_sentence)

new_sentence = "Run, rabbit, run"  // this is the new sentence, it just won't show up.

Donc, j'ai changé le js et redémarrer le serveur, toujours le html montre l'ancienne phrase. Ensuite, j'ai supprimé la référence au fichier login.js et mis tous les js à l'intérieur des balises de script dans le code HTML. Bien entendu, la nouvelle phrase apparaît. Ensuite, j'inclus le fichier login.js, commente le js à l'intérieur du html MAIS je supprime tout le contenu du fichier login.js, ce qui en fait un fichier vide ... mais l'ancienne phrase apparaît toujours. Par conséquent, l'ancien fichier login.js doit être encaissé quelque part, je ne le sais pas. Ensuite, j'ouvre Chrome et j'essaie à nouveau, même problème. 

Qu'est-ce que ça peut être? Existe-t-il une option pour forcer Django à actualiser les fichiers static? Je pensais que redémarrer le serveur était suffisant. .. dois-je redémarrer mon ordinateur? :/lol.

31
  • Effacement du fichier statique python manage.py collectstatic --noinput --clear. Cela effacera la statique au préalable.

  • Effacer le cache du navigateur

  • Ajoutez une chaîne aléatoire après l’inclusion du fichier js, par exemple jquery.js? Rand = 23423423, à chaque chargement.

Cela vous a-t-il aidé?

32
Danial Tz

Il semble que le fichier javascript soit mis en cache dans les deux navigateurs. Dans Chrome, vous pouvez effacer le cache en appuyant sur Ctrl + Shift + Del et en cochant simplement "Images et fichiers en cache". Firefox a probablement un raccourci similaire. 

Vous pouvez consulter cette question sur des astuces pour désactiver complètement la mise en cache de fichiers statiques sur votre serveur de développement. 

19
knbk

Vous devez supprimer le cache du navigateur. Cette balise de gabarit générera un uuid basé sur le temps lorsque DEBUG=True. Sinon, il cherchera une variable d'environnement PROJECT_VERSION. Si cela n'est pas trouvé, un numéro de version statique sera généré.

import os
import uuid
from Django import template                                                                                                              
from Django.conf import settings                                                                                                         

register = template.Library()                                                                                                            

@register.simple_tag(name='cache_bust')                                                                                                  
def cache_bust():                                                                                                                        

    if settings.DEBUG:                                                                                                                   
        version = uuid.uuid1()                                                                                                           
    else:                                                                                                                                
        version = os.environ.get('PROJECT_VERSION')                                                                                       
        if version is None:                                                                                                              
            version = '1'                                                                                                                

    return '__v__={version}'.format(version=version)

Vous utiliseriez un modèle comme celui-ci:

{% load cache_bust %}

<link rel="stylesheet" href="{% static "css/project.css" %}?{% cache_bust %}"/>

et voici le résultat obtenu:

<link rel="stylesheet" href="/static/css/project.css?__v__=7d88de4e-7258-11e7-95a7-0242ac130005"/>
13
Derrick Petzold

J'ai également lutté avec ce problème pendant des heures. J'ai essayé d'injecter une chaîne aléatoire en utilisant Javascript, mais cette méthode semble stupide et laide. Un moyen possible de gérer ce problème consiste à introduire une balise personnalisée. Voir ce document pour plus de détails:

Plus précisément, vous devez créer un package appelé templatetags dans les applications que vous avez créées (ou en créer un si vous le souhaitez). Et vous créez n'importe quel fichier dans ce paquet et écrivez quelque chose comme ceci:

from Django import template
from Django.utils.crypto import get_random_string
from Django.templatetags import static

register = template.Library()


class StaticExtraNode(static.StaticNode):

    def render(self, context):
        return super().render(context) + '?v=' + get_random_string(32)


@register.tag('static_no_cache')
def do_static_extra(parser, token):
    return StaticExtraNode.handle_token(parser, token)


def static_extra(path):
    return StaticExtraNode.handle_simple(path)

alors vous pouvez utiliser la balise {% static_no_cache '.../.../path...' %} pour créer un chemin avec des arguments aléatoires!

J'espère que cela aiderait!

2
Scott Chang

Une solution consiste à modifier les paramètres comme suit:

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

Cela crée une copie du fichier statique avec un hachage de contenu dans le nom du fichier (lors de l'exécution de collectstatic). Ainsi, lorsque le contenu est modifié, le nom du fichier est modifié et l'ancien cache ne sera pas utilisé. Le seul problème avec ceci est qu'il n'est pas utilisé en mode DEBUG = True, vous devez donc effectuer une recharge par décalage pour effectuer une recharge dure.

Vous pouvez lire les docs sur ManifestStaticFilesStorage pour plus d’informations.

EDIT: J'ai trouvé une solution pour s'assurer que les fichiers statiques ne sont pas mis en cache dans dev et l'ai postée sur une autre question.

0
Tim Tisdall

Si vous ne souhaitez pas actualiser le cache du navigateur à chaque fois que vous modifiez vos fichiers CSS et JavaScript, ou tout en modifiant le style des images, vous devez définir STATIC_URLdynamiquement avec un composant de chemin d'accès différent. Avec l'URL qui change de manière dynamique, le navigateur du visiteur force le chargement de tous les nouveaux fichiers statiques non mis en cache chaque fois que le code est mis à jour. Dans cette recette, nous allons définir un chemin dynamique pour STATIC_URL en utilisant l'heure de la dernière modification dans os.

import os
from datetime import datetime    

def get_file_changeset(absolute_path):
    timestamp = max(map(lambda x: os.path.getmtime(x[0]), os.walk(os.path.join(absolute_path, 'static'))))
    try:
        timestamp = datetime.utcfromtimestamp(int(timestamp))
    except ValueError:
        return ""
    changeset = timestamp.strftime('%Y%m%d%H%M%S')
    return changeset

Et le prochain changement dans votre SETTINGS

from utils.misc import get_file_changeset
STATIC_URL = "/static/%s/" % get_file_changeset(BASE_DIR)

Comment ça marche:
La get_file_changeset()function prend le répertoire absolute_path en tant que paramètre et appelle la os.path.getmtime() pour chaque fichier de chaque répertoire imbriqué et recherche le dernier fichier édité (avec sa durée maximale). L'horodatage est analysé; converti en chaîne comprenant l'année, le mois, le jour, l'heure, les minutes et les secondes; revenu; et inclus dans la définition de STATIC_URL.

Remarque: Avec cela, vous devez recharger le serveur de développement à chaque fois que vous modifiez vos fichiers statiques.

0
Chiefir

Si rien d'autre ne fonctionne, recherchez le nom de fichier dans le projet et recherchez une copie inattendue. Si vous avez enregistré à un moment donné au mauvais endroit (application différente) ou que vous avez fractionné une nouvelle application à partir d'une ancienne, la priorité de chargement peut vous jouer des tours.

0
pragmar

Au lieu d'utiliser des solutions compliquées, vous pouvez ajouter des paramètres supplémentaires à vos inclus dans les modèles.

Pour statique comprend:

<script src="{% static 'js/polls/polls.js' %}?version=1"></script>

Pour direct comprend:

<link rel="stylesheet" type="text/css" href="/site_media/css/style.css?version=1" />  

Notez le ?version=1 dans le code. Chaque fois que vous modifiez le fichier css/js, modifiez cette version dans le modèle afin que le navigateur soit obligé de recharger le fichier.

Et si vous voulez éviter la mise en cache pour une raison inconnue, vous pouvez utiliser l’horodatage actuel au lieu de la version:

<link rel="stylesheet" type="text/css" href="/site_media/css/style.css?{% now "U" %}" />
0
The Godfather

Pour actualiser les fichiers statiques, exécutez à nouveau python manage.py collectstatic.

0
catavaran