# Django 6.0.7 문서

# 코딩 스타일

장고에 포함시킬 코드를 작성할 때 이러한 코딩 표준을 따르십시오.

## 사전 커밋 검사

“pre-commit <https://pre-commit.com>”_은(는) 사전 커밋 후크를 관리하기 위한 프레임워크입니다. 이러한 훅은 검토를 위해 코드를 커밋하기 전에 간단한 문제를 식별하는 데 도움이 됩니다. 코드 검토 전에 이러한 문제를 확인함으로써 검토자는 변경 자체에 집중할 수 있으며 CI 실행 횟수를 줄이는 데 도움이 될 수 있습니다.

도구를 사용하려면 먼저 “pre-commit”을 설치한 다음 Git 훅을 설치합니다.

/ 

    $ python -m pip install pre-commit
    $ pre-commit install

    ...\> py -m pip install pre-commit
    ...\> pre-commit install

첫 번째 커밋 “pre-commit”에서 후크를 설치합니다. 후크는 자체 환경에 설치되며 첫 번째 실행에서 설치하는 데 시간이 조금 걸립니다. 이후의 점검은 상당히 빠를 것입니다. 오류가 발견되면 해당 오류 메시지가 표시됩니다. 오류가 “black” 또는 “isort”에서 발생한 경우 도구가 진행하여 오류를 수정해 줍니다. 변경 사항을 검토하고 마음에 드는 경우 커밋을 위해 다시 스테이징하십시오.

## 파이썬 스타일

- 모든 파일은 black 자동 포맷터를 사용하여 포맷해야 합니다. ``pre-commit``이 설정되어 있다면 이 과정은 자동으로 실행됩니다.

- 프로젝트 저장소에는 “.editorconfig’ 파일이 포함되어 있습니다. 들여쓰기 및 공백 문제를 방지하려면 “EditorConfig”_ 지원 텍스트 편집기를 사용하는 것이 좋습니다. 파이썬 파일은 들여쓰기에 4개의 공간을 사용하고 HTML 파일은 2개의 공간을 사용합니다.

- 별도로 지정하지 않는 한:pep:’8’을 따른다.

  flake8`을 사용하여 해당 부분의 문제를 확인하세요. `.flake8`` 파일에는 중대한 위반 사항으로 간주하지 않는 일부 오류가 제외되어 있습니다. :pep:`8`은 가이드일 뿐이므로 주변 코드의 스타일을 우선적으로 따르세요.

  :pep:`8`에 대한 예외로 줄 길이 규칙이 있습니다. 코드에서는 ``black``이 사용하는 줄 길이에 맞춰 최대 88자까지 허용됩니다. 문서, 주석, 독스트링은 79자로 줄바꿈해야 합니다. 이러한 제한은 ``flake8`` 실행 시 검사됩니다.

- 문자열 보간에는 %-formatting, f-strings 또는 :meth:`str.format`을 상황에 맞게 사용하되, 코드 가독성을 높이는 것을 목표로 합니다.

  가독성에 대한 최종 판단은 합병의 재량에 맡겨집니다. 참고로 f-string은 일반 변수 및 속성 액세스만 사용해야 하며, 더 복잡한 경우에는 사전 로컬 변수가 할당되어야 합니다.

      # Allowed
      f"hello {user}"
      f"hello {user.name}"
      f"hello {self.user.name}"

      # Disallowed
      f"hello {get_user()}"
      f"you are {user.age * 365.25} days old"

      # Allowed with local variable assignment
      user = get_user()
      f"hello {user}"
      user_days_old = user.age * 365.25
      f"you are {user_days_old} days old"

  오류 및 로깅 메시지를 포함하여 변환이 필요할 수 있는 문자열에는 f-messages를 사용하면 안 됩니다. 일반적으로 “format()”은 더 장황하기 때문에 다른 포맷 방법을 선호합니다.

  포맷 방법을 조정하기 위해 기존 코드의 관련 없는 리팩터링을 하는 데 시간을 낭비하지 마십시오.

- “We loop over”가 아닌 “Loop over”와 같은 주석에서 “We”를 사용하지 마십시오.

- 변수, 함수 및 메서드 이름에는 camelCase가 아닌 밑줄을 사용합니다(즉, “poll.get_unique_voters()”는 “poll.getUniqueVoters()”가 아닙니다.

- 클래스 이름(또는 클래스를 반환하는 공장 함수의 경우)에는 “InitialCaps”를 사용합니다.

- 문서 문자열에서 기존 문서 문자열의 스타일을 따릅니다.

- 테스트에서는 :meth:’~django.test를 사용합니다.SimpleTestCase.assertRaisesMessage’ 및 :meth:’~django.test.:meth:’~unittest 대신 SimpleTestCase.assertWarnsMessage’를 사용합니다.TestCase.assertRaise’ 및 :meth:’~unittest.예외 또는 경고 메시지를 확인할 수 있도록 TestCase.assertWarns’를 참조하십시오. :meth:’~unit test를 사용합니다.TestCase.assertRegex’ 및 :meth:’’~unittest.정규식 일치가 필요한 경우에만 TestCase.assertWarnsRegex’를 입력합니다.

  :meth:’assertIs(…, True/False)<unittest를 사용합니다.TestCase.assert:meth:’~unittest가 아닌 부울 값을 테스트하기 위한 Is>’입니다.TestCase.assertTrue’와 :meth:’~단위 테스트.TestCase.assertFalse’를 사용하면 식의 진실성이 아닌 실제 부울 값을 확인할 수 있습니다.

- 테스트 문서 문자열에 각 테스트가 보여주는 예상 동작을 기술합니다. “테스트 대상” 또는 “확인 대상”과 같은 프리암블은 포함하지 마십시오.

  티켓에 문서 문자열이나 설명에서 쉽게 설명할 수 없는 추가 세부 정보가 있는 모호한 문제에 대한 티켓 참조를 예약합니다. 다음과 같은 문장의 끝에 티켓 번호를 포함합니다.

      def test_foo():
          """
          A test docstring looks like this (#123456).
          """
          ...

- 가능하다면 :pep:`448`을 따르는 언패킹 일반화 기능을 사용하세요. 예를 들어 매핑 병합(``{**x, **y}``)이나 시퀀스 결합(`[*a, *b]`)과 같은 방식이 있습니다. 이러한 방식은 오류를 줄이면서 성능, 가독성, 유지보수성을 향상시킵니다.

## 수입

- :pypi:`isort`를 사용하여 아래 가이드라인에 따라 import 정렬을 자동화합니다.

  빠른 시작:

  / 

      $ python -m pip install "isort >= 7.0.0"
      $ isort .

      ...\> py -m pip install "isort >= 7.0.0"
      ...\> isort .

  이렇게 하면 현재 디렉토리에서 “isort”가 반복적으로 실행되어 지침에 맞지 않는 파일이 수정됩니다. 순환 가져오기를 피하기 위해 가져오기를 순서가 잘못된 상태로 만들어야 하는 경우 다음과 같은 설명을 사용하십시오.

      import module  # isort:skip

- import를 future, 표준 라이브러리, 서드파티 라이브러리, 기타 Django 구성 요소, 로컬 Django 구성 요소, try/except 그룹으로 나눕니다. 각 그룹의 줄은 전체 모듈 이름 기준으로 알파벳순으로 정렬하세요. 각 섹션에서는 모든 `import module` 문을 `from module import objects``보다 앞에 배치합니다. 다른 Django 구성 요소에는 절대 import를 사용하고, 로컬 구성 요소에는 한 단계 상대 import(``from .foo import Bar`)를 사용하세요. 여러 단계의 상대 import는 피하세요.

- 각 줄에서 소문자 항목 앞에 그룹화된 대문자 항목을 알파벳 순으로 입력합니다.

- 괄호를 사용하여 긴 줄을 끊고 연속선을 4칸씩 들여씁니다. 마지막 가져오기 뒤에 후행 쉼표를 포함하고 닫는 괄호를 자체 행에 배치합니다.

  마지막 가져오기 코드와 모듈 수준 코드 사이에 하나의 빈 줄을 사용하고 첫 번째 함수 또는 클래스 위에 있는 두 개의 빈 줄을 사용합니다.

  예를 들어, (주석은 설명 목적으로만 작성됩니다.)

  `django/contrib/admin/example.py`

      # future
      from __future__ import annotations

      # standard library
      import json
      from itertools import chain

      # third-party
      import bcrypt

      # Django
      from django.http import Http404
      from django.http.response import (
          Http404,
          HttpResponse,
          HttpResponseNotAllowed,
          StreamingHttpResponse,
          cookie,
      )

      # local Django
      from .models import LogEntry

      # try/except
      try:
          import yaml
      except ImportError:
          yaml = None

      CONSTANT = "foo"

      class Example: ...

- 가능한 경우 편의 import를 사용하세요. 예를 들어 다음과 같이 작성합니다:

      from django.views import View

  대신:

      from django.views.generic.base import View

## 템플릿 스타일

Django 템플릿 코드에서는 아래 규칙을 따르세요.

- ``{% extends %}``는 주석을 제외한 첫 번째 줄에 와야 합니다.

  다음 작업을 하세요.

      {% extends "base.html" %}

      {% block content %}
        <h1 class="font-semibold text-xl">
          {{ pages.title }}
        </h1>
      {% endblock content %}

  또는 다음과 같이 할 수 있습니다.

      {# This is a comment #}
      {% extends "base.html" %}

      {% block content %}
        <h1 class="font-semibold text-xl">
          {{ pages.title }}
        </h1>
      {% endblock content %}

  다음 작업은 하지마세요.

      {% load i18n %}
      {% extends "base.html" %}

      {% block content %}
        <h1 class="font-semibold text-xl">
          {{ pages.title }}
        </h1>
      {% endblock content %}

- `{{``와 변수 내용, ``}}` 사이에는 공백을 정확히 하나만 넣어야 합니다.

  다음 작업을 하세요.

      {{ user }}

  다음 작업은 하지마세요.

      {{user}}

- ``{% load … %}``에서는 라이브러리를 알파벳순으로 나열합니다.

  다음 작업을 하세요.

      {% load i18n l10 tz %}

  다음 작업은 하지마세요.

      {% load l10 i18n tz %}

- `{%``와 태그 내용, ``%}` 사이에는 공백을 정확히 하나만 넣어야 합니다.

  다음 작업을 하세요.

      {% load humanize %}

  다음 작업은 하지마세요.

      {%load humanize%}

- `{% block %}` 태그와 같은 줄에 있지 않은 경우, `{% endblock %}` 태그에 블록 이름을 명시하세요.

  다음 작업을 하세요.

      {% block header %}

        Code goes here

      {% endblock header %}

  다음 작업은 하지마세요.

      {% block header %}

        Code goes here

      {% endblock %}

- 중괄호 안에서는 토큰을 공백 하나로 구분하세요. 단, 속성 접근을 위한 `.``와 필터를 나타내는 ``|` 주변에는 공백을 두지 않습니다.

  다음 작업을 하세요.

      {% if user.name|lower == "admin" %}

  다음 작업은 하지마세요.

      {% if user . name | lower  ==  "admin" %}

      {{ user.name | upper }}

- `{% extends %}``를 사용하는 템플릿에서는 최상위 ``{% block %}` 태그를 들여쓰지 마세요.

  다음 작업을 하세요.

      {% extends "base.html" %}

      {% block content %}

  다음 작업은 하지마세요.

      {% extends "base.html" %}

        {% block content %}
        ...

## 보기 스타일

- Django 뷰에서 뷰 함수의 첫 번째 매개변수는 “request”라고 불러야 한다.

  다음 작업을 하세요.

      def my_view(request, foo): ...

  다음 작업은 하지마세요.

      def my_view(req, foo): ...

## 모델 스타일

- 필드 이름은 모두 소문자여야 하며, camelCase 대신 밑줄을 사용합니다.

  다음 작업을 하세요.

      class Person(models.Model):
          first_name = models.CharField(max_length=20)
          last_name = models.CharField(max_length=40)

  다음 작업은 하지마세요.

      class Person(models.Model):
          FirstName = models.CharField(max_length=20)
          Last_Name = models.CharField(max_length=40)

- “class Meta”는 필드가 정의된 후에 나타나야 하며 필드 및 클래스 정의를 구분하는 빈 줄이 하나 있습니다.

  다음 작업을 하세요.

      class Person(models.Model):
          first_name = models.CharField(max_length=20)
          last_name = models.CharField(max_length=40)

          class Meta:
              verbose_name_plural = "people"

  다음 작업은 하지마세요.

      class Person(models.Model):
          class Meta:
              verbose_name_plural = "people"

          first_name = models.CharField(max_length=20)
          last_name = models.CharField(max_length=40)

- 모델 내부 클래스 및 표준 방법의 순서는 다음과 같아야 합니다(모두 필요한 것은 아닙니다).

  - 모든 데이터베이스 필드

  - 사용자 지정 관리자 특성

  - ‘’’클래스 메타’’’’

  - ``def __str__()``와 기타 Python 매직 메서드

  - `def save()`

  - `def get_absolute_url()`

  - 모든 사용자 지정 메서드

- 모델 필드에 ``choices``가 정의된 경우, 각 선택 항목은 매핑으로 정의하고 모델 클래스의 속성으로 모두 대문자 이름을 사용하세요. 예시는 다음과 같습니다:

      class MyModel(models.Model):
          DIRECTION_UP = "U"
          DIRECTION_DOWN = "D"
          DIRECTION_CHOICES = {
              DIRECTION_UP: "Up",
              DIRECTION_DOWN: "Down",
          }

  대안으로 Enumeration types 사용을 고려하세요:

      class MyModel(models.Model):
          class Direction(models.TextChoices):
              UP = "U", "Up"
              DOWN = "D", "Down"

## “django.conf.settings”를 사용합니다.

모듈은 일반적으로 최상위 레벨의 “django.conf.settings”에 저장된 설정을 사용하면 안 됩니다(즉, 모듈을 가져올 때 평가됨). 이에 대한 설명은 다음과 같습니다.

설정을 수동으로 구성합니다(즉, :envvar에 의존하지 않음).’DJANGO_SETTINGS_MODULE’ 환경 변수)는 다음과 같이 허용되며 가능합니다.

    from django.conf import settings

    settings.configure({}, SOME_SETTING="foo")

그러나 ‘’settings.configure’’ 줄 앞에 있는 설정에 액세스하면 이 설정은 작동하지 않습니다. (내부적으로 ‘’settings’’는 설정이 아직 구성되지 않은 경우 자동으로 설정되는 “LazyObject”입니다.)

따라서 다음과 같은 코드가 포함된 모듈이 있으면 다음과 같이 하십시오.

    from django.conf import settings
    from django.urls import get_callable

    default_foo_view = get_callable(settings.FOO_VIEW)

…그러면 이 모듈을 가져오면 설정 개체가 구성됩니다. 즉, 타사가 최상위 수준에서 모듈을 가져오는 기능은 설정 개체를 수동으로 구성하는 기능과 호환되지 않거나 일부 상황에서는 매우 어렵습니다.

위의 코드 대신``django.utils.functional.LazyObject`` `django.utils.functional.lazy()` 나 ``lambda``와 같은 간접적인 수준을 사용해야 합니다.

## 기타

- 국제화에 대한 모든 줄에 마크를 한 후 더 자세한 내용을 원한다면 문서:`i18n `를 보세요

- 코드를 변경할 때 더 이상 사용하지 않는 `import` 문은 제거하세요. :pypi:`flake8`은 이러한 import를 식별해 줍니다. 하위 호환성을 위해 사용하지 않는 import를 유지해야 하는 경우에는 ``# NOQA``를 끝에 추가하여 flake8 경고를 무시하세요.

- 불필요한 바이트가 추가되고 패치가 시각적으로 복잡해지며 불필요한 병합 충돌이 발생할 수 있으므로 코드에서 모든 후행 공백을 체계적으로 제거합니다. 일부 IDE는 IDE를 자동으로 제거하도록 구성할 수 있으며 대부분의 VCS 도구는 IDE를 diff 출력으로 강조 표시하도록 설정할 수 있습니다.

- 기여하는 코드에 이름을 넣지 마십시오. 우리의 정책은 장고와 함께 배포된 “AUTHORS” 파일에 기여자의 이름을 보관하는 것입니다. 사소한 것 이상의 변경을 가할 경우 패치에 “AUTHORS” 파일의 변경 내용을 포함시키십시오.

## JavaScript 스타일

Django에서 사용하는 JavaScript 코드 스타일에 대한 자세한 내용은 자바스크립트 코드’를 참고하세요.