첫 Django 패치 작성하기

개요

커뮤니티에 보답하고 싶은가요? 고치고 싶은 버그가 있거나, 추가하고 싶은 기능이 있을지도 모릅니다.

장고에 공헌하는 것이야말로 여러분의 관심을 드러내는 최선의 방법입니다. 처음에는 부담스러워 보일지도 모르지만, 아주아주 간단합니다. 우리는 전체 프로세스를 살펴볼 것이므로, 여러분은 예를 통해 배울 수 있습니다.

이 튜토리얼은 누구를 위한 것인가요?

더 보기

만약 여러분이 패치를 제출하는 방법에 대한 레퍼런스를 찾고 있다면, Submitting patches 문서를 보세요.

이 튜토리얼을 진행하기 위해서는, 장고에 대한 기본적인 이해가 필요합니다. 첫번째 Django 앱 작성해보기 를 무난하게 따라할 정도면 됩니다. 또한, 파이썬에 대한 적당한 이해도 필요합니다만, 그렇지 않다면 `Dive Into Python`__ 을 읽어보는 것을 권장합니다.

버전 관리 시스템과 Trac에 대해 잘 모르는 분은 이 튜토리얼과 튜토리얼에 포함된 링크를 통해 충분한 정보를 찾을 수 있을 것입니다. 하지만, 장고에 계속 공헌하고자 한다면 이러한 다른 도구들에 대하여 더 읽어두는 것도 좋을 것입니다.

하지만 대부분의 경우, 이 튜토리얼은 폭넓은 독자에게 사용이 될 수 있도록 최대한 설명하려고 합니다.

도움을 받을 수 있는 방법

만약 튜토리얼을 진행하다가 문제가 생길 경우, |django-developers|에 메시지를 보내거나, irc.freenode.net 의 #django-dev를 통해서 다른 장고 유저들과 이야기를 해볼 수 있습니다. 혹시 이들이 도움을 줄지도 모릅니다.

이 튜토리얼이 다루는 내용은 무엇입니까?

여기서는 여러분이 장고에 대한 패치를 처음 제출하는 과정을 다룹니다. 이 튜토리얼을 마치면, 여러분은 기본적인 관련 도구와 프로세스를 모두 이해하게 될 것입니다. 좀더 구체적으로는 다음 내용을 다룹니다.

  • GIT 설치
  • 장고의 개발 사본을 다운로드하는 방법.
  • 장고의 테스트 스위트를 실행.
  • 패치에 대한 테스트를 작성.
  • 패치 코드를 작성.
  • 패치를 테스트.
  • 풀 리퀘스트 보내기.
  • 더 많은 정보를 찾을 수 있는 곳.

한번 튜토리얼을 마쳤다면, Django 문서의 기여하기 를 통해 나머지를 볼 수 있습니다. 다양한 정보들이 있으며, 특히 Django 의 정규 기여자가 되고 싶다면 반드시 봐야 합니다. 궁금하신 점이 있다면 답을 얻으실 수 있을 것입니다.

파이썬 3.x 버전이 필요합니다.

Django 현재의 버전은 파이썬 2.7 을 지원하지 않습니다. 파이썬의 다운로드 페이지 또는 자신의 운영체제의 패키지 관리자로부터 파이썬 3을 받을 수 있습니다.

윈도우 운영체제를 사용하는 경우

윈도우에서 Python 을 설치할 경우, 커맨드라인에서 사용하기 위해서는 반드시 "Add python.exe to Path" 옵션을 체크해야 합니다.

행동 지침

당신은 기여자로서, 개방적이고 포괄적인 Django 커뮤니티를 유지하도록 도움을 줄 수 있습니다. 행동 강령 을 읽고 숙지해주세요.

GIT 설치

이 튜토리얼에서와 같이, 현재 개발 버전의 Django를 다운로드하고 수정하여 패치 파일을 생성하기 위해서는 Git을 설치해야 합니다.

Git 이 설치되었는지 확인해보기 위해, 커맨드라인에서 git 라고 입력해보세요. 만약 그런 명령을 찾을 수 없다는 메세지가 나오면 Git 이 설치되지 않았다는 의미입니다. `Git's download page`__ 를 참조하세요.

윈도우 운영체제를 사용하는 경우

Git 을 윈도우에 설치할 경우, Git 이 자신의 쉘에서 동작하도록 "Git Bash" 옵션을 체크하는것을 권장합니다. 이 튜토리얼은 해당 옵션이 체크 되어 있다고 가정합니다.

Git 을 사용하는것이 익숙하지 않다면, 커맨드라인 상에서 git help 를 입력 함으로써 명령어에 대한 자세한 정보를 확인할 수 있습니다.

Django 개발 버전의 사본을 얻기

Django 에 기여하기위한 첫걸음은 소스코드를 내려받는 것 입니다 fork Django on Github. 커맨드라인에서 cd 명령을 통해 Django 소스를 내려받을 디렉토리로 이동하세요.

다음 명령을 통해 Django 소스코드 저장소를 다운로드하십시오.

$ git clone git@github.com:YourGitHubName/django.git

이제, Django 의 복사본을 확보했습니다. 다른 패키지를 설치할 때처럼, pip 를 이용해 설치할 수 있습니다. 가장 간단한 방법은 가상 환경 (Virtualenv) 을 이용하는 것입니다. Virtualenv 는 프로젝트 별로 패키지가 설치된 개별 디렉토리를 유지하여 서로 간섭하지 않도록 하는 Python 의 기능입니다.

virtualenvs 환경들을 ~/.virtualenvs/ 같은 디렉토리에 몰아서 관리하는 것은 좋은 생각입니다. 아직 그런 디렉토리가 없다면, 다음 명령어로 만들어 보세요.

$ mkdir ~/.virtualenvs

다음을 실행시켜서 새로운 가상 환경을 생성하십시오.

$ python3 -m venv ~/.virtualenvs/djangodev

경로는 당신의 컴퓨터에서 새로운 환경이 저장될 위치를 의미합니다.

윈도우 운영체제를 사용하는 경우

venv 모듈은 윈도우의 Git Bash Shell 에서는 동작하지 않습니다. 이 모듈의 활성 스크립트가 system shell (.bat) 과 PowerShell (.ps1) 에서만 생성되기 때문입니다. venv 대신 virtualenv 패키지를 사용하세요.

$ pip install virtualenv
$ virtualenv ~/.virtualenvs/djangodev

우분투 운영체제 사용자의 경우

몇몇 버전의 우분투 운영체제에서는 위 명령이 동작하지 않을 수 있습니다. 대신 virtualenv 패키지를 사용하시고, 그 전에 pip3가 설치되었는지 확인하십시오.

$ sudo apt-get install python3-pip
$ # Prefix the next command with sudo if it gives a permission denied error
$ pip3 install virtualenv
$ virtualenv --python=`which python3` ~/.virtualenvs/djangodev

가상 환경 설정의 마지막 단계는 그것을 활성화시키는 것입니다.

$ source ~/.virtualenvs/djangodev/bin/activate

만약 source 명령을 사용할 수 없다면, 대신 마침표(.)를 사용해 보십시오.

$ . ~/.virtualenvs/djangodev/bin/activate

윈도우 운영체제를 사용하는 경우

윈도우 운영체제에서 가상 환경을 활성화시키기 위해서는 다음을 실행하십시오:

$ source ~/virtualenvs/djangodev/Scripts/activate

당신은 새로운 터미널 창을 열 때마다 가상환경을 실행시켜야 합니다. virtualenvwrapper__ 는 이것을 편리하게 만들어주는 유용한 도구입니다.

pip 를 통해 설치하는 모든 패키지들은 다른 실행 환경과 격리되어, 현재 활성화된 virtualenv 환경에 설치됩니다. 활성화된 virtualenv 는 커맨드라인의 프롬프트에 표시되므로, 내가 어느 실행환경에 있는지 쉽게 알 수 있습니다. 계속해서, 아까 내려받은 개발버전의 Django 를 설치해보겠습니다.

$ pip install -e /path/to/your/local/clone/django/

현재 설치된 Django 는 당신이 내려받은 Django 의 복제본을 가르키고 있습니다. Django 를 수정하면 그 내역이 곧바로 반영될 것이며, 패치를 작성할때 굉장히 큰 도움이 됩니다.

이전 리비전의 Django로 되돌리기

이 튜토리얼에서는, #24788 티켓으로 사례 연구를 해보겠습니다. git 에 저장된 Django 의 버전 이력을 이용하여, 해당 티켓의 패치가 반영되기 이전 버전으로 돌아간 후, 이를 활용하여 처음부터 패치를 작성하고 테스트 스위트를 동작시키는 것을 포함한 모든 과정을 함께 진행해 보겠습니다.

반드시 염두에 두어야 할 것은, 여기서 Django 의 옛날 버전을 사용하는 이유는 순전히 튜토리얼의 진행을 위해서 입니다. 티켓을 위한 패치를 작성할 때는 반드시 가장 최근 버전의 Django 개발 코드를 사용해야 합니다.

주석

이 티켓을 위한 패치는 Paweł Marczewski 가 작성하였고, Django 에 `commit 4df7e8483b2679fc1cba3410f08960bac6f51115`__ 에 반영되었습니다. 따라서, 우리는 `commit 4ccfc4439a7add24f8db4ef3960d02ef8ae09887`__ 의 바로 직전 버전을 사용할 것입니다.

Django 의 루트 디렉토리로 이동합니다(django, docs, tests, AUTHORS, 같은 디렉토리가 포함된 위치입니다.). 여기서 다음 명령을 통해 튜토리얼에서 사용할 Django 의 예전 버전을 checkout 할 수 있습니다.

$ git checkout 4ccfc4439a7add24f8db4ef3960d02ef8ae09887

Django의 테스트 스위트를 처음으로 실행하기

Django 에 코드를 기여할 때 중요한 점은, 변경된 코드가 Django 의 다른 부분에서 버그를 일으키지 말아야 한다는 것입니다. 이를 확인하기 위해 Django 의 테스트 스위트를 실행시켜 Django 가 잘 동작하는지 알아볼 수 있습니다. 만약 테스트를 모두 통과 했다면, 코드의 변경사항이 Django 를 망가뜨리지 않는다고 생각할 수 있습니다.혹시 그동안 한번도 Django 의 테스트 스위트를 돌려본적이 없다면, 어떤 식으로 동작하는지 미리 봐두는 차원에서 한번 실행해 보는것도 좋습니다.

Django tests/ 디렉터리로 이동하여 의존 패키지를 설치하고 나서 테스트 스위트를 실행합니다.

$ pip install -r requirements/py3.txt

설치 중 에러가 발생했다면, 하나 이상의 Python 패키지에서 필요한 의존성을 해결하지 못한 것일 수 있습니다. 설치에 실패한 Python 패키지의 문서를 살펴보거나 에러 메세지를 인터넷에서 검색해서 해결 방법을 찾아볼 수 있습니다.

이제 테스트 스위트를 실행할 준비가되었습니다. GNU / Linux, macOS 또는 Unix의 다른 맛을 사용한다면 다음을 실행하십시오 :

$ ./runtests.py

이제 9,600 개에 달하는 Django 의 전체 테스트 스위트가 끝날때까지 편히 기다리면 됩니다. 컴퓨터 사양에 따라 다르지만, 전체 실행에 약 5분에서 15분 정도가 소비됩니다.

Django 의 테스트 스위트가 동작하며, 화면에 각 테스트의 상태가 출력되는것을 볼 수 있습니다. E 는 테스트 도중 에러가 발생했다는 것을 말해주며, F 는 테스트가 실패했다는 것을 말합니다. 이 두 가지 상태 모두 테스트가 실패했다고 생각할 수 있습니다. 반면, x 는 실패할 것을 예상한 테스트이고 s 는 건너띈 테스트를 말합니다. 점(.) 은 그동안 통과한 테스트를 말합니다.

건너띈 테스트는 보통 테스트를 수행하기 위해 필요한 외부 라이브러리가 없는 경우 발생합니다. Running all the tests 를 참조하여, 변경과 관련한 모든 테스트를 수행하기 위한 의존성을 확인하고 이를 설치하십시요. 특정한 데이터베이스 백엔드를 필요로 하는 테스트의 경우, 해당 데이터베이스 백엔드를 사용하지 않으면 자동으로 테스트를 건너 띕니다. SQLite 는 기본 데이터베이스 백엔드 입니다. 다른 백엔드를 테스트 하고 싶다면 Using another settings module 를 참조하세요.

일단 테스트가 완료되면, 테스트 성공 여부를 알려주는 메세지가 반길 것입니다. 아직 Django 에 대한 어떤 수정도 하지 않았다면, 반드시 모든 테스트는 통과 되어야 합니다. 만약 실패나 에러가 발생했다면, 이전의 절차를 제대로 수행했는지 다시한번 확인해 보세요. Running the unit tests 에서 더 자세히 알아볼 수 있습니다. 만약 Python 3.5 이상의 버전을 사용한다면, 새로운 Python 에서 도태된(deprecate) 기능에 대한 테스트 실패가 발생할 수 있습니다. 그러나 이는 무시해도 괜찮습니다. 이러한 에러는 새로운 Python 버전에서 탈락된 기존의 기능들을 Django 에서 사용하기 때문에 발생합니다. 이러한 에러는 Django 의 다음 버전에서 수정될 것입니다.

가장 최근의 개발 코드를 보관하는 trunk 저장소는 끊임없이 코드가 변경되기 때문에 안정적이지 않을 수 있습니다. 만약 trunk 저장소를 기준으로 개발한다면, `Django's continuous integration builds`__ 에서 테스트 실패의 원인이 내 개발환경에 있는지, 공식적인 빌드에서 실패한 것인지 알 수 있습니다. 특정 빌드를 클릭하여, "Configuration Matrix" 항목을 확인하면 어떤 파이선 버전과 데이터베이스 백엔드에서 해당 빌드가 실패했는지 자세히 파악할 수 있습니다.

주석

이 튜토리얼과 여러분이 작업하는 티켓에 대해서는 SQLite로 작업하는 것으로 충분하지만, 다른 데이터베이스에서 테스트를 수행하는 것이 가능합니다(때로는 필수적입니다).

패치 용 branch 만들기

변경하기 전에 티켓의 새 branch를 생성합니다.

$ git checkout -b ticket_24788

지점에 대해 원하는 이름을 선택할 수 있으며 "ticket_24788"이 예제입니다. 이 지점에서 이루어진 모든 변경 사항은 특정한 티켓에만 적용되며 이전에 복제 한 코드의 주 복사본에는 영향을 미치지 않습니다.

티켓에 대한 테스트를 작성하기

대부분의 경우에, Django에 대한 패치를 접수할 때에는 테스트를 포함합니다. 버그 수정 패치의 경우, 이것은 그 버그가 나중에 Django에서 다시 발생하지 않도록 회귀 테스트를 작성하는 것을 의미합니다. 회귀 테스트는 버그가 존재하는 동안 실패하다가 일단 버그가 수정되면 통과하도록 작성하여야 합니다. 새로운 기능을 포함하는 패치의 경우 새로운 기능이 올바르게 작동하는지 확인하는 테스트를 포함해야 합니다. 그러한 테스트들은 새로운 기능이 존재하지 않는 경우에는 실패하고, 구현이 되면 통과합니다.

이 작업을 수행하는 좋은 방법은 코드를 변경하기 전에, 먼저 새로운 테스트부터 작성하는 것입니다. 이러한 개발 스타일은 `test-driven development`__이라고 불리우며, 낱개의 패치에서부터 전체 프로젝트에 이르기까지 적용이 가능합니다. 테스트를 작성한 후에는 (당신이 버그를 수정하거나 아직이 기능을 추가하지 않았기 때문에) 그것들이 실제로 실패하는지 확인하기 위해 실행시켜보도록 합니다. 새 테스트가 실패하지 않을 경우, 테스트가 실패하도록 수정해야합니다. 버그가 있든없든 통과하는 회귀 테스트라면 다시 발생하는 버그를 방지하는 데에 그다지 도움이 되지 않습니다.

이제 우리 예제를 살펴보도록 하겠습니다.

티켓 #24788에 대한 테스트 작성하기

#24788 은 작은 기능 추가에 대한 다음과 같은 제안입니다: 클래스 레벨 속성 prefix를 Form 클래스에 정의할수 있게해서 다음과같은 효과를 줍니다:

[…] forms which ship with apps could effectively namespace themselves such
that N overlapping form fields could be POSTed at once and resolved to the
correct form.

이 티켓을 해결하기 위해서, 우리는 prefix 속성를 BaseForm 클래스에 추가할 것입니다. 이 클래스의 인스턴스가 만들어질때, prefix를 __init__() 메소드에 전달하면 생성된 인스턴스에 prefix가 그대로 설정될것 입니다. 하지만 prefix를 전달하지 않으면(혹은 None을 전달하면) 클래스 레벨 prefix를 사용할것 입니다. 우리가 이 변경을 만들기전에, 우리가 수정하는 기능들이 올바르게 동작하고 향후에도 올바르게 동작하는지를 검증하기위한 몇가지 테스트를 작성할것 입니다.

Django의 tests/forms_tests/tests/ 폴더로 이동하여 test_forms.py 파일을 엽니다. 1674 행의 다음과 같은 코드를 test_forms_with_null_boolean 함수 바로 앞에 추가합니다.

def test_class_prefix(self):
    # Prefix can be also specified at the class level.
    class Person(Form):
        first_name = CharField()
        prefix = 'foo'

    p = Person()
    self.assertEqual(p.prefix, 'foo')

    p = Person(prefix='bar')
    self.assertEqual(p.prefix, 'bar')

이 새 테스트는 클래스 레벨 prefix 설정이 예상대로 동작하는지, 인스턴스 생성 시 prefix 파라미터 전달이 잘되는 지를 검사합니다.

하지만 테스팅이 어려워보입니다...

이전에 테스트를 한번도 다뤄보지 않았다면, 처음에는 작성하기에 까다로울 수도 있습니다. 다행히도, 테스트는 컴퓨터 프로그래밍에서 매우 중요한 주제이기 때문에, 많은 정보를 얻을 수 있습니다.

  • 첫 Django 패치 작성하기의 좋은 예제는 Writing and running tests 에 있는 문서에서 찾을 수 있습니다.
  • Dive Into Python (초보 파이썬 개발자를 위한 무료 온라인북)에 훌륭한 `introduction to Unit Testing`__이 있습니다.
  • 그것들을 읽어본 후에, 좀 더 음미해보고 싶다면,`Python unittest documentation`를 읽어보기 바랍니다.

새 테스트를 수행하기

아직 BaseForm 을 실제로 수정하지 않았으므로, 이 테스트는 실패할 것이라는 점을 기억하세요. forms_tests 폴더의 모든 테스트를 수행하여 정말 그렇게 되는지 확인해보도록 하겠습니다. 명령행에서 Django tests/ 디렉토리로 cd 하여 다음과 같이 실행합니다:

$ ./runtests.py forms_tests

테스트가 올바로 수행되면, 우리가 추가한 테스트 메소드와 관련된 실패 한개를 확인할 수 있을 것입니다. 모든 테스트가 성공했다면, 새로운 테스트를 올바른 폴더와 클래스에 추가한 것인지 다시 확인해보시기 바랍니다.

티켓에 대한 코드를 작성하기

다음에는 #24788에서 기술한 기능을 Django에 추가해보도록 하겠습니다.

티켓 #24788에 대한 코드 작성하기

django/django/forms/ 폴더로 이동하여 forms.py 파일을 여세요. 72행에서 BaseForm 클래스를 찾아 field_order 속성 이후에 prefix 클래스 속성를 추가하세요.

class BaseForm:
    # This is the main implementation of all the Form logic. Note that this
    # class is different than Form. See the comments by the Form class for
    # more information. Any improvements to the form API should be made to
    # *this* class, not to the Form class.
    field_order = None
    prefix = None

테스트가 통과하는지 확인하기

일단 Django에 대한 수정을 하였으면, 우리는 앞서 우리가 작성한 테스트가 통과하는지 확인함으로써, 우리가 위에서 작성한 코드가 제대로 작동하는지 확인할 수 있습니다. forms_tests 폴더에서 테스트를 실행하려면, Django tests/ 디렉토리로 cd하여 다음과 같이 실행합니다:

$ ./runtests.py forms_tests

이런, 테스트를 작성해두길 잘 했군요! 여전히 다음과 같은 예외가 발생하여 한 건이 실패했습니다.

AssertionError: None != 'foo'

We forgot to add the conditional statement in the __init__ method. Go ahead and change self.prefix = prefix that is now on line 87 of django/forms/forms.py, adding a conditional statement:

if prefix is not None:
    self.prefix = prefix

테스트를 재수행하면 모두 통과할 것입니다. 그렇지 않다면, BaseForm 클래스를 위와 같이 올바로 수정하였고 새로운 테스트를 올바로 복사했는지 확인해보시기 바랍니다.

Django의 테스트 스위트를 두 번째로 실행하기

패치와 태스트가 올바로 작동하는 것을 확인하였다면, 여러분이 변경한 부분이 Django의 다른 부분에 어떠한 버그를 만들어내지 않았는지 확인하기 위해 전체 Django 테스트 스위트를 실행해보는 것이 좋습니다. 전체 테스트 스위트를 통과하였다고해서 버그가 없다고 확신할 수는 없지만, 모르고 지나쳤을 수도 있는 많은 버그와 잘못을 찾아내는 데에 도움이 됩니다.

Django 테스트 스위트 전체를 실행하려면, Django tests/ 디렉토리로 cd하여 다음과 같이 실행합니다:

$ ./runtests.py

실패를 한개도 보지 못했다면, 여러분은 잘하고 있는 것입니다.

문서 작성하기

이것은 새로운 기능이므로, 문서화를 해야합니다. django/docs/ref/forms/api.txt의 1068행(파일의 끝)에 다음 내용을 추가하세요:

The prefix can also be specified on the form class::

    >>> class PersonForm(forms.Form):
    ...     ...
    ...     prefix = 'person'

.. versionadded:: 1.9

    The ability to specify ``prefix`` on the form class was added.

이 새 기능은 다음 배포본에 있을 것이므로 Django 1.9 릴리즈 노트 docs/releases/1.9.txt 파일 "Forms" 섹션 아래 164행에도 추가됩니다:

* A form prefix can be specified inside a form class, not only when
  instantiating a form. See :ref:`form-prefix` for details.

versionadded에 대한 설명을 포함하여, 문서 작성에 대한 자세한 내용은 Writing documentation을 참조하시기 바랍니다. 그 페이지에는 문서의 사본을 로컬에서 빌드하여, 생성되는 HTML을 미리 살펴볼 수 있도록 하는 방법도 설명하고 있습니다.

변경사항 미리보기

이제 우리 패치의 모든 변경 사항을 검토 할 차례입니다. Django의 현재의 사본 (변경 사항 포함)과 튜토리얼의 앞부분에서 처음 체크 아웃 한 개정판 사이의 차이 점을 표시하려면 다음을 수행하십시오.

$ git diff

위 아래로 움직이려면 화살표 키를 사용하세요.

diff --git a/django/forms/forms.py b/django/forms/forms.py
index 509709f..d1370de 100644
--- a/django/forms/forms.py
+++ b/django/forms/forms.py
@@ -75,6 +75,7 @@ class BaseForm:
     # information. Any improvements to the form API should be made to *this*
     # class, not to the Form class.
     field_order = None
+    prefix = None

     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
                  initial=None, error_class=ErrorList, label_suffix=None,
@@ -83,7 +84,8 @@ class BaseForm:
         self.data = data or {}
         self.files = files or {}
         self.auto_id = auto_id
-        self.prefix = prefix
+        if prefix is not None:
+            self.prefix = prefix
         self.initial = initial or {}
         self.error_class = error_class
         # Translators: This is the default suffix added to form field labels
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt
index 3bc39cd..008170d 100644
--- a/docs/ref/forms/api.txt
+++ b/docs/ref/forms/api.txt
@@ -1065,3 +1065,13 @@ You can put several Django forms inside one ``<form>`` tag. To give each
     >>> print(father.as_ul())
     <li><label for="id_father-first_name">First name:</label> <input type="text" name="father-first_name" id="id_father-first_name" /></li>
     <li><label for="id_father-last_name">Last name:</label> <input type="text" name="father-last_name" id="id_father-last_name" /></li>
+
+The prefix can also be specified on the form class::
+
+    >>> class PersonForm(forms.Form):
+    ...     ...
+    ...     prefix = 'person'
+
+.. versionadded:: 1.9
+
+    The ability to specify ``prefix`` on the form class was added.
diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
index 5b58f79..f9bb9de 100644
--- a/docs/releases/1.9.txt
+++ b/docs/releases/1.9.txt
@@ -161,6 +161,9 @@ Forms
   :attr:`~django.forms.Form.field_order` attribute, the ``field_order``
   constructor argument , or the :meth:`~django.forms.Form.order_fields` method.

+* A form prefix can be specified inside a form class, not only when
+  instantiating a form. See :ref:`form-prefix` for details.
+
 Generic Views
 ^^^^^^^^^^^^^

diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
index 690f205..e07fae2 100644
--- a/tests/forms_tests/tests/test_forms.py
+++ b/tests/forms_tests/tests/test_forms.py
@@ -1671,6 +1671,18 @@ class FormsTestCase(SimpleTestCase):
         self.assertEqual(p.cleaned_data['last_name'], 'Lennon')
         self.assertEqual(p.cleaned_data['birthday'], datetime.date(1940, 10, 9))

+    def test_class_prefix(self):
+        # Prefix can be also specified at the class level.
+        class Person(Form):
+            first_name = CharField()
+            prefix = 'foo'
+
+        p = Person()
+        self.assertEqual(p.prefix, 'foo')
+
+        p = Person(prefix='bar')
+        self.assertEqual(p.prefix, 'bar')
+
     def test_forms_with_null_boolean(self):
         # NullBooleanField is a bit of a special case because its presentation (widget)
         # is different than its data. This is handled transparently, though.

패치 미리보기가 끝나면``q`` 키를 눌러 명령 행으로 돌아갑니다. 패치의 내용이 괜찮아 보이면 변경 사항을 커밋해야합니다.

패치 변경사항 적용하기

변경사항을 적용하려면:

$ git commit -a

그러면 커밋 메시지 를 입력하기위한 텍스트 편집기가 열립니다. : ref :`commit message guidelines <committing-guidelines>에 따라 다음과 같은 메시지 를 작성하십시오.

Fixed #24788 -- Allowed Forms to specify a prefix at the class level.

 commit 푸시 및 pull request 요청

패치를 커밋 한 후 GitHub의 포크로 보내십시오 (다른 경우, 지점 이름으로 "ticket_24788"을 대체하십시오) :

$ git push origin ticket_24788

`Django GitHub 페이지 <https://github.com/django/django/>`_를 방문하여 pull 요청을 만들 수 있습니다. "최근 푸시 된 브랜치"아래에 브랜치가 보일 것입니다. 옆의 "Compare & pull request"를 클릭하십시오.

이 자습서에서는하지 말고, 패치의 미리보기를 표시하는 다음 페이지에서 "pull request 만들기"를 클릭하십시오.

다음 단계

축하합니다. Django에 풀 리퀘스트 을 하는 법을 배웠습니다! 필요한 고급 기술에 대한 자세한 내용은 doc :`/ internals / contributing / writing-code / working-with-git`에 있습니다.

이제 Django의 코드베이스를 개선하여 이러한 기술을 유용하게 사용할 수 있습니다.

새로 오신 기여자분들을 위한 추가 정보

Django 를 위한 패치를 작성하기 전에, 한번 꼭 보셔야 할 정보들이 있습니다.

  • Django 문서 중, 티켓 생성과 패치 제출 문서를 반드시 읽어보십시요. 이 문서는 Trac 사용 예절과, 직접 티켓을 생성하는 방법, 패치 작성 시 지켜야 할 코딩 스타일과 다른 중요한 것들을 자세히 설명합니다.
  • 기여가 처음이신 분들은 첫 기여자를 위한 문서 를 읽어주십시요. Django 를 도와주시려는 분들을 위한 좋은 조언들이 가득합니다.
  • 기여에 대한 정보가 이것으로 충분하지 않으시면, Django 문서의 기여 항목 의 나머지를 흝어보세요. 엄청나게 많은 정보들이 있으며, 궁금하신 점들은 여기서 제일 먼저 찾으셔야 합니다.

첫 번째 진짜 티켓을 찾기

여기까지 흝어 보셨다면, 이제 직접 패치를 작성해볼 티켓을 찾아봅시다. "easy pickings" 제약이 걸린 티켓들을 주의깊게 살펴 봅시다. 이 티켓들은 처리하기 쉬운편이라, 초보 기여자에게 적당합니다. 일단 Django 에 기여하는 과정에 익숙해지면, 조금 더 복잡하고 어려운 티켓에 도전할 수 있습니다.

지금 당장 시작해보고 싶다면(눈치보지 않아도 돼요!), `easy tickets that need patches`__ 목록과 `easy tickets that have patches which need improvement`__ 목록을 살펴보기 바랍니다. 테스트를 작성하는데에 익숙하다면, `easy tickets that need tests`__ 도 살펴보세요. 티켓 생성과 패치 제출하기 에 설명된 티켓 생성에 대한 지침을 잘 따르시기만 하면 됩니다.

pull request을 만든 후 다음은 무엇입니까?

티켓에 패치가있는 경우 두 번째 눈으로 검토해야합니다. pull request을 제출 한 후 티켓에 "패치가 있음", "테스트가 필요 없음"등의 플래그를 설정하여 티켓 메타 데이터를 업데이트하여 다른 사람들이 검토 할 수 있도록합니다. 기여한다고해서 항상 패치를 처음부터 작성하는 것은 아닙니다. 기존 패치를 검토하는 것도 매우 도움이됩니다. 참조 : 자세한 내용은 doc :`/ internals / contributing / triaging-tickets`를 참조하십시오.

Back to Top