2012-02-10 5 views
1

Existe-t-il un moyen de détecter les modèles inutilisés dans un projet Django?Django: Détecter les modèles inutilisés

Avant Django 1.3, cela aurait été possible avec une simple fonction d'appariement de chaînes comme this one. Mais depuis la version 1.3, il existe des vues basées sur des classes génériques qui génèrent automatiquement un template_name, si vous ne le surchargez pas (par exemple, DetailView). En outre, si vous remplacez les modèles de modules tiers, ces modèles ne sont utilisés nulle part directement dans vos vues.

Peut-être que cela pourrait être fait en explorant toutes les définitions d'URL, en chargeant les vues correspondantes et en obtenant le template_name?

+0

Si vous êtes inquiet, vous n'utilisez pas des modèles générés par des vues à base de classe, vous n'utilisez pas ces vues soit (bien à moins que vous surchargeons) je nettoyer les vues :-) –

+0

@ ArgsKwargs Je ne comprends pas vraiment votre commentaire. De toute façon, je pensais à une approche générique de ce problème qui fonctionne dans tous les cas. Ceci est particulièrement utile pour les projets hérités. –

+0

Django ne charge pas les modèles inutilisés. Vous n'avez pas besoin de vous en préoccuper du tout – ramusus

Répondre

0

Il est impossible de détecter des modèles inutilisés pour certains, même en l'absence de vues génériques, parce que vous pouvez toujours écrire du code comme ceci:

get_template(any_code_you_like()).render(context) 

Ainsi, même avant Django 1.3 les modèles-django-utilisé application que vous avez lié à ne pouvait avoir travaillé pour des projets qui respectaient une sorte de discipline sur l'utilisation de modèles. (Par exemple, ayant toujours une chaîne littérale comme argument de modèle à des fonctions comme get_template et render_to_response.)

Chargement tous les points de vue ne serait pas suffisante soit: une vue peut utiliser différents modèles dans des circonstances différentes:

def my_view(request): 
    if request.user.is_authenticated(): 
     return render(request, 'template1.html') 
    else: 
     return render(request, 'template2.html') 

Et bien sûr, les modèles ne peuvent pas être utilisés par les vues, mais par d'autres parties du système (par exemple, les messages électroniques).

+0

Merci. Je m'y attendais déjà, mais je ne savais pas s'il y avait une possibilité à laquelle je n'avais pas pensé :) –

1

J'étais curieux de savoir si vous pouviez le faire en tapant/décorant mon get_template à la place. Je pense que vous pouvez, mais vous devez trouver toutes les fonctions de chargement de modèle (j'en ai deux dans mon exemple ci-dessous).

J'ai utilisé wrapt quand j'ai remarqué qu'il allait au-delà de loader.get_template, mais il semble très bien faire l'affaire. Bien sûr, gardez ces 50000 km loin de prod, mais ...

Maintenant, la chose à suivre est que je conduis ceci avec des tests unitaires et nosetests donc, si vous avez une couverture de branche complète de votre modèle en utilisant Code Python, vous devriez être en mesure d'obtenir la plupart des modèles (en supposant que je n'ai manqué aucune des fonctions de type get_template).

dans settings.py

Ceci est le "cerveau" de patch get_template & co.

import wrapt 
import django.template.loader 
import django.template.engine 

def wrapper(wrapped, instance, args, kwargs): 

    #concatenate the args vector into a string. 
    # print "\n\n\n\n%s\nI am a wrapper \nusage:%s\n%s\n\n\n\n\n" % ("*"*80, usage, "*"*80) 
    try: 
     return wrapped(*args, **kwargs) 
    finally: 
     usage = ",".join([unicode(arg) for arg in args if arg]) 
     track_usage(usage) 

#you have to wrap whatever is loading templates... 
#imported django module + class/method/function path of what needs to be 
#wrapped within that module. comment those 2 lines out and you are back to 
#normal 


wrapt.wrap_function_wrapper(django.template.loader, 'get_template', wrapper) 
wrapt.wrap_function_wrapper(django.template.engine, 'Engine.find_template', wrapper) 

Voir safely-applying-monkey-patches-in-python pour plus de détails sur wrapt. En fait, plus facile à utiliser qu'à comprendre les docs, les décorateurs me font mal au cerveau. De plus, pour savoir quelles fonctions django effectuaient les charges réelles, j'ai mal orthographié certains noms de modèles dans le code et dans les modèles, j'ai exécuté des tests unitaires et j'ai regardé les empilements pour les exceptions de modèles manquants.

Ceci est ma fonction plutôt mal écrit qui ajoute à un ensemble et le met en une sortie JSON ....

def track_usage(usage): 
    fnp_usage = "./usage.json" 

    try: 
     with open(fnp_usage, "r") as fi: 
      data = fi.read() 
      #read the set of used templates from the json file 
      j_data = json.loads(data) 
      s_used_file = set(j_data.get("li_used")) 

    except (IOError,),e: 
      s_used_file = set() 
      j_data = dict() 

    s_used_file.add(usage) 
    #convert the set back to a list for json compatibility 
    j_data["li_used"] = list(s_used_file) 

    with open(fnp_usage, "w") as fo: 
     json.dump(j_data, fo) 

et la sortie (avec un script pour formater):

import sys 
import json 
fnp_usage = sys.argv[1] 


with open(fnp_usage, "r") as fi: 
    data = fi.read() 
    #read the set of used templates from the json file 
    j_data = json.loads(data) 
    li_used_file = j_data.get("li_used") 
    li_used_file.sort() 

    print "\n\nused templates:" 
    for t in li_used_file: 
     print(t) 

De envelopper les 2 fonctions ci-dessus, il semble avoir pris étend,% comprend et get_templates droits, ainsi que la liste -type de modèles utilisés par les vues basées sur les classes. Il a même attrapé mes modèles générés dynamiquement qui ne sont même pas sur le système de fichiers, mais se charger avec un chargeur personnalisé.

used templates: 
bootstrap/display_form.html 
bootstrap/errors.html 
bootstrap/field.html 
bootstrap/layout/baseinput.html 
bootstrap/layout/checkboxselectmultiple.html 
bootstrap/layout/field_errors.html 
bootstrap/layout/field_errors_block.html 
bootstrap/layout/help_text.html 
bootstrap/layout/help_text_and_errors.html 
bootstrap/layout/radioselect.html 
bootstrap/whole_uni_form.html 
django_tables2/table.html 
dynamic_template:db:testdb:name:pssecurity/directive.PrimaryDetails.json 
uni_form/layout/div.html 
uni_form/layout/fieldset.html 
websec/__base.html 
websec/__full12.html 
websec/__l_right_sidebar.html 
websec/bootstrapped_home.html 
websec/changedb.html 
websec/login.html 
websec/requirejs_config.html 
websec/topnav.html 
websec/user_msg.html 
Questions connexes