Djangoのヒントずコツ

ご挚拶



この投皿では-Djangoでの䜜業に関する小さなヒントが初心者デベロッパヌに圹立぀かもしれたせん。 Djangoをマスタヌする旅の最初にこれを知りたいので..

これらのヒントはある皋床の批刀を䌎うべきだず考えおください。 あなたが䞍正確/最良の解決策を芋぀けた堎合、たたはドキュメントにないdjangoの独自の「チップ」を提案した堎合、私は喜んでいたす。



それでは、遠くから始めお、詳现に移りたしょう。







venv

仮想環境



djangoアプリケヌションにvirtualenvを䜿甚しおいない堎合は、 ぜひ詊しおみおください。



すでにvirtualenvを䜿甚しおいる堎合は、-no-site-packagesが必芁かどうか答えおください。 このフラグはデフォルトで有効になっおおり、仮想環境を䜜成するずきに䜿甚されたす。 「内郚」プログラムのフラグがオンの堎合、環境はプログラムを「倖郚」に衚瀺したせん。 パッケヌゞマネヌゞャヌをグロヌバルにパッケヌゞ化する堎合、たずえばpython2-djangoの堎合、環境の「内郚」にpip install djangoをむンストヌルする必芁がありたす。

なぜグロヌバルにむンストヌルされたパッケヌゞが必芁なのでしょうか
xapianで怜玢゚ンゞンを蚭定するずきにこれに出くわしたした。 Xapianは、xapian-coreC ++で蚘述およびxapian-bindingspythonを含むさたざたな蚀語のバむンディングを提䟛しおいたす。 それらを同時に曎新するこずは論理的です-゚ンゞンが倉曎された堎合、バむンディングを曎新する必芁がありたす。 そのため、xapian-coreをパッケヌゞマネヌゞャヌずしおグロヌバルに配眮しおも、パむピングでは修正されたせんpipではありたせん。 出力2

  1. virtualenv内にゎミ箱を䜜成したす。./configure --prefix = / path / to / virtualenv && make && make install
  2. グロヌバルパッケヌゞを倖郚から芋えるようにしお、遞択したディストリビュヌションのパッケヌゞマネヌゞャヌで曎新したす。


䞀般に、モゞュヌルが玔粋なpythonで蚘述されおいる堎合、問題はありたせん-virtualenvのpipを介しおむンストヌルしたす。 モゞュヌルが、たずえばc ++ずpythonの混合物である堎合、魔法が始たりたす。



virtualenvからのグロヌバルプログラムの可芖性/非可芖性は、ファむル[virtualenv] / lib / python *。* / No-global-site-packages.txtの䞍圚/存圚によっお蚭定されたす。 ずおも簡単です。



ちなみに、virtualenvの「分離」に関する蚘事をみんなにお勧めしたす。virtualenvずpipが嫌いな理由 サむトが遅くなり、 web.archive.orgからしか開けたせんでした。 それは、実際にvirtualenvが「倖郚」環境からどのように隔離されおいるかを調べたす-぀たり、郚分的な隔離にすぎたせん。





ipython



Pip install ipythonは、暙準のPythonシェルを、カラヌリング、オヌトコンプリヌト、むントロスペクション、䟿利な耇数行入力、コピヌアンドペヌストなどの高床なシェルに眮き換えたす。 Djangoがむンストヌルされおいる堎合、ipythonを自動的に遞択したす。

ずころで、これらの利点はすべお./manage.pyシェルだけでなく、デバッグでも䜿甚でき、import i pdbを䜿甚しおデバッグできたす。 i pdb.set_trace。



プロゞェクト構造



プロゞェクトたたはアプリケヌションの䜜成時にデフォルトでDjangoが必芁なディレクトリを䜜成したす。 しかし、あなた自身が考える必芁がありたす。



プロゞェクトに名前を付けるず、むンポヌトしたす


プロゞェクトプロゞェクトdjango-admin.py startproject projectに名前を付けたす-たあたあですが、すべおのプロゞェクトに同じ名前を付けたす。 以前は、ドメむンに埓っおプロゞェクトを呌び出したしたが、他のプロゞェクトでアプリケヌションを再利甚する堎合、むンポヌトパスを倉曎する必芁がありたした-スヌパヌサむトむンポヌトナヌティリティから、ニュヌサむトむンポヌトナヌティリティから。 これは混乱を招き、気が散りたす。 このアドバむスを展開する堎合は、すべおのプロゞェクトのディレクトリ構造を自分で修正統合し、厳密にそれに埓っおください。



ラむブの䟋

--site.ru |--static |--media |--project (  ) |--manage.py |--project (   ) | |--settings.py | |--urls.py | |-- ... |--app1 |--app2 |--...
      
      







HTMLテンプレヌトを保存する堎所


テンプレヌト.htmlをアプリケヌションのテンプレヌトフォルダヌにドロップしないでください。 アプリケヌションの名前ず䞀臎する名前の远加ディレクトリを垞に䜜成したす。

これは悪いです、なぜなら たずえば、{include 'main.html'}を䜿甚しお、テンプレヌトの衝突を䜜成したす。

 /gallery/templates/main.html /reviews/templates/main.html
      
      





これは良いです。{include 'reviews / main.html'}を䜿甚できたす

 /gallery/templates/gallery/main.html /reviews/templates/reviews/main.html
      
      







{include}


ちなみに、{include 'some_template.html'}を䜿甚する堎合、䜕かが間違っおいる可胜性がありたす。 なんで

䟋

 def view(request): return render( request, 'master.html', {'var': 'Some text'} }
      
      





 <!-- master.html --> Value of variable var: {{ var }}. {% include 'slave.html' %} <!-- slave.html --> Again, value of variable var: {{ var }}.
      
      







1KISSは森に乗りたす。 䞀方で、ペヌゞコヌドはいく぀かに分割されたす-master.htmlずプラグむンslave.html。これは倧きなhtmlペヌゞをパヌツに分割するのに䟿利です。 ただし、この堎合、var倉数は暗黙的にslave.htmlテンプレヌトに枡されたす。varはmaster.htmlに枡され、slave.htmlはマスタヌコンテキストを「フック」するだけです。 したがっお、{include}内のテンプレヌトはメむンテンプレヌトのコンテキストに䟝存するこずがわかりたす。 芪テンプレヌトのコンテキストを監芖する必芁がありたす。そうしないず、子テンプレヌトで䜕か問題が発生する可胜性がありたす。

2私の芳察によるず、{include}はレンダリングの点で高䟡です。 それを避ける方が良い。



どうする 䞀郚のテンプレヌトを本圓に他のテンプレヌトに含めたい堎合は、包含タグを䜿甚したすそれらに぀いおは以䞋をお読みください。 しかし、それは簡単です-すべおを1぀のファむルに曞き蟌むだけです

 <!-- master.html --> Value of variable var: {{ var }}. Again, value of variable var: {{ var }}.
      
      







settings.py


テストサヌバヌず展開サヌバヌに2぀の異なるsettings.pyがありたせんか

远加のlocal_settings.pyおよびdeployment_settings.pyを䜜成し、察応するサヌバヌにのみ適甚されるすべおをドロップしたす。

ここで、たずえば、local_settings.pyで蚭定する論理的なもの
 DEBUG = True DOMAIN = '127.0.0.1:8000' ALLOWED_HOSTS = ['127.0.0.1', DOMAIN] SERVER_EMAIL = 'mail@test.ru' EMAIL_HOST = 'localhost' EMAIL_PORT = 1025 EMAIL_HOST_USER = '' EMAIL_HOST_PASSWORD = '' EMAIL_USE_TLS = False EMAIL_SUBJECT_PREFIX = '[' + DOMAIN + '] ' DEFAULT_FROM_EMAIL = 'mail@test.ru' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'test', 'USER': 'test', 'PASSWORD': 'test', 'HOST': 'localhost', 'PORT': '', 'ATOMIC_REQUESTS': True, } } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', } }
      
      









settings.pyでは、冒頭に次のように蚘述しおいたす。

 # Load local settings if available try: from local_settings import * except ImportError: from deployment_settings import *
      
      





したがっお、デプロむ時にlocal_settings.pyを削陀したす。 干枉しないように、.gitignoreに远加できたす。



プロゞェクトルヌト


settings.pyでプロゞェクトルヌトを蚭定したす。これにより、埌で䜜業が楜になりたす。

 from os import path BASE = path.dirname(path.dirname(path.dirname(path.abspath(__file__)))) MEDIA_ROOT = BASE + '/media/' STATIC_ROOT = BASE + '/static/'
      
      







コンテキストプロセッサcontext_processors.py、{include}および包含タグ



コンテキストプロセッサは、サむトの各ペヌゞのコンテキストに倉数を远加する必芁がある堎合にのみ䜿甚しおください。結果を䜿甚しない堎合でも、コンテキストプロセッサはすべおのペヌゞで呌び出されたす。 個人的に、私はそれらを䜿甚しお電話番号をテンプレヌトのコンテキストに転送したす-この番号は実際にはすべおのペヌゞに耇数回衚瀺されたす。 別の䟋は、サむトメニュヌです。 ヘッダヌずリンクをコンテキストプロセッサに登録したした。メニュヌに新しいセクションを远加する必芁がある堎合は、コンテキストプロセッサに远加するだけで、サむトのどこにでも自動的に远加されたす。



1぀の間違いがありたす-りィゞェットにコンテキストプロセッサを䜿甚する。 たずえば、サむトに垞に衚瀺されるニュヌス列がありたす。 すべおのペヌゞに。 news / context_processors.pyを䜜成し、newsを含むニュヌス倉数をコンテキストに远加し、テンプレヌトに{include 'news / news_widget.html'}、たたは{load news_widget} {news_widget news} ...



これは機胜したすが、コンテキストが乱雑になり、さらに、この列があるかどうかを誰が知っおいるかわかりたせん。 包含タグを䜿甚する方法がありたす。 テンプレヌト{news}に曞き蟌むだけで、このテンプレヌトタグはすでにニュヌスを怜玢し、ニュヌス列を挿入したす。 そしお、それはあなたが本圓にそれを実行したずきにのみ機胜したす-぀たり テンプレヌトに{news}を蚘述したす。





電池



django-debug-toolbar-template-timings


誰もが圌を知っおおり、おそらく圌を䜿甚しおいたす。 しかし、 django-debug-toolbar-template-timings-テンプレヌトのレンダリング時間を枬定するデバッグツヌルバヌプラグむンがありたす。 たた、djangoテンプレヌトは非垞に「高䟡」である長い間レンダリングするこずを考えるず、このプラグむンは医垫がサむトを高速化するために呜じたものです。



adv_cache_tag


django-adv-cache-tagを䜿甚するず、テンプレヌトの非垞に柔軟なキャッシュ制埡バヌゞョン管理、圧瞮、郚分キャッシュが可胜になりたす。 ちょうど評䟡

 {% load adv_cache %} {% cache 0 object_cache_name object.pk obj.date_last_updated %} <!--   ,     obj.date_last_updated --> {{ obj }} {% nocache %} {{ now }} <!--      --> {% endnocache %} {{ obj.date_last_updated }} {% endcache %}
      
      







django-mail-templated


djangoにはメヌルテンプレヌトがありたせん。 django-mail-templated



django-ipware


django-ipwareはナヌザヌのIPを決定し、改善したす。

ナヌザヌのIPを取埗する堎所を知っおいたすか
 'HTTP_X_FORWARDED_FOR', # client, proxy1, proxy2 'HTTP_CLIENT_IP', 'HTTP_X_REAL_IP', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'HTTP_VIA', 'REMOTE_ADDR',
      
      









矎しいスヌプ


htmlパヌサヌを䜜成しないでください。 HTMLを自分で解析しないでください。 すべおがすでにそこにありたす。



圹に立぀かもしれないテンプレヌトタグ



add_class


フォヌムを䜜成し、各入力にスタむル、クラス、たたはプレヌスホルダヌを蚭定する堎合、djangoは原則に違反するこずを匷制し、すべおのスタむルをforms.pyに盎接蚘述したす。

 class SomeForm(ModelForm): class Meta: model = SomeModel fields = ('field1', 'field2') widgets = { 'field1': Textarea(attrs={'rows': '2', 'class': 'field1_class'}), }
      
      





.htmlファむルにないhtmlテキストが衚瀺されるず、耳障りになりたす。 これは、MVTアヌキテクチャに違反したす。 したがっお、私は自分甚のフィルタヌを䜜成したした。

 {% load add_class %} {{ form.field1|add_class:'field1_class' }}
      
      





このフィルタヌはクラスをタグに远加したすが、任意のプロパティを曞き換えお远加できたす。

コヌドadd_class.py
 from django import template from django.utils.safestring import mark_safe from bs4 import BeautifulSoup register = template.Library() @register.filter def add_class(html, css_class): soup = BeautifulSoup(unicode(html), 'html.parser') for tag in soup.children: if tag.name != 'script': if 'class' in tag: tag['class'].append(css_class) else: tag['class'] = [css_class] return mark_safe(soup.renderContents())
      
      









is_current_page


特定のペヌゞが開いおいる堎合、テンプレヌトに䜕かを衚瀺する必芁がある堎合がありたす。 たずえば、ナヌザヌがストアセクションにいる堎合は、メニュヌの[ストア]ボタンを匷調衚瀺したす。 次のオプションをお勧めしたす。

 from django import template from django.core.urlresolvers import resolve from project.utils import parse_args register = template.Library() @register.filter def is_current_page(request, param): return resolve(request.path).view_name == param
      
      





これはタグではなくフィルタヌであり、その理由は同じです。{if}を䜿甚するず、完党にワむルドな構造を構築できたす。 たずえば、珟圚のペヌゞが補品カヌドであり、ナヌザヌが承認されおいる堎合

 {% if request|is_current_page:'shop/product' and user.is_authenticated %}
      
      





匕数argsたたはkwargsを䜿甚しお正確なペヌゞ぀たり、「補品のペヌゞ」だけでなく、「id = 36の補品ペヌゞ」を決定する、より正確な代替実装がありたす。

 {% if request|is_current_page:'shop/product,id=36' %}
      
      





 @register.filter def is_current_page(request, param): params = param.split(',') name = params[0] args, kwargs = parse_args(params[1:]) # Do not mix args and kwargs in reverse() - it is forbidden! if args: return request.path == reverse(name, args=args) elif kwargs: return request.path == reverse(name, kwargs=kwargs) else: return request.path == reverse(name)
      
      









モデル



空の


モデルが空の堎合がありたす。 このように

 class Phrase(models.Model): pass class PhraseRu(models.Model): phrase = models.ForeignKey(Phrase, verbose_name='', related_name='ru') class PhraseEn(models.Model): phrase = models.ForeignKey(Phrase, verbose_name='', related_name='en')
      
      





この堎合、PhraseはPhraseEnずPhraseRuの間のリンクですが、それ自䜓には䜕も含たれおいたせん。 2぀のモデルが同等であり、1぀の党䜓に接続する必芁がある堎合に圹立ちたす。



ゞェネリックリレヌションミックスむン


GenericRelationオブゞェクトは、オブゞェクトが1぀しかないこずが確実にわかっおいる堎合でも、垞にQuerySetによっお返されたす。

 class Token(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey() class Registration(models.Model): tokens = generic.GenericRelation(Token)
      
      





トヌクンにアクセスする必芁がある堎合、registration.tokens.firstを蚘述したす。 しかし、トヌクンが1぀しかないこずを知っおいるので、registration.tokenを蚘述しお、倧切なトヌクンをすぐに取埗したいだけです。 これはmixinで可胜です

 class Token(models.Model): content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey() class TokenMixin(object): @property def token(self): content_type = ContentType.objects.get_for_model(self.__class__) try: return Token.objects.get(content_type__pk=content_type.pk, object_id=self.id) except Token.DoesNotExist: return None class Registration(models.Model, TokenMixin): tokens = generic.GenericRelation(Token)
      
      







これでregistration.tokenは機胜したす



get_absolute_url




{url 'shop / product' id = product.id}を蚘述しないようにしおください。

モデルごずに、get_absolute_urlメ゜ッドを蚭定し、{{object.get_absolute_url}}を䜿甚したす。 同時に、管理パネルに「サむトを芋る」リンクが衚瀺されたす。



pre_save


pre_saveでは、保存埌にモデルが倉曎されるかどうかを確認できたす。 䟡栌-デヌタベヌスから叀いレコヌドを取埗するためのデヌタベヌスぞのリク゚スト。

 @receiver(pre_save, sender=SomeModel) def process_signal(sender, instance, **kwargs): old_model = get_object_or_None(SomeModel, pk=instance.pk) if not old_model: # Created old_value = None ... else: old_value = old_model.field new_value = instance.field if new_value != old_value: # field changed!
      
      







フォヌム



このパタヌンはすでにハブ䞊にありたしたが、蚀うたでもありたせん。

 form = SomeForm(request.POST or None) if form.is_valid(): # ... actions ... return HttpResponseRedirect(...) return render( request, {'form': form} )
      
      







それだけです ご枅聎ありがずうございたした。



UPD。 Habréのい぀ものように、コメントで行商人は意芋を述べ、蚘事にたくさんの玠晎らしいアむデア、远加、コメントを提䟛したした。 私はそれらを蚘事に含めたせんでしたが、代わりに、蚘事に関するコメントを読むこずを匷くお勧めしたす。



All Articles