{"title":"첫 번째 장고 앱 작성하기, part 2","version":"3.1","locale":"ko","docname":"intro/tutorial02","url":"/ko/3.1/intro/tutorial02/","canonical":"https://djangodocs.dev/ko/3.1/intro/tutorial02/","summary":"이 튜토리얼은 튜토리얼 1장 에서 이어집니다. 데이터베이스를 설치하고 첫 모델을 생성한 후, Django에서 자동 생성되는 관리자 사이트에 대해 짧게 소개합니다. 도움을 받을 수 있는 방법 If you’re having trouble going through this tutorial,…","html":"<h1>첫 번째 장고 앱 작성하기, part 2<a class=\"heading-anchor\" href=\"#writing-your-first-django-app-part-2\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>이 튜토리얼은 <a class=\"reference internal\" href=\"/ko/3.1/intro/tutorial01/\"><span class=\"doc\">튜토리얼 1장</span></a>에서 이어집니다. 데이터베이스를 설치하고 첫 모델을 생성한 후, Django에서 자동 생성되는 관리자 사이트에 대해 짧게 소개합니다.</p>\n<aside class=\"admonition-where-to-get-help admonition\">\n<p class=\"admonition-title\">도움을 받을 수 있는 방법</p>\n<p>If you’re having trouble going through this tutorial, please head over to\nthe <a class=\"reference internal\" href=\"/ko/3.1/faq/help/\"><span class=\"doc\">Getting Help</span></a> section of the FAQ.</p>\n</aside>\n<section id=\"database-setup\">\n<h2>데이터베이스 설치<a class=\"heading-anchor\" href=\"#database-setup\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>이제, <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code> 파일을 열어보세요. 이 파일은 Django 설정을 모듈 변수로 표현한 보통의 Python 모듈입니다.</p>\n<p>기본적으로는 SQLite을 사용하도록 구성되어 있습니다. 만약 데이터베이스를 처음 경험해보거나, Django에서 데이터베이스를 한번 경험해 보고 싶다면, SQLite가 가장 간단한 방법입니다. SQLite는 Python에서 기본으로 제공되기 때문에 별도로 설치할 필요가 없습니다. 그러나 실제 프로젝트를 시작할 때에는, 나중에 데이터베이스를 교체하느라 골치 아파질 일을 피하기 위해서라도 PostgreSQL 같이 좀 더 확장성 있는 데이터베이스를 사용하는 것이 좋습니다.</p>\n<p>다른 데이터베이스를 사용해보고 싶다면, 적절한 <a class=\"reference internal\" href=\"/ko/3.1/topics/install/#database-installation\"><span class=\"std std-ref\">데이터베이스 바인딩</span></a>을 설치하고, 데이터베이스 연결 설정과 맞게끔 <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> <code class=\"docutils literal notranslate\"><span class=\"pre\">'default'</span></code> 항목의 값을 다음의 키 값으로 바꿔주세요.</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-DATABASE-ENGINE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ENGINE</span></code></a> – <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.db.backends.sqlite3'</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.db.backends.postgresql'</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.db.backends.mysql'</span></code>, 또는 <code class=\"docutils literal notranslate\"><span class=\"pre\">'django.db.backends.oracle'</span></code>. 그외에 <a class=\"reference internal\" href=\"/ko/3.1/ref/databases/#third-party-notes\"><span class=\"std std-ref\">서드파티 백엔드</span></a> 참조.</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a> – The name of your database. If you’re using SQLite, the\ndatabase will be a file on your computer; in that case, <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-NAME\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">NAME</span></code></a>\nshould be the full absolute path, including filename, of that file. The\ndefault value, <code class=\"docutils literal notranslate\"><span class=\"pre\">BASE_DIR</span> <span class=\"pre\">/</span> <span class=\"pre\">'db.sqlite3'</span></code>, will store the file in your\nproject directory.</p></li>\n</ul>\n<p>SQLite 를 데이터베이스로 사용하지 않는 경우, <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-USER\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">USER</span></code></a>, <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-PASSWORD\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">PASSWORD</span></code></a>, <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-HOST\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">HOST</span></code></a> 같은 추가 설정이 반드시 필요합니다. 더 자세한 내용은 <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-DATABASES\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DATABASES</span></code></a> 문서를 참조해 주세요.</p>\n<aside class=\"admonition-for-databases-other-than-sqlite admonition\">\n<p class=\"admonition-title\">SQLite 이외의 데이터베이스라면</p>\n<p>만약 SQLite 이외의 데이터베이스를 사용하는 경우, 이 시점에서 데이터베이스를 생성해야 합니다. 데이터베이스의 대화형 프롬프트 내에서 “<code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">DATABASE</span> <span class=\"pre\">database_name;</span></code>” 명령을 실행하면 됩니다.</p>\n<p>또한, <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code> 에 설정된 데이터베이스 사용자가 “create database” 권한이 있는지도 확인해 봐야 합니다. 튜토리얼을 진행하며 필요한 경우 <a class=\"reference internal\" href=\"/ko/3.1/topics/testing/overview/#the-test-database\"><span class=\"std std-ref\">테스트 데이터베이스</span></a>를 자동으로 생성할 수 있도록 해줍니다.</p>\n<p>SQLite를 사용한다면 아무것도 미리 생성할 필요가 없습니다. 데이터베이스 파일은 필요할 때마다 자동으로 생성됩니다.</p>\n</aside>\n<p><code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code>를 편집할 때, 당신의 시간대에 맞춰 <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-TIME_ZONE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TIME_ZONE</span></code></a> 값을 설정하세요.</p>\n<p>또한, 이 파일의 윗쪽에 있는 <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 에 대해 언급하자면, 이 파일은 현재 Django 인스턴스에서 활성화된 모든 Django 어플리케이션들의 이름이 담겨 있습니다. 앱들은 다수의 프로젝트에서 사용될 수 있고, 다른 프로젝트에서 쉽게 사용될 수 있도록 패키징하여 배포할 수 있습니다.</p>\n<p>기본적으로는, <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>는 Django와 함께 딸려오는 다음의 앱들을 포함합니다.</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/ref/contrib/admin/#module-django.contrib.admin\" title=\"django.contrib.admin: Django's admin site.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.admin</span></code></a> – 관리용 사이트. 곧 사용하게 될 겁니다.</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/topics/auth/#module-django.contrib.auth\" title=\"django.contrib.auth: Django's authentication framework.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></code></a> – 인증 시스템.</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/ref/contrib/contenttypes/#module-django.contrib.contenttypes\" title=\"django.contrib.contenttypes: Provides generic interface to installed models.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.contenttypes</span></code></a> – 컨텐츠 타입을 위한 프레임워크.</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/topics/http/sessions/#module-django.contrib.sessions\" title=\"django.contrib.sessions: Provides session management for Django projects.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.sessions</span></code></a> – 세션 프레임워크.</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/ref/contrib/messages/#module-django.contrib.messages\" title=\"django.contrib.messages: Provides cookie- and session-based temporary message storage.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.messages</span></code></a> – 메세징 프레임워크.</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/ref/contrib/staticfiles/#module-django.contrib.staticfiles\" title=\"django.contrib.staticfiles: An app for handling static files.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.staticfiles</span></code></a> – 정적 파일을 관리하는 프레임워크.</p></li>\n</ul>\n<p>이 어플리케이션들은 일반적인 경우에 사용하기 편리하도록 기본으로 제공됩니다.</p>\n<p>이러한 기본 어플리케이션들 중 몇몇은 최소한 하나 이상의 데이터베이스 테이블을 사용하는데, 그러기 위해서는 데이터베이스에서 테이블을 미리 만들 필요가 있습니다. 이를 위해, 다음의 명령을 실행해봅시다.</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-0-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>migrate\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-0-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py migrate\n</code></pre></div></div></div>\n<p>The <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> command looks at the <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> setting\nand creates any necessary database tables according to the database settings\nin your <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code> file and the database migrations shipped\nwith the app (we’ll cover those later). You’ll see a message for each\nmigration it applies. If you’re interested, run the command-line client for your\ndatabase and type <code class=\"docutils literal notranslate\"><span class=\"pre\">\\dt</span></code> (PostgreSQL), <code class=\"docutils literal notranslate\"><span class=\"pre\">SHOW</span> <span class=\"pre\">TABLES;</span></code> (MariaDB, MySQL),\n<code class=\"docutils literal notranslate\"><span class=\"pre\">.schema</span></code> (SQLite), or <code class=\"docutils literal notranslate\"><span class=\"pre\">SELECT</span> <span class=\"pre\">TABLE_NAME</span> <span class=\"pre\">FROM</span> <span class=\"pre\">USER_TABLES;</span></code> (Oracle) to\ndisplay the tables Django created.</p>\n<aside class=\"admonition-for-the-minimalists admonition\">\n<p class=\"admonition-title\">최소주의자(minimalists)들을 위하여</p>\n<p>위에서 언급했다시피, 기본으로 제공되는 어플리케이션은 일반적인 상황을 염두에 두었으나, 모두에게 필요한 것은 아닙니다. 만약 이것들이 필요 없다고 생각되시면, <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> 를 실행하기 전에 <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 에서 제거할 어플리케이션들을 그냥 주석처리(comment-out) 하시거나 삭제하시면 됩니다. <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> 명령은 <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 에 등록된 어플리케이션에 한하여 실행될 것입니다.</p>\n</aside>\n</section>\n<section id=\"creating-models\">\n<span id=\"id1\"></span><h2>모델 만들기<a class=\"heading-anchor\" href=\"#creating-models\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>이제, 모델을 정의해 보겠습니다. 본질적으로, 모델이란 부가적인 메타데이터를 가진 데이터베이스의 구조(layout)를 말합니다.</p>\n<aside class=\"admonition-philosophy admonition\">\n<p class=\"admonition-title\">철학</p>\n<p>모델(“model”)은 데이터에 관한 단 하나의, 가장 확실한 진리의 원천입니다. 이것은 당신이 저장하는 데이터의 필수적인 필드들과 동작들을 포함하고 있습니다. Django 는 <a class=\"reference internal\" href=\"/ko/3.1/misc/design-philosophies/#dry\"><span class=\"std std-ref\">DRY 원칙</span></a> 을 따릅니다. 이 원칙에 따라 데이터 모델을 한곳에서 정의하고, 이것으로부터 자동으로 뭔가를 유도하는 것이 목표입니다.</p>\n<p>This includes the migrations - unlike in Ruby On Rails, for example, migrations\nare entirely derived from your models file, and are essentially a\nhistory that Django can roll through to update your database schema to\nmatch your current models.</p>\n</aside>\n<p>In our poll app, we’ll create two models: <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code>. A\n<code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> has a question and a publication date. A <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> has two\nfields: the text of the choice and a vote tally. Each <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> is associated\nwith a <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>.</p>\n<p>These concepts are represented by Python classes. Edit the\n<code class=\"file docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code> file so it looks like this:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/models.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Question</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">question_text</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">200</span><span class=\"p\">)</span>\n    <span class=\"n\">pub_date</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">DateTimeField</span><span class=\"p\">(</span><span class=\"s1\">&#39;date published&#39;</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Choice</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"n\">question</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignKey</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">,</span> <span class=\"n\">on_delete</span><span class=\"o\">=</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CASCADE</span><span class=\"p\">)</span>\n    <span class=\"n\">choice_text</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">200</span><span class=\"p\">)</span>\n    <span class=\"n\">votes</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">IntegerField</span><span class=\"p\">(</span><span class=\"n\">default</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>Here, each model is represented by a class that subclasses\n<a class=\"reference internal\" href=\"/ko/3.1/ref/models/instances/#django.db.models.Model\" title=\"django.db.models.Model\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.db.models.Model</span></code></a>. Each model has a number of class variables,\neach of which represents a database field in the model.</p>\n<p>데이터베이스의 각 필드는 <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> 클래스의 인스턴스로서 표현됩니다. <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a> 는 문자(character) 필드를 표현하고, <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a> 는 날짜와 시간(datetime) 필드를 표현합니다. 이것은 각 필드가 어떤 자료형을 가질 수 있는지를 Django 에게 말해줍니다.</p>\n<p>각각의 <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> 인스턴스의 이름(<code class=\"docutils literal notranslate\"><span class=\"pre\">question_text</span></code> 또는 <code class=\"docutils literal notranslate\"><span class=\"pre\">pub_date</span></code>)은 기계가 읽기 좋은 형식(machine-friendly format)의 데이터베이스 필드 이름입니다. 이 필드명을 Python 코드에서 사용할 수 있으며, 데이터베이스에서는 컬럼명으로 사용할 것입니다.</p>\n<p><a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> 클래스의 생성자에 선택적인 첫번째 위치 인수를 전달하여 사람이 읽기 좋은(human-readable) 이름을 지정할 수도 있습니다. 이 방법은 Django 의 내부를 설명하는 용도로 종종 사용되는데, 이는 마치 문서가 늘어나는 것 같은 효과를 가집니다. 만약 이 선택적인 첫번째 위치 인수를 사용하지 않으면, Django 는 기계가 읽기 좋은 형식의 이름을 사용합니다. 이 예제에서는, <code class=\"docutils literal notranslate\"><span class=\"pre\">Question.pub_date</span></code> 에 한해서만 인간이 읽기 좋은 형태의 이름을 정의하겠습니다. 그 외의 다른 필드들은, 기계가 읽기 좋은 형태의 이름이라도 사람이 읽기에는 충분합니다.</p>\n<p>몇몇 <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> 클래스들은 필수 인수가 필요합니다. 예를 들어, <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a> 의 경우 <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.CharField.max_length\" title=\"django.db.models.CharField.max_length\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">max_length</span></code></a> 를 입력해 주어야 합니다. 이것은 데이터베이스 스키마에서만 필요한것이 아닌 값을 검증할때도 쓰이는데, 곧 보게 될것입니다.</p>\n<p>또한 <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.Field\" title=\"django.db.models.Field\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Field</span></code></a> 는 다양한 선택적 인수들을 가질 수 있습니다. 이 예제에서는, <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.Field.default\" title=\"django.db.models.Field.default\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">default</span></code></a> 로 하여금 <code class=\"docutils literal notranslate\"><span class=\"pre\">votes</span></code> 의 기본값을 0 으로 설정하였습니다.</p>\n<p>마지막으로, <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.ForeignKey\" title=\"django.db.models.ForeignKey\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code></a> 를 사용한 관계설정에 대해 설명하겠습니다. 이 예제에서는 각각의 <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> 가 하나의 <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> 에 관계된다는 것을 Django 에게 알려줍니다. Django 는 다-대-일(many-to-one), 다-대-다(many-to-many), 일-대-일(one-to-one) 과 같은 모든 일반 데이터베이스의 관계들를 지원합니다.</p>\n</section>\n<section id=\"activating-models\">\n<h2>모델의 활성화<a class=\"heading-anchor\" href=\"#activating-models\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>모델에 대한 이 작은 코드가, Django에게는 상당한 양의 정보를 전달합니다. Django는 이 정보를 가지고 다음과 같은 일을 할 수 있습니다.</p>\n<ul class=\"simple\">\n<li><p>이 앱을 위한 데이터베이스 스키마 생성(<code class=\"docutils literal notranslate\"><span class=\"pre\">CREATE</span> <span class=\"pre\">TABLE</span></code> 문)</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>과 <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code> 객체에 접근하기 위한 Python 데이터베이스 접근 API를 생성</p></li>\n</ul>\n<p>그러나, 가장 먼저 현재 프로젝트에게 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 앱이 설치되어 있다는 것을 알려야 합니다.</p>\n<aside class=\"admonition-philosophy admonition\">\n<p class=\"admonition-title\">철학</p>\n<p>Django의 앱들은 “꼈다뺐다”할 수 있습니다. 앱을 다수의 프로젝트에서 사용할 수 있으며, 앱을 배포할 수도 있습니다. 특정 Django 사이트에 앱들이 묶여있지 않아도 되기 때문입니다.</p>\n</aside>\n<p>앱을 현재의 프로젝트에 포함시키기 위해서는, 앱의 구성 클래스에 대한 참조를 <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 설정에 추가해야 합니다. <code class=\"docutils literal notranslate\"><span class=\"pre\">PollsConfig</span></code> 클래스는 <code class=\"file docutils literal notranslate\"><span class=\"pre\">polls/apps.py</span></code> 파일 내에 존재합니다. 따라서, 점으로 구분된 경로는 <code class=\"docutils literal notranslate\"><span class=\"pre\">'polls.apps.PollsConfig'</span></code>가 됩니다. 이 점으로 구분된 경로를, <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code> 파일을 편집하여 <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a> 설정에 추가하면 됩니다. 이는 다음과 같이 보일 것입니다.</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">mysite/settings.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"n\">INSTALLED_APPS</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n    <span class=\"s1\">&#39;polls.apps.PollsConfig&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.admin&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.auth&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.contenttypes&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.sessions&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.messages&#39;</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;django.contrib.staticfiles&#39;</span><span class=\"p\">,</span>\n<span class=\"p\">]</span>\n</code></pre></figure>\n<p>이제, Django는 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 앱이 포함된 것을 알게 되었습니다. 다른 명령을 내려봅시다.</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-1-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>makemigrations<span class=\"w\"> </span>polls\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-1-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py makemigrations polls\n</code></pre></div></div></div>\n<p>다음과 비슷한 것이 보일 겁니다.</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>Migrations for &#39;polls&#39;:\n  polls/migrations/0001_initial.py\n    - Create model Question\n    - Create model Choice\n</code></pre></div>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code> 을 실행시킴으로서, 당신이 모델을 변경시킨 사실과(이 경우에는 새로운 모델을 만들었습니다) 이 변경사항을 <em>migration</em>으로 저장시키고 싶다는 것을 Django에게 알려줍니다.</p>\n<p>Migrations are how Django stores changes to your models (and thus your\ndatabase schema) - they’re files on disk. You can read the migration for your\nnew model if you like; it’s the file <code class=\"docutils literal notranslate\"><span class=\"pre\">polls/migrations/0001_initial.py</span></code>.\nDon’t worry, you’re not expected to read them every time Django makes one, but\nthey’re designed to be human-editable in case you want to manually tweak how\nDjango changes things.</p>\n<p>당신을 위해 migration들을 실행시켜주고, 자동으로 데이터베이스 스키마를 관리해주는 <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> 명령어가 있습니다. 이 명령을 알아보기 전에 migration이 내부적으로 어떤 SQL 문장을 실행하는지 살펴봅시다. <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-sqlmigrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">sqlmigrate</span></code></a> 명령은 migration 이름을 인수로 받아, 실행하는 SQL 문장을 보여줍니다.</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-2-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>sqlmigrate<span class=\"w\"> </span>polls<span class=\"w\"> </span><span class=\"m\">0001</span>\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-2-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py sqlmigrate polls 0001\n</code></pre></div></div></div>\n<p>다음과 비슷한 결과를 보실 수 있습니다. (가독성을 위해 결과물을 조금 다듬었습니다)</p>\n<div class=\"code-block\" data-language=\"sql\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">SQL</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"SQL code\"><code><span class=\"k\">BEGIN</span><span class=\"p\">;</span>\n<span class=\"c1\">--</span>\n<span class=\"c1\">-- Create model Question</span>\n<span class=\"c1\">--</span>\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_question&quot;</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;id&quot;</span><span class=\"w\"> </span><span class=\"nb\">serial</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"w\"> </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;question_text&quot;</span><span class=\"w\"> </span><span class=\"nb\">varchar</span><span class=\"p\">(</span><span class=\"mi\">200</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;pub_date&quot;</span><span class=\"w\"> </span><span class=\"k\">timestamp</span><span class=\"w\"> </span><span class=\"k\">with</span><span class=\"w\"> </span><span class=\"k\">time</span><span class=\"w\"> </span><span class=\"k\">zone</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span>\n<span class=\"p\">);</span>\n<span class=\"c1\">--</span>\n<span class=\"c1\">-- Create model Choice</span>\n<span class=\"c1\">--</span>\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice&quot;</span><span class=\"w\"> </span><span class=\"p\">(</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;id&quot;</span><span class=\"w\"> </span><span class=\"nb\">serial</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"w\"> </span><span class=\"k\">PRIMARY</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;choice_text&quot;</span><span class=\"w\"> </span><span class=\"nb\">varchar</span><span class=\"p\">(</span><span class=\"mi\">200</span><span class=\"p\">)</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;votes&quot;</span><span class=\"w\"> </span><span class=\"nb\">integer</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span><span class=\"p\">,</span>\n<span class=\"w\">    </span><span class=\"ss\">&quot;question_id&quot;</span><span class=\"w\"> </span><span class=\"nb\">integer</span><span class=\"w\"> </span><span class=\"k\">NOT</span><span class=\"w\"> </span><span class=\"k\">NULL</span>\n<span class=\"p\">);</span>\n<span class=\"k\">ALTER</span><span class=\"w\"> </span><span class=\"k\">TABLE</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice&quot;</span>\n<span class=\"w\">  </span><span class=\"k\">ADD</span><span class=\"w\"> </span><span class=\"k\">CONSTRAINT</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice_question_id_c5b4b260_fk_polls_question_id&quot;</span>\n<span class=\"w\">    </span><span class=\"k\">FOREIGN</span><span class=\"w\"> </span><span class=\"k\">KEY</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"ss\">&quot;question_id&quot;</span><span class=\"p\">)</span>\n<span class=\"w\">    </span><span class=\"k\">REFERENCES</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_question&quot;</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"ss\">&quot;id&quot;</span><span class=\"p\">)</span>\n<span class=\"w\">    </span><span class=\"k\">DEFERRABLE</span><span class=\"w\"> </span><span class=\"k\">INITIALLY</span><span class=\"w\"> </span><span class=\"k\">DEFERRED</span><span class=\"p\">;</span>\n<span class=\"k\">CREATE</span><span class=\"w\"> </span><span class=\"k\">INDEX</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice_question_id_c5b4b260&quot;</span><span class=\"w\"> </span><span class=\"k\">ON</span><span class=\"w\"> </span><span class=\"ss\">&quot;polls_choice&quot;</span><span class=\"w\"> </span><span class=\"p\">(</span><span class=\"ss\">&quot;question_id&quot;</span><span class=\"p\">);</span>\n\n<span class=\"k\">COMMIT</span><span class=\"p\">;</span>\n</code></pre></div>\n<p>다음을 참고하세요.</p>\n<ul class=\"simple\">\n<li><p>사용하는 데이터베이스에 따라서 출력결과는 다를 수 있습니다. 위의 출력결과는 PostgreSQL에서 생성되었습니다.</p></li>\n<li><p>테이블 이름은 앱의 이름과 모델의 이름(소문자)이 조합되어 자동으로 생성됩니다. 이 경우, 앱의 이름인 <code class=\"docutils literal notranslate\"><span class=\"pre\">polls</span></code> 와 소문자로 표기된 모델의 이름인 <code class=\"docutils literal notranslate\"><span class=\"pre\">question</span></code> 과 <code class=\"docutils literal notranslate\"><span class=\"pre\">choice</span></code>가 합쳐집니다. (이 동작을 재지정(override)하여 수정할 수 있습니다.)</p></li>\n<li><p>기본 키(ID)가 자동으로 추가됩니다. (역시 이 동작도 재지정할 수 있습니다.)</p></li>\n<li><p>관례에 따라, Django는 외래 키 필드명에 <code class=\"docutils literal notranslate\"><span class=\"pre\">&quot;_id&quot;</span></code> 이름을 자동으로 추가합니다. (물론 이것도 재지정할 수 있습니다.)</p></li>\n<li><p>The foreign key relationship is made explicit by a <code class=\"docutils literal notranslate\"><span class=\"pre\">FOREIGN</span> <span class=\"pre\">KEY</span></code>\nconstraint. Don’t worry about the <code class=\"docutils literal notranslate\"><span class=\"pre\">DEFERRABLE</span></code> parts; it’s telling\nPostgreSQL to not enforce the foreign key until the end of the transaction.</p></li>\n<li><p>사용하는 데이터베이스에 따라, 데이터베이스 고유의 필드타입이 조정됩니다. 따라서, 자동 증가 필드를 생성할 경우 <code class=\"docutils literal notranslate\"><span class=\"pre\">auto_increment</span></code>(MySQL), <code class=\"docutils literal notranslate\"><span class=\"pre\">serial</span></code>(PostgreSQL), <code class=\"docutils literal notranslate\"><span class=\"pre\">integer</span> <span class=\"pre\">primary</span> <span class=\"pre\">key</span> <span class=\"pre\">autoincrement</span></code>(SQLite)와 같이 사용하는 데이터베이스에 따라 적절한 필드타입이 자동으로 선택됩니다. 필드 명에 사용되는 인용부호도 상황에 따라 겹따옴표나 홑따옴표가 적절히 선택됩니다.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-sqlmigrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">sqlmigrate</span></code></a> command doesn’t actually run the migration on your\ndatabase - instead, it prints it to the screen so that you can see what SQL\nDjango thinks is required. It’s useful for checking what Django is going to\ndo or if you have database administrators who require SQL scripts for\nchanges.</p></li>\n</ul>\n<p>관심이 있다면, <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-check\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">check</span></code></a> 명령을 통해 마이그레이션을 수행하거나 데이터베이스를 건드리지 않고도 프로젝트의 문제를 확인할 수 있습니다.</p>\n<p>이제, <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> 를 실행시켜 데이터베이스에 모델과 관련된 테이블을 생성해봅시다.</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-3-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>migrate\n<span class=\"go\">Operations to perform:</span>\n<span class=\"go\">  Apply all migrations: admin, auth, contenttypes, polls, sessions</span>\n<span class=\"go\">Running migrations:</span>\n<span class=\"go\">  Rendering model states... DONE</span>\n<span class=\"go\">  Applying polls.0001_initial... OK</span>\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-3-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py migrate\n<span class=\"go\">Operations to perform:</span>\n<span class=\"go\">  Apply all migrations: admin, auth, contenttypes, polls, sessions</span>\n<span class=\"go\">Running migrations:</span>\n<span class=\"go\">  Rendering model states... DONE</span>\n<span class=\"go\">  Applying polls.0001_initial... OK</span>\n</code></pre></div></div></div>\n<p><a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">migrate</span></code></a> 명령은 아직 적용되지 않은 마이그레이션을 모두 수집해 이를 실행하며(Django는 <code class=\"docutils literal notranslate\"><span class=\"pre\">django_migrations</span></code> 테이블을 두어 마이그레이션 적용 여부를 추적합니다) 이 과정을 통해 모델에서의 변경 사항들과 데이터베이스의 스키마의 동기화가 이루어집니다.</p>\n<p>마이그레이션은 매우 기능이 강력하여, 마치 프로젝트를 개발할 때처럼 데이터베이스나 테이블에 손대지 않고도 모델의 반복적인 변경을 가능하게 해줍니다. 동작 중인 데이터베이스를 자료 손실 없이 업그레이드 하는 데 최적화 되어 있습니다. 튜토리얼의 나머지 부분에서 이 부분을 조금 더 살펴보겠습니다만, 지금은 모델의 변경을 만드는 세 단계의 지침을 기억하세요.</p>\n<ul class=\"simple\">\n<li><p>(<code class=\"docutils literal notranslate\"><span class=\"pre\">models.py</span></code> 에서) 모델을 변경합니다.</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-makemigrations\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">makemigrations</span></code></a>을 통해 이 변경사항에 대한 마이그레이션을 만드세요.</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/#django-admin-migrate\"><code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span></code></a> 명령을 통해 변경사항을 데이터베이스에 적용하세요.</p></li>\n</ul>\n<p>마이그레이션을 만드는 명령과 적용하는 명령이 분리된 것은 버전 관리 시스템에 마이그레이션을 커밋하고 앱과 함께 출시할 수 있도록 하기 위해서입니다. 이는 당신의 개발을 쉽게 해줄 뿐 아니라, 다른 개발자가 프로덕션에서 사용할 수 있게 해줍니다.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">manage.py</span></code> 유틸리티로 어떤 일들을 할 수 있는지 <a class=\"reference internal\" href=\"/ko/3.1/ref/django-admin/\"><span class=\"doc\">django-admin 문서</span></a>를 읽어보세요.</p>\n</section>\n<section id=\"playing-with-the-api\">\n<h2>API 가지고 놀기<a class=\"heading-anchor\" href=\"#playing-with-the-api\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>이제, 대화식 Python 쉘에 뛰어들어 Django API를 자유롭게 가지고 놀아봅시다. Python 쉘을 실행하려면 다음의 명령을 입력합니다.</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-4-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>shell\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-4-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py shell\n</code></pre></div></div></div>\n<p>We’re using this instead of simply typing “python”, because <code class=\"file docutils literal notranslate\"><span class=\"pre\">manage.py</span></code>\nsets the <span class=\"target\" id=\"index-0\"></span><a class=\"reference internal\" href=\"/ko/3.1/topics/settings/#envvar-DJANGO_SETTINGS_MODULE\"><code class=\"xref std std-envvar docutils literal notranslate\"><span class=\"pre\">DJANGO_SETTINGS_MODULE</span></code></a> environment variable, which gives\nDjango the Python import path to your <code class=\"file docutils literal notranslate\"><span class=\"pre\">mysite/settings.py</span></code> file.</p>\n<p>쉘에 진입한 후, <a class=\"reference internal\" href=\"/ko/3.1/topics/db/queries/\"><span class=\"doc\">데이터베이스 API</span></a>를 탐험해 보세요.</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">polls.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Choice</span><span class=\"p\">,</span> <span class=\"n\">Question</span>  <span class=\"c1\"># Import the model classes we just wrote.</span>\n\n<span class=\"go\"># No questions are in the system yet.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet []&gt;</span>\n\n<span class=\"go\"># Create a new Question.</span>\n<span class=\"go\"># Support for time zones is enabled in the default settings file, so</span>\n<span class=\"go\"># Django expects a datetime with tzinfo for pub_date. Use timezone.now()</span>\n<span class=\"go\"># instead of datetime.datetime.now() and it will do the right thing.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"p\">(</span><span class=\"n\">question_text</span><span class=\"o\">=</span><span class=\"s2\">&quot;What&#39;s new?&quot;</span><span class=\"p\">,</span> <span class=\"n\">pub_date</span><span class=\"o\">=</span><span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">())</span>\n\n<span class=\"go\"># Save the object into the database. You have to call save() explicitly.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n\n<span class=\"go\"># Now it has an ID.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">id</span>\n<span class=\"go\">1</span>\n\n<span class=\"go\"># Access model field values via Python attributes.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">question_text</span>\n<span class=\"go\">&quot;What&#39;s new?&quot;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">pub_date</span>\n<span class=\"go\">datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=&lt;UTC&gt;)</span>\n\n<span class=\"go\"># Change values by changing the attributes, then calling save().</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">question_text</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;What&#39;s up?&quot;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n\n<span class=\"go\"># objects.all() displays all the questions in the database.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: Question object (1)&gt;]&gt;</span>\n</code></pre></div>\n<p>여기서 잠깐. <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;Question:</span> <span class=\"pre\">Question</span> <span class=\"pre\">object</span> <span class=\"pre\">(1)&gt;</span></code>은 이 객체를 표현하는 데 별로 도움이 되지 않습니다. (<code class=\"docutils literal notranslate\"><span class=\"pre\">polls/models.py</span></code> 파일의) <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> 모델을 수정하여, <a class=\"reference internal\" href=\"/ko/3.1/ref/models/instances/#django.db.models.Model.__str__\" title=\"django.db.models.Model.__str__\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">__str__()</span></code></a> 메소드를 <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code>과 <code class=\"docutils literal notranslate\"><span class=\"pre\">Choice</span></code>에 추가해 봅시다.</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/models.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Question</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__str__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">question_text</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Choice</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"fm\">__str__</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">choice_text</span>\n</code></pre></figure>\n<p>당신의 모델에 <a class=\"reference internal\" href=\"/ko/3.1/ref/models/instances/#django.db.models.Model.__str__\" title=\"django.db.models.Model.__str__\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">__str__()</span></code></a> 메소드를 추가하는것은 객체의 표현을 대화식 프롬프트에서 편하게 보려는 이유 말고도, Django 가 자동으로 생성하는 관리 사이트 에서도 객체의 표현이 사용되기 때문입니다.</p>\n<p id=\"tutorial02-import-timezone\">이 모델에 커스텀 메소드 또한 추가해봅시다:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/models.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">datetime</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">models</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Question</span><span class=\"p\">(</span><span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">Model</span><span class=\"p\">):</span>\n    <span class=\"c1\"># ...</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">was_published_recently</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">pub_date</span> <span class=\"o\">&gt;=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span> <span class=\"o\">-</span> <span class=\"n\">datetime</span><span class=\"o\">.</span><span class=\"n\">timedelta</span><span class=\"p\">(</span><span class=\"n\">days</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">import</span> <span class=\"pre\">datetime</span></code>은 Python의 표준 모듈인 <a class=\"reference external\" href=\"https://docs.python.org/3/library/datetime.html#module-datetime\" title=\"(Python v3.14에서)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">datetime</span></code></a> 모듈을, <code class=\"docutils literal notranslate\"><span class=\"pre\">from</span> <span class=\"pre\">django.utils</span> <span class=\"pre\">import</span> <span class=\"pre\">timezone</span></code>은 Django의 시간대 관련 유틸리티인 <a class=\"reference internal\" href=\"/ko/3.1/ref/utils/#module-django.utils.timezone\" title=\"django.utils.timezone: Timezone support.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.utils.timezone</span></code></a>을 참조하기 위해 추가한 것입니다. 만약 Python에서 시간대를 조작하는 방법에 대해 익숙하지 않다면, <a class=\"reference internal\" href=\"/ko/3.1/topics/i18n/timezones/\"><span class=\"doc\">시간대 지원 문서</span></a>에서 더 많은 것을 배울 수 있습니다.</p>\n<p>변경된 사항을 저장하고, <code class=\"docutils literal notranslate\"><span class=\"pre\">python</span> <span class=\"pre\">manage.py</span> <span class=\"pre\">shell</span></code>를 다시 실행해보세요.</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">polls.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Choice</span><span class=\"p\">,</span> <span class=\"n\">Question</span>\n\n<span class=\"go\"># Make sure our __str__() addition worked.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: What&#39;s up?&gt;]&gt;</span>\n\n<span class=\"go\"># Django provides a rich database lookup API that&#39;s entirely driven by</span>\n<span class=\"go\"># keyword arguments.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: What&#39;s up?&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">question_text__startswith</span><span class=\"o\">=</span><span class=\"s1\">&#39;What&#39;</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Question: What&#39;s up?&gt;]&gt;</span>\n\n<span class=\"go\"># Get the question that was published this year.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.utils</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">timezone</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">current_year</span> <span class=\"o\">=</span> <span class=\"n\">timezone</span><span class=\"o\">.</span><span class=\"n\">now</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">year</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pub_date__year</span><span class=\"o\">=</span><span class=\"n\">current_year</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;Question: What&#39;s up?&gt;</span>\n\n<span class=\"go\"># Request an ID that doesn&#39;t exist, this will raise an exception.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">2</span><span class=\"p\">)</span>\n<span class=\"gt\">Traceback (most recent call last):</span>\n<span class=\"w\">    </span><span class=\"o\">...</span>\n<span class=\"gr\">DoesNotExist</span>: <span class=\"n\">Question matching query does not exist.</span>\n\n<span class=\"x\"># Lookup by a primary key is the most common case, so Django provides a</span>\n<span class=\"x\"># shortcut for primary-key exact lookups.</span>\n<span class=\"x\"># The following is identical to Question.objects.get(id=1).</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;Question: What&#39;s up?&gt;</span>\n\n<span class=\"go\"># Make sure our custom method worked.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">was_published_recently</span><span class=\"p\">()</span>\n<span class=\"go\">True</span>\n\n<span class=\"go\"># Give the Question a couple of Choices. The create call constructs a new</span>\n<span class=\"go\"># Choice object, does the INSERT statement, adds the choice to the set</span>\n<span class=\"go\"># of available choices and returns the new Choice object. Django creates</span>\n<span class=\"go\"># a set to hold the &quot;other side&quot; of a ForeignKey relation</span>\n<span class=\"go\"># (e.g. a question&#39;s choice) which can be accessed via the API.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span> <span class=\"o\">=</span> <span class=\"n\">Question</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">pk</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n\n<span class=\"go\"># Display any choices from the related object set -- none so far.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet []&gt;</span>\n\n<span class=\"go\"># Create three choices.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">choice_text</span><span class=\"o\">=</span><span class=\"s1\">&#39;Not much&#39;</span><span class=\"p\">,</span> <span class=\"n\">votes</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;Choice: Not much&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">choice_text</span><span class=\"o\">=</span><span class=\"s1\">&#39;The sky&#39;</span><span class=\"p\">,</span> <span class=\"n\">votes</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;Choice: The sky&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">choice_text</span><span class=\"o\">=</span><span class=\"s1\">&#39;Just hacking again&#39;</span><span class=\"p\">,</span> <span class=\"n\">votes</span><span class=\"o\">=</span><span class=\"mi\">0</span><span class=\"p\">)</span>\n\n<span class=\"go\"># Choice objects have API access to their related Question objects.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">question</span>\n<span class=\"go\">&lt;Question: What&#39;s up?&gt;</span>\n\n<span class=\"go\"># And vice versa: Question objects get access to Choice objects.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n<span class=\"go\">&lt;QuerySet [&lt;Choice: Not much&gt;, &lt;Choice: The sky&gt;, &lt;Choice: Just hacking again&gt;]&gt;</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">count</span><span class=\"p\">()</span>\n<span class=\"go\">3</span>\n\n<span class=\"go\"># The API automatically follows relationships as far as you need.</span>\n<span class=\"go\"># Use double underscores to separate relationships.</span>\n<span class=\"go\"># This works as many levels deep as you want; there&#39;s no limit.</span>\n<span class=\"go\"># Find all Choices for any question whose pub_date is in this year</span>\n<span class=\"go\"># (reusing the &#39;current_year&#39; variable we created above).</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">Choice</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">question__pub_date__year</span><span class=\"o\">=</span><span class=\"n\">current_year</span><span class=\"p\">)</span>\n<span class=\"go\">&lt;QuerySet [&lt;Choice: Not much&gt;, &lt;Choice: The sky&gt;, &lt;Choice: Just hacking again&gt;]&gt;</span>\n\n<span class=\"go\"># Let&#39;s delete one of the choices. Use delete() for that.</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span> <span class=\"o\">=</span> <span class=\"n\">q</span><span class=\"o\">.</span><span class=\"n\">choice_set</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span><span class=\"n\">choice_text__startswith</span><span class=\"o\">=</span><span class=\"s1\">&#39;Just hacking&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">c</span><span class=\"o\">.</span><span class=\"n\">delete</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>모델의 관계에 대한 더 많은 정보는 <a class=\"reference internal\" href=\"/ko/3.1/ref/models/relations/\"><span class=\"doc\">관련 객체에 접근하기</span></a>를 참조하세요. API에서 이중 밑줄(<code class=\"docutils literal notranslate\"><span class=\"pre\">__</span></code>) 을 이용해서 어떻게 필드를 조회할 수 있는지는 <a class=\"reference internal\" href=\"/ko/3.1/topics/db/queries/#field-lookups-intro\"><span class=\"std std-ref\">필드 조회</span></a>를 읽어보세요.데이터베이스 API에 대한 자세한 내용을 보려면, <a class=\"reference internal\" href=\"/ko/3.1/topics/db/queries/\"><span class=\"doc\">데이터베이스 API 레퍼런스</span></a>를 읽어보세요.</p>\n</section>\n<section id=\"introducing-the-django-admin\">\n<h2>Django 관리자 소개<a class=\"heading-anchor\" href=\"#introducing-the-django-admin\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<aside class=\"admonition-philosophy admonition\">\n<p class=\"admonition-title\">철학</p>\n<p>직원들이나 고객들이 컨텐츠를 수정하기 위한 관리자 사이트를 만드는 것은 딱히 창의적일 필요없는 지루한 작업입니다. 이런 이유로, Django는 모델에 대한 관리용 인터페이스를 모두 자동으로 생성합니다.</p>\n<p>Django는 <code class=\"docutils literal notranslate\"><span class=\"pre\">Lawrence</span> <span class=\"pre\">Journal-World</span></code> 신문사의 프로그래머가 처음 개발하였습니다. 이런 태생적인 이유 때문에, “컨텐츠 게시자” 와 “공개” 사이트의 구분이 명확합니다. 사이트 관리자는 뉴스 기사, 사건, 스포츠 경기 결과 같은 것들을 시스템에 추가합니다. 그렇게 추가된 컨텐츠는 “공개” 사이트에 노출됩니다. Django는 사이트 관리자가 컨텐츠를 편집할 수 있는 통합적인 인터페이스를 생성하는 문제를 해결합니다.</p>\n<p>관리자 사이트는 사이트 방문자를 위한 것이 아니라, 사이트 관리자를 위한 것입니다.</p>\n</aside>\n<section id=\"creating-an-admin-user\">\n<h3>관리자 생성하기<a class=\"heading-anchor\" href=\"#creating-an-admin-user\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>우선, 관리 사이트에 로그인 할 수 있는 사용자를 생성해 봅시다. 다음과 같은 명령을 수행합니다.</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-5-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>createsuperuser\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-5-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py createsuperuser\n</code></pre></div></div></div>\n<p>원하는 username 을 입력하고 엔터를 누르세요</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>Username: admin\n</code></pre></div>\n<p>그런 다음 원하는 이메일 주소를 입력하라는 메시지가 표시됩니다.</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>Email address: admin@example.com\n</code></pre></div>\n<p>마지막으로, 암호를 입력하세요. 암호를 두번 물어보게 되는데, 두번째 입력하는 암호를 올바로 입력했는지를 확인하기 위한 암호입니다.</p>\n<div class=\"code-block\" data-language=\"text\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Text</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Text code\"><code>Password: **********\nPassword (again): *********\nSuperuser created successfully.\n</code></pre></div>\n</section>\n<section id=\"start-the-development-server\">\n<h3>개발 서버 시작<a class=\"heading-anchor\" href=\"#start-the-development-server\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Django 관리자 사이트는 기본으로 활성화되어 있습니다. 개발 서버를 켜고, 탐험해 봅시다.</p>\n<p>서버가 동작하고 있지 않다면 다음 명령으로 시작합니다.</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-6-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span>python<span class=\"w\"> </span>manage.py<span class=\"w\"> </span>runserver\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-6-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> py manage.py runserver\n</code></pre></div></div></div>\n<p>이제, 웹 브라우져를 열고 로컬 도메인의 “/admin/”으로 이동합니다. 예를 들면, <a class=\"reference external\" href=\"http://127.0.0.1:8000/admin/\">http://127.0.0.1:8000/admin/</a>으로 접근할 수 있습니다. 그럼 다음과 같이 로그인 화면이 보일 겁니다.</p>\n<img alt=\"Django admin login screen\" src=\"/ko/3.1/_images/admin01.png\" />\n<p>Since <a class=\"reference internal\" href=\"/ko/3.1/topics/i18n/translation/\"><span class=\"doc\">translation</span></a> is turned on by default, if\nyou set <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-LANGUAGE_CODE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LANGUAGE_CODE</span></code></a>, the login screen will be displayed in the\ngiven language (if Django has appropriate translations).</p>\n</section>\n<section id=\"enter-the-admin-site\">\n<h3>관리자 사이트에 들어가기<a class=\"heading-anchor\" href=\"#enter-the-admin-site\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>앞서 생성한 슈퍼유저(superuser) 계정으로 로그인해봅시다. 다음과 같은 Django 관리 인덱스 페이지가 보일 것입니다.</p>\n<img alt=\"Django admin index page\" src=\"/ko/3.1/_images/admin02.png\" />\n<p>편집 가능한 그룹과 사용자와 같은 몇 종류의 컨텐츠를 볼 수 있습니다. 이것들은 <a class=\"reference internal\" href=\"/ko/3.1/topics/auth/#module-django.contrib.auth\" title=\"django.contrib.auth: Django's authentication framework.\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">django.contrib.auth</span></code></a> 모듈에서 제공되는데, Django 에서 제공되는 인증 프레임워크 입니다.</p>\n</section>\n<section id=\"make-the-poll-app-modifiable-in-the-admin\">\n<h3>관리 사이트에서 poll app 을 변경가능하도록 만들기<a class=\"heading-anchor\" href=\"#make-the-poll-app-modifiable-in-the-admin\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>그런데, poll app 이 관리 인덱스 페이지에서 보이지 않네요. 어디에 있을까요?</p>\n<p>Only one more thing to do: we need to tell the admin that <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> objects\nhave an admin interface. To do this, open the <code class=\"file docutils literal notranslate\"><span class=\"pre\">polls/admin.py</span></code> file, and\nedit it to look like this:</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\">polls/admin.py</figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">admin</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Question</span>\n\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">register</span><span class=\"p\">(</span><span class=\"n\">Question</span><span class=\"p\">)</span>\n</code></pre></figure>\n</section>\n<section id=\"explore-the-free-admin-functionality\">\n<h3>자유로운 관리 기능을 탐색하기<a class=\"heading-anchor\" href=\"#explore-the-free-admin-functionality\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>이제, <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> 을 등록시켰으니 Django 는 이를 알아채고 관리 인덱스 페이지에 이를 표시할 것입니다:</p>\n<img alt=\"Django admin index page, now with polls displayed\" src=\"/ko/3.1/_images/admin03t.png\" />\n<p>“Questions” 을 클릭하십시요. 그러면 질문들을 위한 “change list” 로 이동합니다. 이 페이지는 데이터베이스에 저장된 모든 질문들을 보여주며, 그 중 하나를 선택하여 변경할 수 있습니다. 이전에 등록했던 “What’s up?” 질문이 있을 것입니다.</p>\n<img alt=\"Polls change list page\" src=\"/ko/3.1/_images/admin04t.png\" />\n<p>“What’s up?” 질문을 클릭하여 수정합니다.</p>\n<img alt=\"Editing form for question object\" src=\"/ko/3.1/_images/admin05t.png\" />\n<p>여기서 알아둘 것들:</p>\n<ul class=\"simple\">\n<li><p>이 서식은 <code class=\"docutils literal notranslate\"><span class=\"pre\">Question</span></code> 모델에서 자동으로 생성되었습니다</p></li>\n<li><p>모델의 각 필드 유형들은 (<a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a>, <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.CharField\" title=\"django.db.models.CharField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">CharField</span></code></a>) 적절한 HTML 입력 위젯으로 표현됩니다. 필드의 각 유형들은 Django 관리 사이트에서 어떻게 표현해되어야 할지 알고 있습니다.</p></li>\n<li><p>각각의 <a class=\"reference internal\" href=\"/ko/3.1/ref/models/fields/#django.db.models.DateTimeField\" title=\"django.db.models.DateTimeField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">DateTimeField</span></code></a> 는 JavaScript 로 작성된 단축 기능과 연결됩니다. 날짜는 “오늘”(“Today”) 버튼과 달력 팝업에서 입력할 수 있으며, 시간은 “지금”(“Now”) 버튼과 일반적으로 입력하는 시간들을 제공하는 편리한 팝업을 통해서도 입력할 수 있습니다.</p></li>\n</ul>\n<p>페이지의 아래 부분에서 다음과 같은 몇가지 옵션을 제공합니다.</p>\n<ul class=\"simple\">\n<li><p>저장(Save) – 이 유형의 객체에 대한 변경사항을 저장하고, 변경된 목록 페이지를 보여줍니다</p></li>\n<li><p>저장 및 편집 계속(Save and continue editing) – 이 객체에 대한 변경사항을 저장하고, 현재 편집창을 갱신합니다</p></li>\n<li><p>저장 및 다른 이름으로 추가(Save and add another) – 변경사항을 저장하고, 이 유형의 객체에 대한 비어있는 새로운 입력창을 불러옵니다</p></li>\n<li><p>삭제(Delete) – 삭제를 확인하는 페이지를 띄웁니다.</p></li>\n</ul>\n<p>만약 “Date published” 의 값이 <a class=\"reference internal\" href=\"/ko/3.1/intro/tutorial01/\"><span class=\"doc\">Tutorial 1</span></a> 에서 질문을 생성했을때의 시간과 일치하지 않는다면, <a class=\"reference internal\" href=\"/ko/3.1/ref/settings/#std-setting-TIME_ZONE\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">TIME_ZONE</span></code></a> (시간대) 설정을 깜빡 하신것일지도 모릅니다. 이 설정을 바꾸시고 다시 페이지를 불러오시면 올바른 값이 표현됩니다.</p>\n<p>“Date published” 의 값을 “오늘”(“Today”) 과 “지금”(“Now”) 단축버튼을 눌러 바꾸십시요. 그런 후, “저장 및 편집 계속”(“Save and continue editing”) 을 누르십시요. 그런 후, 우측 상단의 “히스토리”(“History”) 버튼을 누르십시요. Django 관리사이트를 통해 누가(username) 언제(timestamp) 무엇을 바꾸었는지 목록을 확인할 수 있습니다.</p>\n<img alt=\"History page for question object\" src=\"/ko/3.1/_images/admin06t.png\" />\n<p>모델 API와 관리 사이트에 익숙해졌다면, <a class=\"reference internal\" href=\"/ko/3.1/intro/tutorial03/\"><span class=\"doc\">이 튜토리얼의 3장</span></a>에서 투표 앱에 뷰를 추가하는 방법을 배워보세요.</p>\n</section>\n</section>","rootId":"writing-your-first-django-app-part-2","toc":[{"title":"데이터베이스 설치","anchor":"database-setup","children":[]},{"title":"모델 만들기","anchor":"creating-models","children":[]},{"title":"모델의 활성화","anchor":"activating-models","children":[]},{"title":"API 가지고 놀기","anchor":"playing-with-the-api","children":[]},{"title":"Django 관리자 소개","anchor":"introducing-the-django-admin","children":[{"title":"관리자 생성하기","anchor":"creating-an-admin-user","children":[]},{"title":"개발 서버 시작","anchor":"start-the-development-server","children":[]},{"title":"관리자 사이트에 들어가기","anchor":"enter-the-admin-site","children":[]},{"title":"관리 사이트에서 poll app 을 변경가능하도록 만들기","anchor":"make-the-poll-app-modifiable-in-the-admin","children":[]},{"title":"자유로운 관리 기능을 탐색하기","anchor":"explore-the-free-admin-functionality","children":[]}]}],"breadcrumbs":[{"docname":"intro/index","title":"시작하기","url":"/ko/3.1/intro/"}],"prev":{"docname":"intro/tutorial01","title":"첫 번째 장고 앱 작성하기, part 1","url":"/ko/3.1/intro/tutorial01/"},"next":{"docname":"intro/tutorial03","title":"첫 번째 장고 앱 작성하기, part 3","url":"/ko/3.1/intro/tutorial03/"},"formats":{"html":"/ko/3.1/intro/tutorial02/","markdown":"/ko/3.1/intro/tutorial02.md","json":"/ko/3.1/intro/tutorial02.json"},"source":"https://github.com/django/django/blob/stable/3.1.x/docs/intro/tutorial02.txt","official":"https://docs.djangoproject.com/ko/3.1/intro/tutorial02/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}