2010-11-04 3 views
2

Best Practices for Speeding Up Your Website états de Yahoo:Comment mettre du JavaScript en bas des pages Django lors de l'utilisation de templatetags?

Scripts mettre au fond

qu'il existe deux types de scripts dans mon application Django:

  1. Scripts inclus dans ma base (par exemple héritées du passé) modèle; et
  2. Les scripts écrits modèles à l'intérieur instanciées par templatetags

scripts pour soutenir le contrôle de l'interface utilisateur ne sont pas nécessairement une partie du modèle de leur étiquette de modèle de support pour gérer des choses comme des identifiants uniques et de conserver le code dépendant ensemble. Le problème est que si je suis les conseils de Yahoo et que je mets les bibliothèques (# 1) au bas de la page, 100% des scripts inclus en ligne (# 2) échoueront car les bibliothèques n'ont pas été chargées et analysé encore.

Je ne peux pas étendre un élément {% block%} dans mon gabarit de base car tout ce que je fais dans le contexte du gabarit ne se propagera pas à l'extérieur pour éviter les conflits de noms de variables (selon Django's Documentation).

Quelqu'un at-il une idée de comment je peux reporter le JavaScript de mes modèles de templatetags à rendre au fond de mon modèle de base?

Répondre

3

J'ai généralement une configuration de modèle de base comme celui-ci. Ensuite, je peux étendre ce modèle de base et ne remplacer que les blocs dont je me soucie. Je mets tout javascript qui ne doit pas être dans l'en-tête de js-foot et parce qu'il se trouve en bas du template il va se charger en dernier. Si vous devez vous déplacer là où votre javascript se charge, il vous suffit de déplacer le bloc js-foot dans le template de base.

Rien d'extraordinaire mais ça marche.

+0

C'est un modèle que j'ai commencé à adopter dans mes derniers projets, Ken. Merci pour votre réponse; Je le marque comme la réponse acceptée parce que c'est simple et cela fonctionne. Malheureusement, cela ne résout toujours pas le problème avec l'intégration de scripts dans templatetags, mais il semble qu'il n'y ait aucun moyen possible de faire cela de la façon dont les choses sont construites en ce moment. – isolationism

+2

Cette méthode échoue si vous avez Javascript dans les modèles partiels appelés en utilisant la balise de modèle 'include'. Ces fichiers d'inclusion ne peuvent en aucun cas ajouter leur code HTML à l'un des blocs du modèle principal. – LS55321

1

Envelopper les scripts que vous incluez en ligne dans

jQuery (function() {...});

Qui s'exécutera lorsque le DOM est prêt et que les scripts ont été téléchargés.

Une autre option pourrait être de créer une sorte de balise de modèle personnalisé comme:

{% inlinescript %} 
// some javascript code. 
{% endinlinescript %} 

que vous pourriez utiliser pour agréger des scripts inline comme produit d'exécution. Vous aurez besoin d'agréger ces données lorsque votre modèle sera analysé - ce qui devient délicat car les balises de gabarit ont des contextes différents et c'est quelque chose que vous voudriez stocker dans un contexte global dans une variable personnalisée, par exemple inline_scripts. Je regarderais la façon dont Django implémente les différentes constructions with ... as .. dans la bibliothèque de modèles par défaut pour un exemple de comment ajouter votre propre variable à un contexte.

Ensuite, au bas de votre page, vous pouvez faire {{inline_scripts}}.

La solution la plus simple est le jQuery.ready(function(){})/jQuery(function(){ }) (Les deux méthodes sont synonymes).

Ou vous pourriez vouloir reconsidérer le conseil de Yahoo. Il y a des choses positives à propos de l'insertion de votre javascript - cela peut réduire FOUC/FOUBC (Flash du contenu non-géré). Yahoo a tendance à avoir une sorte de pédantisme - (il suffit de regarder l'API YUI;). Si vous avez besoin de réécrire des parties de votre application pour une amélioration des performances moyennement perceptible, cela pourrait ne pas valoir le coup.


Pour faire l'agrégation script (captureas initialement basé hors sur django-extraits):

@register.tag(name='aggregate') 
def do_aggregate(parser, token): 
    try: 
     tag_name, args = token.contents.split(None, 1) 
    except ValueError: 
     raise template.TemplateSyntaxError("'aggregate' node requires a variable name.") 
    nodelist = parser.parse(('endaggregate',)) 
    parser.delete_first_token() 
    return AggregateNode(nodelist, args) 

class AggregateNode(Node): 
    def __init__(self, nodelist, varname): 
     self.nodelist = nodelist 
     self.varname = varname 

    def render(self, context): 
     output = self.nodelist.render(context) 
     if context.has_key(self.varname): 
      context[self.varname] += output 
     else: 
      context[self.varname] = output 
     return '' 

Utilisation:

{% aggregate inline_scripts %} 
var foo = 'bar'; 
{% endaggregate %} 

... template code 

{% aggregate inline_scripts %} 
var baz = 'bar'; 
{% endaggregate %} 

... somewhere near the bottom of your page 

{{ inline_scripts }} 
+1

jQuery() ne fonctionnera pas, parce que jQuery est pas encore défini. Ça va jeter une erreur. C'est la nature du problème - vous ne pouvez pas appeler jQuery tant qu'il n'est pas défini, et le définir en premier signifie ignorer les conseils de Yahoo. L'autre méthode est plus proche de ce que je veux faire, mais comme vous le dites, c'est difficile - comment le faire réellement? – isolationism

+0

Huh, maintenant cela * semble * intéressant. Je vais essayer plus tard et faire un rapport. Merci d'avoir pris le temps de mettre ça ensemble. aller voter cela comme il devrait faire exactement ce que je cherche. – isolationism

+0

Donc, après avoir étudié ce matin, ce script ne fait rien d'utile - parce que l'ajout au contexte LOCAL qui est déjà un template-templat ne l'expose pas au contexte GLOBAL du modèle de la page entière. Toujours à la recherche d'une réponse qui résout ce problème. – isolationism

Questions connexes