web-dev-qa-db-fra.com

Favori Django Conseils et fonctionnalités?

Inspiré par la série de questions 'Caractéristiques cachées de ...', je suis curieux d'entendre parler de vos conseils préférés Django ou des fonctionnalités moins connues mais utiles que vous connaissez.

  • Merci d'inclure un seul conseil par réponse.
  • Ajoutez Django les exigences de version s’il en existe.
308
Haes

Je vais juste commencer par un conseil de moi :)

Utilisez os.path.dirname () dans settings.py pour éviter les noms de répertoire codés en dur.

Ne codez pas le chemin d'accès dans votre fichier settings.py si vous souhaitez exécuter votre projet dans des emplacements différents. Utilisez le code suivant dans settings.py si vos modèles et fichiers statiques sont situés dans le répertoire Django project:

# settings.py
import os
PROJECT_DIR = os.path.dirname(__file__)
...
STATIC_DOC_ROOT = os.path.join(PROJECT_DIR, "static")
...
TEMPLATE_DIRS = (
    os.path.join(PROJECT_DIR, "templates"),
)

Crédits: J'ai eu cette astuce du screencast ' Django From The Ground Up '.

222
Haes

Installez Extensions de commande Django et pygraphviz , puis lancez la commande suivante pour obtenir une apparence vraiment agréable Django:

./manage.py graph_models -a -g -o my_project.png
130
Haes

Utilisez Django-ennoying'srender_to décorateur au lieu de render_to_response.

@render_to('template.html')
def foo(request):
    bars = Bar.objects.all()
    if request.user.is_authenticated():
        return HttpResponseRedirect("/some/url/")
    else:
        return {'bars': bars}

# equals to
def foo(request):
    bars = Bar.objects.all()
    if request.user.is_authenticated():
        return HttpResponseRedirect("/some/url/")
    else:
        return render_to_response('template.html',
                              {'bars': bars},
                              context_instance=RequestContext(request))

Modifié pour indiquer que le renvoi d'une réponse HttpResponse (telle qu'une redirection) court-circuitera le décorateur et fonctionnera comme vous le souhaitez.

119
user20955

J'utilise un ensemble de balises personnalisées sur tous les modèles de mon site. À la recherche d'un moyen de charger automatiquement le fichier (DRY, rappelez-vous?), J'ai trouvé ce qui suit:

from Django import template
template.add_to_builtins('project.app.templatetags.custom_tag_module')

Si vous mettez cela dans un module chargé par défaut (votre urlconf principal par exemple), les balises et filtres de votre module de balises personnalisées sont disponibles dans tous les modèles, sans utiliser {% load custom_tag_module %}.

L'argument passé à template.add_to_builtins() peut être n'importe quel chemin de module; votre module de balise personnalisé ne doit pas nécessairement vivre dans une application spécifique. Par exemple, il peut également s'agir d'un module dans le répertoire racine de votre projet (par exemple. 'project.custom_tag_module').

102
Steef

Virtualenv + Python = économiseur de vie si vous travaillez sur plusieurs Django projets et il est possible qu'ils ne le fassent pas tous). dépendent de la même version de Django/une application.

97
phillc

Ne codez pas vos URL en dur!

Utilisez noms d'URL à la place et la fonction reverse pour obtenir l'URL elle-même.

Lorsque vous définissez vos mappages d'URL, donnez des noms à vos URL.

urlpatterns += ('project.application.views'
   url( r'^something/$', 'view_function', name="url-name" ),
   ....
)

Assurez-vous que le nom est unique par URL.

J'ai généralement un format cohérent "project-appplication-view", par exemple. "cbx-forum-thread" pour une vue de fil.

[~ # ~] met à jour [~ # ~] (vole sans vergogne ajout d'ayaz ):

Ce nom peut être utilisé dans les modèles avec la balise url .

88
hasen

Utilisez barre d’outils de débogage de Django . Par exemple, cela permet d'afficher toutes les requêtes SQL effectuées lors du rendu, mais vous pouvez également afficher la trace de pile pour chacune d'entre elles.

82
Eugene Morozov

N'écrivez pas vos propres pages de connexion. Si vous utilisez Django.contrib.auth.

Le vrai secret est que si vous utilisez également Django.contrib.admin et Django.template.loaders.app_directories.load_template_source se trouve dans vos chargeurs de modèles, vous pouvez également obtenir vos modèles gratuitement!

# somewhere in urls.py
urlpatterns += patterns('Django.contrib.auth',
    (r'^accounts/login/$','views.login', {'template_name': 'admin/login.html'}),
    (r'^accounts/logout/$','views.logout'),
)
80

Les processeurs de contexte sont géniaux.

Supposons que vous avez un modèle d'utilisateur différent et que vous souhaitez l'inclure dans chaque réponse. Au lieu de faire ceci:

def myview(request, arg, arg2=None, template='my/template.html'):
    ''' My view... '''
    response = dict()
    myuser = MyUser.objects.get(user=request.user)
    response['my_user'] = myuser
    ...
    return render_to_response(template,
                              response,
                              context_instance=RequestContext(request))

Les processus de contexte vous permettent de transmettre n'importe quelle variable à vos modèles. Je mets généralement le mien dans 'my_project/apps/core/context.py:

def my_context(request):
    try:
        return dict(my_user=MyUser.objects.get(user=request.user))
    except ObjectNotFound:
        return dict(my_user='')

Dans votre settings.py ajouter la ligne suivante à votre TEMPLATE_CONTEXT_PROCESSORS

TEMPLATE_CONTEXT_PROCESSORS = (
    'my_project.apps.core.context.my_context',
    ...
)

Maintenant, chaque fois qu'une demande est faite, elle inclut le my_user touche automatiquement.

Aussi signaux gagner.

J'ai écrit un article à ce sujet il y a quelques mois sur mon blog, alors je vais simplement couper et coller:

Out of the box Django vous donne plusieurs signaux extrêmement utiles. Vous avez la possibilité de faire des choses avant et après l'enregistrement, l'initiation, la suppression ou même lorsqu'une demande est en cours de traitement. éloignez-vous des concepts et montrez comment ils sont utilisés. Supposons que nous avons un blog

from Django.utils.translation import ugettext_lazy as _
class Post(models.Model):
    title = models.CharField(_('title'), max_length=255)
    body = models.TextField(_('body'))
    created = models.DateTimeField(auto_now_add=True)

Vous souhaitez donc notifier l’un des nombreux services de ping sur les blogs pour lesquels nous avons créé une nouvelle publication, reconstruire le cache des publications les plus récentes et envoyer un tweet à ce sujet. Avec les signaux, vous avez la possibilité de faire tout cela sans avoir à ajouter de méthodes à la classe Post.

import Twitter

from Django.core.cache import cache
from Django.db.models.signals import post_save
from Django.conf import settings

def posted_blog(sender, created=None, instance=None, **kwargs):
    ''' Listens for a blog post to save and alerts some services. '''
    if (created and instance is not None):
        Tweet = 'New blog post! %s' instance.title
        t = Twitter.PostUpdate(settings.Twitter_USER,
                               settings.Twitter_PASSWD,
                               Tweet)
        cache.set(instance.cache_key, instance, 60*5)
       # send pingbacks
       # ...
       # whatever else
    else:
        cache.delete(instance.cache_key)
post_save.connect(posted_blog, sender=Post)

Voilà, en définissant cette fonction et en utilisant le signal post_init pour connecter la fonction au modèle Post et l'exécuter après son enregistrement.

67
notzach

Quand j'ai commencé, je ne savais pas qu'il y avait un Paginator , assurez-vous de connaître son existence !!

57
hasen

Utilisez IPython pour accéder à votre code à tout niveau et déboguer en utilisant la puissance d’IPython. Une fois que vous avez installé IPython, insérez ce code partout où vous souhaitez déboguer:

from IPython.Shell import IPShellEmbed; IPShellEmbed()()

Ensuite, actualisez la page, allez dans la fenêtre de votre serveur d'exécution et vous serez dans une fenêtre interactive IPython.

J'ai un extrait configuré dans TextMate, je viens donc de taper ipshell et d'appuyer sur tab. Je ne pourrais pas m'en passer.

47
sheats

Exécutez un serveur de développement SMTP qui produira tout ce qui lui est envoyé (si vous ne voulez pas installer réellement SMTP sur votre serveur dev.)

ligne de commande:

python -m smtpd -n -c DebuggingServer localhost:1025
43
Carl G

Depuis le documentation Django-admin :

Si vous utilisez le shell Bash, envisagez d'installer le script d'achèvement Django bash, qui réside dans extras/Django_bash_completion dans la distribution Django. Elle permet la complétion par des tabulations de Django-admin.py et manage.py commandes, afin que vous puissiez, par exemple ...

  • Tapez Django-admin.py.
  • Appuyez sur [TAB] pour voir toutes les options disponibles.
  • Tapez sql, puis [TAB], pour voir toutes les options disponibles dont le nom commence par sql.
41
John

La facilité ./manage.py runserver_plus Fournie avec Django_extensions est vraiment géniale.

Il crée une page de débogage améliorée qui, entre autres choses, utilise le débogueur Werkzeug pour créer des consoles de débogage interactives pour chaque point de la pile (voir la capture d'écran). Il fournit également une méthode de débogage très utile dump() pour afficher des informations sur un objet/cadre.

enter image description here

Pour installer, vous pouvez utiliser pip:

pip install Django_extensions
pip install Werkzeug

Ajoutez ensuite 'Django_extensions' À votre INSTALLED_APPS Tuple dans settings.py Et démarrez le serveur de développement avec la nouvelle extension:

./manage.py runserver_plus

Cela changera la façon dont vous déboguez.

40
DavidWinterbottom

Lors de la tentative d’échange de données entre Django et une autre application, request.raw_post_data est un bon ami. Utilisez-le pour recevoir et traiter de manière personnalisée, par exemple, des données XML.

Documentation: http://docs.djangoproject.com/en/dev/ref/request-response/

37
chefsmart

J'aime utiliser les projets Python du débogueur pdb pour déboguer Django.

Ceci est un lien utile pour apprendre à l'utiliser: http://www.ferg.org/papers/debugging_in_python.html

37
Harold

Ajouter assert False dans votre code de vue pour vider les informations de débogage.

35
zgoda

Utilisez Jinja2 aux côtés de Django.

Si vous trouvez que le Django est extrêmement restrictif (comme moi!), Vous n’aurez pas à vous en prendre à vous-même. Django est flexible, et le Le langage de modèle est vaguement couplé au reste du système. Il vous suffit donc de brancher un autre langage de modèle et de l'utiliser pour afficher vos réponses http!

J'utilise Jinja2 , c'est presque comme une version améliorée du langage de template Django, il utilise la même syntaxe et vous permet d'utiliser des expressions dans les instructions if! plus besoin de créer un if-tags personnalisé tel que if_item_in_list! vous pouvez simplement dire %{ if item in list %}, ou {% if object.field < 10 %}.

Mais ce n'est pas tout; il a beaucoup plus de fonctionnalités pour faciliter la création de modèles, que je ne peux pas toutes les parcourir ici.

35
hasen

Cela ajoute à la réponse ci-dessus à propos de noms d'URL Django et distribution d'URL inverse .

Les noms d'URL peuvent également être utilisés efficacement dans les modèles. Par exemple, pour un modèle d'URL donné:

url(r'(?P<project_id>\d+)/team/$', 'project_team', name='project_team')

vous pouvez avoir les éléments suivants dans les modèles:

<a href="{% url project_team project.id %}">Team</a>
33
ayaz

Étant donné que Django "les vues" doivent uniquement être des callables renvoyant une réponse HttpResponse, vous pouvez facilement créer des vues basées sur les classes telles que celles de Ruby sur Rails et d’autres frameworks.

Il y a plusieurs façons de créer des vues basées sur les classes, voici mon préféré:

from Django import http

class RestView(object):
    methods = ('GET', 'HEAD')

    @classmethod
    def dispatch(cls, request, *args, **kwargs):
        resource = cls()
        if request.method.lower() not in (method.lower() for method in resource.methods):
            return http.HttpResponseNotAllowed(resource.methods)
        try:
            method = getattr(resource, request.method.lower())
        except AttributeError:
            raise Exception("View method `%s` does not exist." % request.method.lower())
        if not callable(method):
            raise Exception("View method `%s` is not callable." % request.method.lower())
        return method(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        return http.HttpResponse()

    def head(self, request, *args, **kwargs):
        response = self.get(request, *args, **kwargs)
        response.content = ''
        return response

Vous pouvez ajouter toutes sortes d'autres choses, telles que le traitement conditionnel des demandes et l'autorisation, dans votre vue de base.

Une fois que vous avez configuré vos vues, votre urls.py ressemblera à ceci:

from Django.conf.urls.defaults import *
from views import MyRestView

urlpatterns = patterns('',
    (r'^restview/', MyRestView.dispatch),
)
27
mmalone

Au lieu d'utiliser render_to_response Pour lier votre contexte à un modèle et le restituer (ce que montrent habituellement les documents Django), utilisez la vue générique direct_to_template . Il fait la même chose que render_to_response Mais ajoute automatiquement RequestContext au contexte du modèle, autorisant implicitement l'utilisation de processeurs de contexte. Vous pouvez le faire manuellement en utilisant render_to_response, Mais pourquoi s'en préoccuper? C'est juste une autre étape à retenir et un autre LOC. En plus d'utiliser des processeurs de contexte, avoir RequestContext dans votre modèle vous permet de faire des choses comme:

<a href="{{MEDIA_URL}}images/frog.jpg">A frog</a> 

ce qui est très utile. En fait, +1 sur les vues génériques en général. La documentation Django les affiche principalement sous forme de raccourcis pour ne même pas avoir de fichier views.py pour les applications simples, mais vous pouvez également les utiliser dans vos propres fonctions d'affichage:

from Django.views.generic import simple

def article_detail(request, slug=None):
    article = get_object_or_404(Article, slug=slug)
    return simple.direct_to_template(request, 
        template="articles/article_detail.html",
        extra_context={'article': article}
    )
21
mazelife

Je n'ai pas assez de réputation pour répondre au commentaire en question, mais il est important de noter que si vous utilisez Jinja , il ne prend PAS en charge le caractère '-' dans les noms de blocs de modèles. , while while Django). Cela m’a causé beaucoup de problèmes et une perte de temps à essayer de retrouver le message d’erreur très obscur qu’il a généré.

20
user61000

Le Webdesign app est très utile pour commencer à concevoir votre site Web. Une fois importé, vous pouvez ajouter ceci pour générer un exemple de texte:

{% load webdesign %}
{% lorem 5 p %}
19
Ross Light

Django.db.models.get_model vous permet de récupérer un modèle sans l'importer.

James montre à quel point cela peut être pratique: "Conseils Django: écrire de meilleurs modèles de balises - Itération 4" .

19
vikingosegundo

Tout le monde sait qu'il existe un serveur de développement que vous pouvez exécuter avec "manage.py runserver", mais saviez-vous qu'il existe également une vue de développement permettant de servir des fichiers statiques (CSS/JS/IMG)?

Les nouveaux arrivants sont toujours perplexes car Django ne fournit aucun moyen de servir des fichiers statiques. C’est parce que l’équipe de développeurs pense que c’est le travail d’un serveur Web réel.

Mais lors du développement, vous ne souhaitez peut-être pas configurer Apache + mod_wisgi, c'est lourd. Ensuite, vous pouvez simplement ajouter ce qui suit à urls.py:

(r'^site_media/(?P<path>.*)$', 'Django.views.static.serve',
        {'document_root': '/path/to/media'}),

Votre CSS/JS/IMG sera disponible sur www.votresite.com/site_media/.

Bien sûr, ne l'utilisez pas dans un environnement de production.

19
e-satis

J'ai appris celui-ci de la documentation de l'application sorl-thumbnails . Vous pouvez utiliser le mot clé "en tant que" dans les balises de modèle pour utiliser les résultats de l'appel ailleurs dans votre modèle.

Par exemple:

{% url image-processor uid as img_src %}
<img src="{% thumbnail img_src 100x100 %}"/>

Ceci est mentionné en passant dans la documentation de Django templatetag, mais en référence à des boucles uniquement. Ils ne vous disent pas que vous pouvez l’utiliser ailleurs (ailleurs?).

18
Joe Kueser

PyCharm IDE est un environnement agréable à coder et surtout à déboguer, avec support intégré pour Django.

16
Art

Django.views.generic.list_detail.object_list - Il fournit toutes les variables de logique et de modèle pour la pagination (une de ces tâches fastidieuses que j'ai écrites mille fois maintenant). Envelopper permet n'importe quelle logique dont vous avez besoin. Ce petit bijou m'a évité de nombreuses heures d'erreurs de débogage une par une dans mes pages "Résultats de la recherche" et rend la vue plus propre.

16
jds

Utilisez les migrations de base de données. Utilisez Sud .

14
vad

Utilisez xml_models pour créer Django des modèles qui utilisent un XML REST API (au lieu d'un SQL)). C'est très utile. en particulier lorsque vous modélisez des API tierces - vous obtenez la même syntaxe QuerySet que celle à laquelle vous êtes habitué. Vous pouvez l’installer à partir de PyPI.

XML à partir d'une API:

<profile id=4>
    <email>[email protected]</email>
    <first_name>Joe</first_name>
    <last_name>Example</last_name>
    <date_of_birth>1975-05-15</date_of_birth>
</profile>

Et maintenant en python:

class Profile(xml_models.Model):
    user_id = xml_models.IntField(xpath='/profile/@id')
    email = xml_models.CharField(xpath='/profile/email')
    first = xml_models.CharField(xpath='/profile/first_name')
    last = xml_models.CharField(xpath='/profile/last_name')
    birthday = xml_models.DateField(xpath='/profile/date_of_birth')

    finders = {
        (user_id,):  settings.API_URL +'/api/v1/profile/userid/%s',
        (email,):  settings.API_URL +'/api/v1/profile/email/%s',
    }

profile = Profile.objects.get(user_id=4)
print profile.email
# would print '[email protected]'

Il peut également gérer des relations et des collections. Nous l'utilisons tous les jours dans un code de production très utilisé, donc même s'il est en version bêta, il est très utilisable. Il contient également un bon nombre de stubs que vous pouvez utiliser dans vos tests.

(Avertissement: bien que je ne sois pas l'auteur de cette bibliothèque, je suis maintenant un committer, après avoir commis quelques commits mineurs)

14
godswearhats

Je viens de trouver ce lien: http://lincolnloop.com/Django-best-practices/#table-of-contents - "Meilleures pratiques de Django".

13
None-da

Au lieu d'évaluer tout le jeu de requêtes pour vérifier si vous avez obtenu des résultats, utilisez .exists () dans Django 1.2+ et .count () pour les versions précédentes.

Existe à la fois exist () et count () efface les clauses de commande d'ordre et récupère un entier de DB. Cependant, existe () retournera toujours 1 où nombre peut retourner des valeurs plus élevées sur lesquelles les limites seront appliquées manuellement. La source de has_result utilisée dans exist () et get_count utilisée dans count () pour les curieux.

Puisqu'ils renvoient tous les deux un seul entier, il n'y a pas d'instanciation de modèle, de chargement d'attributs de modèle en mémoire et pas de champs TextField importants échangés entre votre base de données et votre application.

Si vous avez déjà évalué la requête, .count () calcule len (cached_result) et .exists () calcule bool (cached_result)

Pas efficace - Exemple 1

books = Books.objects.filter(author__last_name='Brown')
if books:
    # Do something

Pas efficace - Exemple 2

books = Books.objects.filter(author__last_name='Brown')
if len(books):
    # Do something

Efficace - Exemple 1

books = Books.objects.filter(author__last_name='Brown')
if books.count():
    # Do something

Efficace - Exemple 2

books = Books.objects.filter(author__last_name='Brown')
if books.exists():
    # Do something
12
tarequeh

Si vous apportez des modifications au modèle

./manage.py dumpdata appname > appname_data.json  
./manage.py reset appname
Django-admin.py loaddata appname_data.json
12
Ezequiel Marquez

Utilisez signaux pour ajouter des méthodes d’accesseur à la volée.

J'ai vu cette technique dans Django-photologue : Pour tout objet Size ajouté, le signal post_init ajoutera les méthodes correspondantes au modèle Image. Si vous ajoutez un site géant , les méthodes permettant de récupérer l'image en résolution géante seront image.get_giant_url().

Les méthodes sont générées en appelant add_accessor_methods du post_init _ signal:

def add_accessor_methods(self, *args, **kwargs):
    for size in PhotoSizeCache().sizes.keys():
        setattr(self, 'get_%s_size' % size,
                curry(self._get_SIZE_size, size=size))
        setattr(self, 'get_%s_photosize' % size,
                curry(self._get_SIZE_photosize, size=size))
        setattr(self, 'get_%s_url' % size,
                curry(self._get_SIZE_url, size=size))
        setattr(self, 'get_%s_filename' % size,
                curry(self._get_SIZE_filename, size=size))

Voir le code source de photologue.models pour une utilisation dans le monde réel.

11
vikingosegundo

Supprimer les informations d'accès à la base de données de settings.py

Une chose que j'ai faite dans mon Django le site settings.py charge les informations d’accès à la base de données depuis un fichier dans /etc. De cette façon, la configuration de l'accès (hôte de la base de données, port, nom d'utilisateur, mot de passe) peut être différente pour chaque ordinateur et des informations sensibles telles que le mot de passe ne sont pas dans le référentiel de mon projet. Vous voudrez peut-être limiter l'accès aux travailleurs de la même manière, en leur permettant de se connecter avec un nom d'utilisateur différent.

Vous pouvez également transmettre les informations de connexion à la base de données, ou même simplement une clé ou un chemin d'accès à un fichier de configuration, via des variables d'environnement, et le gérer dans settings.py.

Par exemple, voici comment j'insère mon fichier de configuration de base de données:

g = {}
dbSetup = {}
execfile(os.environ['DB_CONFIG'], g, dbSetup)
if 'databases' in dbSetup:
    DATABASES = dbSetup['databases']
else:
    DATABASES = {
        'default': {
            'ENGINE': 'Django.db.backends.mysql',
            # ...
        }
    }

Inutile de dire que vous devez vous assurer que le fichier dans DB_CONFIG _ n'est accessible à aucun utilisateur en dehors des administrateurs de la base de données et Django lui-même. Le cas par défaut devrait faire référence Django à la propre base de données de test d'un développeur. Il peut également être une meilleure solution en utilisant le module ast au lieu de execfile, mais je n'ai pas encore fait de recherches à ce sujet.

Une autre chose que je fais est d’utiliser des utilisateurs distincts pour les tâches d’administrateur de base de données par rapport à tout le reste. Dans mon manage.py, J'ai ajouté le préambule suivant:

# Find a database configuration, if there is one, and set it in the environment.
adminDBConfFile = '/etc/Django/db_admin.py'
dbConfFile = '/etc/Django/db_regular.py'
import sys
import os
def goodFile(path):
    return os.path.isfile(path) and os.access(path, os.R_OK)
if len(sys.argv) >= 2 and sys.argv[1] in ["syncdb", "dbshell", "migrate"] \
    and goodFile(adminDBConfFile):
    os.environ['DB_CONFIG'] = adminDBConfFile
Elif goodFile(dbConfFile):
    os.environ['DB_CONFIG'] = dbConfFile

Où la config dans /etc/Django/db_regular.py est destiné à un utilisateur n'ayant accès qu'à la base de données Django avec SELECT, INSERT, UPDATE et DELETE et /etc/Django/db_admin.py est destiné à un utilisateur disposant de ces autorisations, plus CREATE, DROP, INDEX, ALTER et LOCK TABLES. (La commande migrate provient de South .) Cela me protège un peu du code Django qui dérange mon schéma au moment de l'exécution et limite les dégâts une attaque par injection SQL peut provoquer (bien que vous deviez quand même vérifier et filtrer toutes les entrées utilisateur).

(Copié de ma réponse à ne autre question )

11
Mike DeSimone

Au lieu d’exécuter le Django dev sur localhost, exécutez-le sur une interface réseau appropriée. Par exemple:

python manage.py runserver 192.168.1.110:8000

ou

python manage.py runserver 0.0.0.0:8000

Ensuite, vous pouvez non seulement utiliser facilement Fiddler ( http://www.fiddler2.com/fiddler2/ ) ou un autre outil comme HTTP Debugger ( http://www.httpdebugger.com/ ) pour inspecter vos en-têtes HTTP, mais vous pouvez également accéder à votre site de développement à partir d’autres machines de votre réseau local à tester.

Assurez-vous cependant que vous êtes protégé par un pare-feu, bien que le serveur dev soit minimal et relativement sûr.

9
chefsmart

Le Django Debug Toolbar est vraiment fantastique. Ce n'est pas vraiment une barre d'outils, mais un volet latéral qui vous indique toutes sortes d'informations sur ce qui vous a amené à la page que vous consultez - requêtes DB, variables de contexte envoyées au modèle, signaux, etc.

7
Mark Snidovich

Utilisez wraps decorator dans les vues personnalisées pour conserver le nom, le module et la docstring de la vue. Par exemple.

try:
    from functools import wraps
except ImportError:
    from Django.utils.functional import wraps  # Python 2.3, 2.4 fallback.

def view_decorator(fun):
    @wraps(fun)
    def wrapper():
        # here goes your decorator's code
    return wrapper

Attention: ne fonctionnera pas sur les vues basées sur les classes (celles avec __call__ méthode)), si l'auteur n'a pas défini de __name__ propriété. Pour contourner ce problème, utilisez:

from Django.utils.decorators import available_attrs
...
    @wraps(fun, assigned=available_attrs(fun))
7
trybik

Utilisation d'un dossier 'apps' pour organiser vos applications sans modifier PYTHONPATH

Cela m'a été utile lorsque je souhaite organiser mes dossiers de la manière suivante:

apps/
    foo/
    bar/
site/
settings.py
urls.py

sans écraser PYTHONPATH ni avoir à ajouter des applications à chaque import, comme par exemple:

from apps.foo.model import *
from apps.bar.forms import *

Dans votre settings.py ajouter

import os
import sys
PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
sys.path.insert(0, os.path.join(PROJECT_ROOT, "apps"))

et vous êtes prêt à partir :-)

J'ai vu cela à http://codespatter.com/2009/04/10/how-to-add-locations-to-python-path-for-reusable-Django-apps/

6
Javi Romero

Rendu formulaire via Django au lieu de as_ (ul | table | p) () .

Cet article explique comment utiliser un modèle pour rendre CusstomForms au lieu de as_p(), as_table()...

Pour que ça marche change

  • from Django import newforms as forms à from Django import forms
  • from Django.newforms.forms import BoundField à from Django.forms.forms import BoundField
5
vikingosegundo

Définir automatiquement l'attribut 'DEBUG' sur l'environnement de production (settings.py)

import socket

if socket.gethostname() == 'productionserver.com':
    DEBUG = False
else:
    DEBUG = True

Par: http://nicksergeant.com/2008/automatically-setting-debug-in-your-Django-app-based-on-server-hostname/

5
Ahmet Recep Navruz

Utilisez djangorecipe pour gérer votre projet

  • Si vous écrivez une nouvelle application, cette recette facilite son test en dehors d'un projet.
  • Il vous permet de gérer les dépendances d’un projet (par exemple, sur quelle version d’une application il devrait dépendre)

Pour commencer, voici tout ce que vous avez à faire:

  1. Créez un dossier pour votre nouveau site web (ou bibliothèque)
  2. Créez un fichier buildout.cfg avec le contenu suivant:

    
    [buildout]
    parts=Django
    
    [Django]
    recipe=djangorecipe
    version=1.1.1
    project=my_new_site
    settings=development
    
  3. Saisissez un fichier bootstrap.py pour obtenir une installation locale de buildout et placez-le dans votre répertoire. Vous pouvez soit aller avec le officiel (désolé, Markdown n’a pas aimé une partie du lien complet: - /) ou avec celui qui utilise distribuer au lieu de setuptools comme décrit par Reinout van Rees .
  4. python bootstrap.py (ou python bootstrap_dev.py _ si vous voulez utiliser distribuer).
  5. ./bin/buildout

C'est ça. Vous devriez maintenant avoir un nouveau dossier "my_new_site", qui est votre nouveau projet Django 1.1.1, et dans ./bin vous trouverez le script Django- qui remplace le manage.py sur une installation normale.

Quel est l'avantage? Supposons que vous souhaitiez utiliser quelque chose comme Django-comment-spamfighter dans votre projet. Tout ce que vous avez à faire est de changer votre buildout.cfg en quelque chose comme ceci:


[buildout]
parts=Django

[Django]
recipe=djangorecipe
version=1.1.1
project=my_new_site
settings=development
eggs=
    Django-comments-spamfighter==0.4

Notez que tout ce que j’ai fait, c’est d’ajouter les 2 dernières lignes qui indiquent que la partie Django devrait également avoir le paquet Django-comments-spamfighter dans la version 0.4. La prochaine fois que vous exécutez ./bin/buildout, buildout téléchargera ce paquet et modifiera ./bin/Django pour l’ajouter à son PYTHONPATH.

djangorecipe est également adapté au déploiement de votre projet avec mod_wsgi. Ajoutez simplement le wsgi=true définissant la partie Django de votre buildout.cfg et un "Django.wsgi" apparaîtra dans votre dossier ./bin :-)

Et si vous définissez l'option test sur une liste d'applications, djangorecipe créera un wrapper Nice qui exécutera tous les tests de l'application répertoriée dans votre projet.

Si vous souhaitez développer une seule application dans un environnement autonome pour le débogage, etc., Jakob Kaplan-Moss propose un didacticiel assez complet sur son blog

5
Horst Gutmann

Utilisez reverse dans votre urlconf.

C'est l'une de ces astuces pour lesquelles je ne comprends pas pourquoi ce n'est pas le cas par défaut.

Voici un lien vers où je l'ai ramassé: http://andr.in/2009/11/21/calling-reverse-in-Django/

Voici l'extrait de code:

from Django.conf.urls.defaults import *
from Django.core.urlresolvers import reverse
from Django.utils.functional import lazy
from Django.http import HttpResponse

reverse_lazy = lazy(reverse, str)

urlpatterns = patterns('',
url(r'^comehere/', lambda request: HttpResponse('Welcome!'), name='comehere'),
url(r'^$', 'Django.views.generic.simple.redirect_to',
{'url': reverse_lazy('comehere')}, name='root')
)
5
jfenwick

C’est un moyen très simple de ne plus jamais avoir à importer un autre de vos modèles dans votre python Shell.

Commencez par installer IPython (Si vous n'utilisez pas IPython, qu'est-ce qui ne va pas avec vous?). Ensuite, créez un script python, ipythonrc.py, dans votre répertoire de projet Django, avec le code suivant:

from Django.db.models.loading import get_models 
for m in get_models(): 
     globals()[m.__name__] = m 
#NOTE: if you have two models with the same name you'll only end up with one of them

Ensuite, dans votre fichier ~/.ipython/ipythonrc, insérez le code suivant dans la section "Fichiers Python à charger et à exécuter":

execfile /path/to/project/ipythonrc.py

Maintenant, chaque fois que vous démarrez IPython ou exécutez ./manage.py Shell tous vos modèles seront déjà importés et prêts à être utilisés. Pas besoin d'importer un autre modèle à nouveau.

Vous pouvez également mettre tout autre code que vous exécutez beaucoup dans votre fichier ipythonrc.py pour gagner du temps.

4
sheats

Changement Django propriétés du champ de formulaire sur init

Parfois, il est utile de passer des arguments supplémentaires à une classe Form.

from Django import forms
from mymodels import Group

class MyForm(forms.Form):
    group=forms.ModelChoiceField(queryset=None)
    email=forms.EmailField()
    some_choices=forms.ChoiceField()


    def __init__(self,my_var,*args,**kwrds):
        super(MyForm,self).__init__(*args,**kwrds)
        self.fields['group'].queryset=Group.objects.filter(...)
        self.fields['email'].widget.attrs['size']='50'
        self.fields['some_choices']=[[x,x] for x in list_of_stuff]

source: extraits de Dzone

4
jbochi

PyCharm et Wingware IDE est un excellent outil si vous avez de l’argent pour payer la licence.

Étant donné que je suis un mauvais développeur, j'utilise PyDev avec Eclipse .

2
kelvinfix

Django_extensions de https://github.com/Django-extensions/Django-extensions est tout simplement génial.

Peu de Nice ./manage.py commandes:

  • Shell_plus - auto-importe les modèles de tous les INSTALLED_APPS
  • show_urls - imprime toutes les URL définies dans toutes les applications du projet
  • runscript - exécute n'importe quel script dans le contexte du projet (vous pouvez utiliser des modèles et d'autres modules liés à Django)
2
gorsky

Utilisez des tâches asynchrones. Utilisez céleri

1
vad

Lisez Django Unbreaking si ce n'est déjà fait. Il contient beaucoup d'informations utiles concernant les Django.

1
tback

Créez des modèles dynamiques pour des ensembles de tables héritées ayant la même structure:

class BaseStructure(models.Model):
    name = models.CharField(max_length=100)
    address = models.CharField(max_length=100)

    class Meta:
        abstract=True

class DynamicTable(models.Model):
    table_name = models.CharField(max_length=20)

    def get_model(self):
        class Meta:
            managed=False
            table_name=self.table_name

        attrs = {}
        attrs['Meta'] = Meta

        # type(new_class_name, (base,classes), {extra: attributes})
        dynamic_class = type(self.table_name, (BaseStructure,), attrs) 
        return dynamic_class

customers = DynamicTable.objects.get(table_name='Customers').get_model()
me = customers.objects.get(name='Josh Smeaton')
me.address = 'Over the Rainbow'
me.save()

Cela suppose que vous ayez des tables héritées ayant la même structure. Au lieu de créer un modèle pour envelopper chacune des tables, vous définissez un modèle de base et construisez de manière dynamique la classe nécessaire pour interagir avec une table spécifique.

1
Josh Smeaton

Utilisez isapi-wsgi et Django-pyodbc pour exécuter Django sous Windows avec IIS et SQL Server !

1
Jason Baker

Un peu tard pour la fête. Mais Django Canvas est récemment sorti et mérite une place ici.

Ne commencez pas votre projet avec Django-admin.py startproject. Au lieu de cela, vous pouvez utiliser quelque chose comme Django Canvas pour vous aider à reconstituer un projet vierge avec les modules dont vous avez besoin.

Vous allez sur ce site, cochez quelques options puis téléchargez un projet vierge, si simple.

Il présente toutes les caractéristiques communes telles que les migrations de schéma South et les extensions de commande, ainsi que de nombreuses autres pratiques recommandées mentionnées ici. De plus, il a un grand start.sh/shart.bat script qui installera python, virtualenv, pip, Django et tout ce dont vous avez besoin pour démarrer à partir d’une nouvelle copie de Windows, osx ou linux.

1
Keyo

Django n'a pas de paramètres d'application, j'ai donc créé ma propre détection app_settings.py. Au bas de la settings.py j'ai ajouté ce code:

import sys, os
# Append application settings without triggering the __init__.
for installed_app in INSTALLED_APPS:
    # Ignore Django applications
    if not installed_app.startswith('Django.'):
        # Find the app (and the settings file)
        for path in sys.path:
            path = os.path.join(path, installed_app, 'app_settings.py')
            if os.path.isfile(path):
                # Application settings found
                exec open(path).read()

Il détecte app_settings.py dans tous les INSTALLED_APPS. Au lieu de l'importer, il lira le contenu du fichier app_settings et l'exécutera en ligne. Si app_settings est importé directement, toutes les sortes de Django seront générées (car Django n'est pas encore initialisé).).

Donc, mon application/app_settings.py ressemblera à ceci:

MIDDLEWARE_CLASSES += (
    'app.middleware.FancyMiddleware',
)

Désormais, il suffit d’ajouter l’application à INSTALLED_APPS au lieu de rechercher tous les paramètres de l’application et de les ajouter à settings.py (middleware, urls ...).

Remarque: Il serait préférable que Django dispose d'un point d'ancrage pour ajouter des paramètres supplémentaires, afin que les paramètres de l'application puissent être ajoutés au démarrage (ou à l'exécution).

0
Willian

Lorsque vous passez des variables d'une vue à un modèle, la saisie du dictionnaire de réponses peut s'avérer fastidieuse. Je trouve ça agréable de simplement passer toutes les variables locales en même temps en utilisant locals().

def show_thing(request, thing_id):
    thing = Thing.objects.get(pk=thing_id)
    return render_to_response('templates/things/show.html', locals())

(Ce n'est pas une fonctionnalité cachée en soi, mais néanmoins utile quand on découvre Python et ou Django.)

Edit: Évidemment, il vaut mieux être explicite qu'implicite, mais cette approche peut être utile pendant le développement.

0
droidballoon

dir () & augmenter ValueError ()

Pour déboguer/explorer l'état des choses pendant le développement, j'utilise l'astuce suivante:

...
  to_see = dir(inspect_this_thing)
  to_see2 = inspect_this_thing.some_attribute
  raise ValueError("Debugging")
...

Ceci est particulièrement utile lorsque vous travaillez sur des parties de Django qui ne sont pas particulièrement bien documentées (form.changed_fields en est un que j'ai utilisé récemment).

locals ().

Au lieu d'écrire chaque variable pour le contexte du modèle, utilisez la commande python builtin locals () qui crée un dictionnaire pour vous:

#This is tedious and not very DRY
return render_to_response('template.html', {"var1": var1, "var2":var2}, context_instance=RequestContext(request))

#95% of the time this works perfectly
return render_to_response('template.html', locals(), context_instance=RequestContext(request))

#The other 4.99%
render_dict = locals()
render_dict['also_needs'] = "this value"
return render_to_response('template.html', render_dict, context_instance=RequestContext(request))
0
Ted