{"title":"Django 인증 커스터마이징하기","version":"4.1","locale":"ko","docname":"topics/auth/customizing","url":"/ko/4.1/topics/auth/customizing/","canonical":"https://djangodocs.dev/ko/4.1/topics/auth/customizing/","summary":"Django에 포함된 인증은 대부분의 일반적인 경우에서 충분히 좋습니다. 그렇지만 원한다면 Django 기본 인증에서 벗어나셔도 됩니다. 당신의 프로젝트에서 인증에 대한 사항을 커스터마이징하기 위해서는 먼저 시스템이 제공해주는 것 중에 어떤 것이 확장 가능하고 어떤 것이 대체 가능한지 알아야…","html":"<h1>Django 인증 커스터마이징하기<a class=\"heading-anchor\" href=\"#customizing-authentication-in-django\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django에 포함된 인증은 대부분의 일반적인 경우에서 충분히 좋습니다. 그렇지만 원한다면 Django 기본 인증에서 벗어나셔도 됩니다. 당신의 프로젝트에서 인증에 대한 사항을 커스터마이징하기 위해서는 먼저 시스템이 제공해주는 것 중에 어떤 것이 확장 가능하고 어떤 것이 대체 가능한지 알아야 합니다. 이 문서는 어떻게 인증 시스템을 커스터마이징 할 수 있는지에 대해서 자세히 다룹니다.</p>\n<p>:ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>인증 백엔드 &lt;authentication-backends&gt;`는 user model에 저장된 username과 password이 Django의 디폴트가 아닌 다른 서비스에서 인증되어야 할 경우를 위한 확장가능한 시스템을 제공합니다.</p>\n<p>독자는 자신의 모델에 Django의 인증 시스템을 통해 확인할 수 있는 :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>맞춤 권한 &lt;custom-permissions&gt;`을 줄 수 있습니다.</p>\n<p>독자는 디폴트 <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> 모델을 :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>확장 &lt;extending-user&gt;`하거나 완전히 맞춤화된 모델로 :ref:<a href=\"#id3\"><span class=\"problematic\" id=\"id4\">`</span></a>대체 &lt;auth-custom-user&gt;`할 수 있습니다.</p>\n<section id=\"other-authentication-sources\">\n<span id=\"authentication-backends\"></span><h2>다른 인증 소스들<a class=\"heading-anchor\" href=\"#other-authentication-sources\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>또 다른 인증 소스가 필요한 순간이 있을 수 있습니다 – 즉, username과 password 또는 인증 메소드의 또 다른 소스.</p>\n<p>예를 들어 독자의 회사가 모든 직원의 username과 password를 저장하는 LDAP 설정을 이미 가지고 있을 수 있습니다. 만약 사용자가 계정을 LDAP와 Django기반의 애플리케이션에 분리했다면 그건 네트워크 관리자와 사용자 모두에게 곤란할 것입니다.</p>\n<p>따라서 이런 상황을 다루기 위해 Django 인증 시스템은 독자가 다른 인증 소스에 플러그인 할 수 있게 해줍니다. 독자는 Django의 디폴트 데이터베이스 기반 스키마를 오버라이드할 수 있습니다. 또는 독자는 다른 시스템과 협력관계로 디폴트 시스템을 사용할 수 있습니다.</p>\n<p>Django에 포함된 인증 백엔드에 관한 정보는 :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>인증 백엔드 참조 &lt;authentication-backends-reference&gt;`에서 볼 수 있습니다.</p>\n<section id=\"specifying-authentication-backends\">\n<h3>인증 백엔드 명세하기<a class=\"heading-anchor\" href=\"#specifying-authentication-backends\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>비하인드로 Django는 인증을 확인하는 “인증 백엔드” 리스트를 유지하고 있습니다. 누군가 :func:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>django.contrib.auth.authenticate()`를 호출하면 –  :ref:<a href=\"#id3\"><span class=\"problematic\" id=\"id4\">`</span></a>사용자 로그인 방법 &lt;how-to-log-a-user-in&gt;`에서 서술한 것처럼 – Django는 모든 인증 백엔드를 거쳐 인증을 시도합니다. 만약 가장 처음의 인증 메소드가 실패하면 Django는 두번째 것을 시도하고 모든 백엔드가 시도될 때까지 반복합니다.</p>\n<p>사용하는 인증 백엔드 리스트는 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> 설정에 명세됩니다. 이것은 인증하는 방법을 알고 있는 Python 클래스를 가리키는 Python 경로 이름 리스트 이어야 합니다. 이 클래스들은 독자의 Python 경로의 어디에나 있을 수 있습니다.</p>\n<p>디폴트로 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></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=\"p\">[</span><span class=\"s1\">&#39;django.contrib.auth.backends.ModelBackend&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<p>django 사용자 데이터베이스를 확인하고 내장된 권한을 질의하는 기초 인증 백엔드이다. 속도 제한 메커니즘을 통한 무차별 대입 공격에 대한 보호를 제공하지 않는다. 맞춤 인증 백엔드에서 자체 속도 제한 메커니즘을 구현하거나 대부분의 웹 서버에서 제공하는 메커니즘을 사용할 수 있다.</p>\n<p><a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a> 의 순서는 중요합니다. 만약 같은 username과 password가 참인 여러 개의 백엔드가 있으면 Django는 첫번째 참인 곳에서 처리를 멈출 것입니다.</p>\n<p>만약 백엔드가 <a class=\"reference internal\" href=\"/ko/4.1/ref/exceptions/#django.core.exceptions.PermissionDenied\" title=\"django.core.exceptions.PermissionDenied\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PermissionDenied</span></code></a> 예외를 발생시키면, 인증은 즉시 실패할 것입니다. Django는 뒤따르는 백엔드는 확인하지 않습니다.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">참고</p>\n<p>Once a user has authenticated, Django stores which backend was used to\nauthenticate the user in the user’s session, and reuses the same backend\nfor the duration of that session whenever access to the currently\nauthenticated user is needed. This effectively means that authentication\nsources are cached on a per-session basis, so if you change\n<a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTHENTICATION_BACKENDS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTHENTICATION_BACKENDS</span></code></a>, you’ll need to clear out session data if\nyou need to force users to re-authenticate using different methods. A\nsimple way to do that is to execute <code class=\"docutils literal notranslate\"><span class=\"pre\">Session.objects.all().delete()</span></code>.</p>\n</aside>\n</section>\n<section id=\"writing-an-authentication-backend\">\n<h3>인증 백엔드 작성하기<a class=\"heading-anchor\" href=\"#writing-an-authentication-backend\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>인증 백엔드는 두 가지 필수 메소드를 구현하는 클래스입니다: <a class=\"reference internal\" href=\"#authorization-methods\"><span class=\"std std-ref\">인증 메소드</span></a> 와 관련된 선택적 권한 집합 뿐만 아니라 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_user(user_id)</span></code> 와 <code class=\"docutils literal notranslate\"><span class=\"pre\">authenticate(request,</span> <span class=\"pre\">**credentials)</span></code>.</p>\n<p>get_user`` 메소드는 <code class=\"docutils literal notranslate\"><span class=\"pre\">user_id</span></code> 를 반환하는데, 이것은 username, 데이터베이스 ID 또는 무엇이든 될 수 있습니다. 하지만 user object 의 primary key 이어야 하며 사용자 객체를 반환합니다.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">authenticate</span></code> 메소드는 키워드 인자로 <code class=\"docutils literal notranslate\"><span class=\"pre\">request</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.backends</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BaseBackend</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyBackend</span><span class=\"p\">(</span><span class=\"n\">BaseBackend</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">authenticate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">username</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Check the username/password and return a user.</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p>하지만 이것은 또한 다음과 같이 토큰을 인증하는 것일 수 있습니다:</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.backends</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BaseBackend</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyBackend</span><span class=\"p\">(</span><span class=\"n\">BaseBackend</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">authenticate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">token</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Check the token and return a user.</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p>어느 것이든 <code class=\"docutils literal notranslate\"><span class=\"pre\">authenticate()</span></code> 는 자격 증명을 확인하고 이 자격 증명이 참인 경우 이 자격 증명과 매치하는 사용자 객체를 리턴해야 합니다. 만약 참이 아니라면 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>None``을 리턴해야 합니다.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">request</span></code> 는 django.http.HttpRequest 라는 Class 이고 만일 django.contrib.auth.authenticate 함수 (백엔드로 그걸 전달하는) 가  제공되지 않으면 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> 일 수 있습니다.</p>\n<p>Django 관리자는 Django <a class=\"reference internal\" href=\"/ko/4.1/topics/auth/default/#user-objects\"><span class=\"std std-ref\">사용자 객체</span></a> 와 단단히 결합되어 있습니다. 관리자를 다루는 가장 좋은 방법은 Django <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> 객체를 독자의 백엔드 에 존재하는 각 사용자로 생성하는 것입니다. (e.g., 독자의 LDAP 디렉토리 에서 외부 SQL 데이터베이스 등) 사전에 스크립트를 작성해서 하거나 <code class=\"docutils literal notranslate\"><span class=\"pre\">authenticate</span></code> 메소드가 사용자가 로그인한 첫 순간에 할 수 있습니다.</p>\n<p>여기에 여러분의 <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code> 파일에 정의된 username 과 password 로 인증하여 사용자가 첫 번째로 인증할 때 Django <code class=\"docutils literal notranslate\"><span class=\"pre\">User</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.conf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">settings</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.backends</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BaseBackend</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.hashers</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">check_password</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">User</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">SettingsBackend</span><span class=\"p\">(</span><span class=\"n\">BaseBackend</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">    Authenticate against the settings ADMIN_LOGIN and ADMIN_PASSWORD.</span>\n\n<span class=\"sd\">    Use the login name and a hash of the password. For example:</span>\n\n<span class=\"sd\">    ADMIN_LOGIN = &#39;admin&#39;</span>\n<span class=\"sd\">    ADMIN_PASSWORD = &#39;pbkdf2_sha256$30000$Vo0VlMnkR4Bk$qEvtdyZRWTcOsCnI/oQ7fVOu1XAURIZYoOZ3iq8Dr4M=&#39;</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">authenticate</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">request</span><span class=\"p\">,</span> <span class=\"n\">username</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"n\">login_valid</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">ADMIN_LOGIN</span> <span class=\"o\">==</span> <span class=\"n\">username</span><span class=\"p\">)</span>\n        <span class=\"n\">pwd_valid</span> <span class=\"o\">=</span> <span class=\"n\">check_password</span><span class=\"p\">(</span><span class=\"n\">password</span><span class=\"p\">,</span> <span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">ADMIN_PASSWORD</span><span class=\"p\">)</span>\n        <span class=\"k\">if</span> <span class=\"n\">login_valid</span> <span class=\"ow\">and</span> <span class=\"n\">pwd_valid</span><span class=\"p\">:</span>\n            <span class=\"k\">try</span><span class=\"p\">:</span>\n                <span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"n\">User</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\">username</span><span class=\"o\">=</span><span class=\"n\">username</span><span class=\"p\">)</span>\n            <span class=\"k\">except</span> <span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">DoesNotExist</span><span class=\"p\">:</span>\n                <span class=\"c1\"># Create a new user. There&#39;s no need to set a password</span>\n                <span class=\"c1\"># because only the password from settings.py is checked.</span>\n                <span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"n\">User</span><span class=\"p\">(</span><span class=\"n\">username</span><span class=\"o\">=</span><span class=\"n\">username</span><span class=\"p\">)</span>\n                <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_staff</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n                <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_superuser</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n                <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n            <span class=\"k\">return</span> <span class=\"n\">user</span>\n        <span class=\"k\">return</span> <span class=\"kc\">None</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">get_user</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">user_id</span><span class=\"p\">):</span>\n        <span class=\"k\">try</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"n\">User</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=\"n\">user_id</span><span class=\"p\">)</span>\n        <span class=\"k\">except</span> <span class=\"n\">User</span><span class=\"o\">.</span><span class=\"n\">DoesNotExist</span><span class=\"p\">:</span>\n            <span class=\"k\">return</span> <span class=\"kc\">None</span>\n</code></pre></div>\n</section>\n<section id=\"handling-authorization-in-custom-backends\">\n<span id=\"authorization-methods\"></span><h3>맞춤 백엔드 에서 인증 다루기<a class=\"heading-anchor\" href=\"#handling-authorization-in-custom-backends\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>맞춤 인증 백엔드는 스스로 권한을 제공할 수 있다.</p>\n<p>사용자 모델과 관리자는 권환 조회 함수(<a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.get_user_permissions\" title=\"django.contrib.auth.models.User.get_user_permissions\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_user_permissions()</span></code></a>, <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.get_group_permissions\" title=\"django.contrib.auth.models.User.get_group_permissions\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_group_permissions()</span></code></a>, <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.get_all_permissions\" title=\"django.contrib.auth.models.User.get_all_permissions\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get_all_permissions()</span></code></a>, <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.has_perm\" title=\"django.contrib.auth.models.User.has_perm\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_perm()</span></code></a>, <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.has_module_perms\" title=\"django.contrib.auth.models.User.has_module_perms\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_module_perms()</span></code></a>, 및 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.UserManager.with_perm\" title=\"django.contrib.auth.models.UserManager.with_perm\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">with_perm()</span></code></a>)를 이런 함수들을 구현하는 인증 백엔드에 위임할 것이다.</p>\n<p>사용자에게 주어진 권한은 모든 백엔드에서 반환되는 전체 권한의 상위 집합일 것입니다. 즉, Django 는 하나의 백엔드를 주는 사용자에게 권한을 줍니다.</p>\n<p>만약 백엔드가 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.has_perm\" title=\"django.contrib.auth.models.User.has_perm\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_perm()</span></code></a> 이나 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.has_module_perms\" title=\"django.contrib.auth.models.User.has_module_perms\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">has_module_perms()</span></code></a> 에서 <a class=\"reference internal\" href=\"/ko/4.1/ref/exceptions/#django.core.exceptions.PermissionDenied\" title=\"django.core.exceptions.PermissionDenied\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PermissionDenied</span></code></a> 예외가 일어나면 , 인증은 즉시 실패하고 Django 는 뒤따르는 백엔드를 확인하지 않을 것입니다.</p>\n<p>백엔드는 다음과 같이 매직 관리자에 대한 권한을 구현할 수 있다.:</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.backends</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">BaseBackend</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MagicAdminBackend</span><span class=\"p\">(</span><span class=\"n\">BaseBackend</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">has_perm</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">user_obj</span><span class=\"p\">,</span> <span class=\"n\">perm</span><span class=\"p\">,</span> <span class=\"n\">obj</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"k\">return</span> <span class=\"n\">user_obj</span><span class=\"o\">.</span><span class=\"n\">username</span> <span class=\"o\">==</span> <span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">ADMIN_LOGIN</span>\n</code></pre></div>\n<p>위의 예제에서 접근을 허가받은 사용자들에게 완전한 권한을 부여합니다. 연관된 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.models.User</span></code></a> 함수에서 주어진 같은 인자이지만 백엔드 인증 함수는 모두 인자로 익명 사용자일 수도 있는 사용자 객체를 받는다는 것을 명심하세요.</p>\n<p>전체 인증 구현은 <a class=\"extlink-source reference external\" href=\"https://github.com/django/django/blob/stable/4.1.x/django/contrib/auth/backends.py`의 ``ModelBackend`\">django/contrib/auth/backends.py`의 ``ModelBackend`</a> 클래스에서 찾을 수 있으며,  디폴트 백엔드이고 대부분의 경우 <code class=\"docutils literal notranslate\"><span class=\"pre\">auth_permission</span></code>  테이블을 쿼리한다.</p>\n<section id=\"authorization-for-anonymous-users\">\n<span id=\"anonymous-auth\"></span><h4>익명 사용자를 위한 인증<a class=\"heading-anchor\" href=\"#authorization-for-anonymous-users\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>익명 사용자는 인증되지 않은 사용자입니다. 즉 그들은 참인 인증 상세를 제공하지 않습니다. 하지만 그것이 꼭 어떤 것을 하는데 권한을 부여받지 않음을 의미하는 것은 아닙니다. 대부분의 기초 수준에서 많은 웹사이트들이 익명 사용자에게 대부분의 사이트를 둘러볼 것을 허가하고 익명 댓글을 포스팅하는 것을 허가합니다.</p>\n<p>Django’s permission framework does not have a place to store permissions for\nanonymous users. However, the user object passed to an authentication backend\nmay be an <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.AnonymousUser\" title=\"django.contrib.auth.models.AnonymousUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.models.AnonymousUser</span></code></a> object, allowing\nthe backend to specify custom authorization behavior for anonymous users. This\nis especially useful for the authors of reusable apps, who can delegate all\nquestions of authorization to the auth backend, rather than needing settings,\nfor example, to control anonymous access.</p>\n</section>\n<section id=\"authorization-for-inactive-users\">\n<span id=\"inactive-auth\"></span><h4>비활성 사용자를 위한 인증<a class=\"heading-anchor\" href=\"#authorization-for-inactive-users\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>비활성 사용자는 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_active\" title=\"django.contrib.auth.models.User.is_active\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_active</span></code></a> 필드가 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> 로 설정되어 있는 사람입니다. <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.backends.ModelBackend\" title=\"django.contrib.auth.backends.ModelBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code></a> 와 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.backends.RemoteUserBackend\" title=\"django.contrib.auth.backends.RemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RemoteUserBackend</span></code></a> 인증 백엔드는 이 사용자들이 인증되는 것을 막습니다. 만약 맞춤 사용자 모델이 <a class=\"reference internal\" href=\"#django.contrib.auth.models.CustomUser.is_active\" title=\"django.contrib.auth.models.CustomUser.is_active\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_active</span></code></a> 필드를 가지고 있지 않다면, 모든 사용자는 인증이 허락될 것 입니다.</p>\n<p>만약 비활성 사용자가 인증하는 것을 허락하고자 하면, 독자는 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.backends.AllowAllUsersModelBackend\" title=\"django.contrib.auth.backends.AllowAllUsersModelBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AllowAllUsersModelBackend</span></code></a> 나 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.backends.AllowAllUsersRemoteUserBackend\" title=\"django.contrib.auth.backends.AllowAllUsersRemoteUserBackend\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AllowAllUsersRemoteUserBackend</span></code></a> 를 사용할 수 있습니다.</p>\n<p>권한 시스템에서 익명 사용자를 위한 지원은 비활성 인증된 사용자가 할 수는 없지만 익명 사용자는 가능한 시나리오를 포함합니다.</p>\n<p>여러분의 백엔드 권한 메소드에서 사용자의 <code class=\"docutils literal notranslate\"><span class=\"pre\">is_active</span></code> 속성을 테스트 하는 것을 잊지 마세요.</p>\n</section>\n<section id=\"handling-object-permissions\">\n<h4>객체 권한 다루기<a class=\"heading-anchor\" href=\"#handling-object-permissions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Django의 권한 프레임워크는 비록 코어에 구현은 되어 있지 않지만 객체 권한에 기반를 두고 있습니다. 즉 객체 권한을 확인하면 항상 <code class=\"docutils literal notranslate\"><span class=\"pre\">False``나</span> <span class=\"pre\">빈</span> <span class=\"pre\">리스트를</span> <span class=\"pre\">반환할</span> <span class=\"pre\">것입니다</span> <span class=\"pre\">(확인이</span> <span class=\"pre\">수행됨에</span> <span class=\"pre\">따라서).</span> <span class=\"pre\">인증</span> <span class=\"pre\">백엔드는</span> <span class=\"pre\">인증</span> <span class=\"pre\">메소드와</span> <span class=\"pre\">관련된</span> <span class=\"pre\">각</span> <span class=\"pre\">객체에</span> <span class=\"pre\">``obj</span></code> 와 <code class=\"docutils literal notranslate\"><span class=\"pre\">user_obj</span></code> 키워드 파라미터를 받고 적합한 객체 수준 권한을 반환할 수 있습니다.</p>\n</section>\n</section>\n</section>\n<section id=\"custom-permissions\">\n<span id=\"id1\"></span><h2>맞춤 권한<a class=\"heading-anchor\" href=\"#custom-permissions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>주어진 모델 객체를 위한 맞춤 권한을 생성하기 위해서 <code class=\"docutils literal notranslate\"><span class=\"pre\">permissions</span></code> <a class=\"reference internal\" href=\"/ko/4.1/topics/db/models/#meta-options\"><span class=\"std std-ref\">모델  메타 속성</span></a> 을 사용합니다.</p>\n<p>이 예제 <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</span></code> 모델은 두 가지 맞춤 권한, 즉 애플리케이션 사용자가 <code class=\"docutils literal notranslate\"><span class=\"pre\">Task</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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Task</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=\"o\">...</span>\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">permissions</span> <span class=\"o\">=</span> <span class=\"p\">[</span>\n            <span class=\"p\">(</span><span class=\"s2\">&quot;change_task_status&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Can change the status of tasks&quot;</span><span class=\"p\">),</span>\n            <span class=\"p\">(</span><span class=\"s2\">&quot;close_task&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;Can remove a task by setting its status as closed&quot;</span><span class=\"p\">),</span>\n        <span class=\"p\">]</span>\n</code></pre></div>\n<p>이것이 하는 유일한 일은 <code class=\"xref std std-djadmin docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span> <span class=\"pre\">&lt;migrate&gt;`(:data:`~django.db.models.signals.post_migrate</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=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">has_perm</span><span class=\"p\">(</span><span class=\"s1\">&#39;app.close_task&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"extending-the-existing-user-model\">\n<span id=\"extending-user\"></span><h2>기존 <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> 모델 확장하기<a class=\"heading-anchor\" href=\"#extending-the-existing-user-model\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>독자 스스로의 모델을 대체하지 않고 기본 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 모델을 확장시키는 데 두 가지 방법이 있습니다. 만약 여러분이 하고자 하는 변경이 순수히 행동적이고 데이터베이스에 저장되는 것의 변화는 필요하지 않다면 독자는 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 에 기반한 <a class=\"reference internal\" href=\"/ko/4.1/topics/db/models/#proxy-models\"><span class=\"std std-ref\">프록시 모델</span></a> 을 생성할 수 있습니다. 이것은 기본 정렬, 맞춤 매니저 또는 맞춤 모델 메소드를 포함해서 프록시 모델에서 제안된 기능을 허용합니다.</p>\n<p>만약 독자가 <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> 에 관련된 정보를 저장하길 원한다면 <a class=\"reference internal\" href=\"/ko/4.1/ref/models/fields/#django.db.models.OneToOneField\" title=\"django.db.models.OneToOneField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">OneToOneField</span></code></a> 를 추가적인 정보를 위한 필드를 포함하는 모델로 사용할 수 있습니다. 이 일대일 모델은 사이트 사용자에 대한 비인증 관련 정보를 저장할 수도 있기 때문에 종종 프로필 모델로 불립니다. 예를 들어 독자는 Employee 모델을 생성할 수도 있습니다:</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">User</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Employee</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\">user</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">OneToOneField</span><span class=\"p\">(</span><span class=\"n\">User</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\">department</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\">100</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>User와 Employee 모델을 가지는 Employee Fred Smith가 있다고 가정하면 여러분은 Django의 표준 연관 모델 관례에 따라 관련된 정보에 접근할 수 있습니다:</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=\"n\">u</span> <span class=\"o\">=</span> <span class=\"n\">User</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\">username</span><span class=\"o\">=</span><span class=\"s1\">&#39;fsmith&#39;</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">freds_department</span> <span class=\"o\">=</span> <span class=\"n\">u</span><span class=\"o\">.</span><span class=\"n\">employee</span><span class=\"o\">.</span><span class=\"n\">department</span>\n</code></pre></div>\n<p>프로필 모델의 필드를 관리자 사용자 페이지에 추가하기 위해선 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin\" title=\"django.contrib.admin.InlineModelAdmin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">InlineModelAdmin</span></code></a> 를 독자 앱의 <code class=\"docutils literal notranslate\"><span class=\"pre\">admin.py``에</span> <span class=\"pre\">정의합니다.</span> <span class=\"pre\">(예로</span> <span class=\"pre\">우리는</span> <span class=\"pre\">:class:`~django.contrib.admin.StackedInline`를</span> <span class=\"pre\">사용할</span> <span class=\"pre\">것입니다.)</span> <span class=\"pre\">그리고</span> <span class=\"pre\">:class:`~django.contrib.auth.models.User`</span> <span class=\"pre\">클래스로</span> <span class=\"pre\">등록된</span> <span class=\"pre\">``UserAdmin</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=\"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<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.admin</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">UserAdmin</span> <span class=\"k\">as</span> <span class=\"n\">BaseUserAdmin</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">User</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">my_user_profile_app.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Employee</span>\n\n<span class=\"c1\"># Define an inline admin descriptor for Employee model</span>\n<span class=\"c1\"># which acts a bit like a singleton</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">EmployeeInline</span><span class=\"p\">(</span><span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">StackedInline</span><span class=\"p\">):</span>\n    <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">Employee</span>\n    <span class=\"n\">can_delete</span> <span class=\"o\">=</span> <span class=\"kc\">False</span>\n    <span class=\"n\">verbose_name_plural</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;employee&#39;</span>\n\n<span class=\"c1\"># Define a new User admin</span>\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">UserAdmin</span><span class=\"p\">(</span><span class=\"n\">BaseUserAdmin</span><span class=\"p\">):</span>\n    <span class=\"n\">inlines</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"n\">EmployeeInline</span><span class=\"p\">,)</span>\n\n<span class=\"c1\"># Re-register UserAdmin</span>\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">unregister</span><span class=\"p\">(</span><span class=\"n\">User</span><span class=\"p\">)</span>\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\">User</span><span class=\"p\">,</span> <span class=\"n\">UserAdmin</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>이 프로필 모델은 어떤 방식으로든 특별하지 않습니다. - 이것은 단지 사용자 모델과 일대일 링크를 가지기 위한 Django 모델입니다. 이와 같이 프로필 모델은 사용자가 생성될 때 스스로 생성되지 않고  :attr:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>django.db.models.signals.post_save`이 생성 또는 관련 모델을 업데이트하기 위해 적절히 사용될 될 수 있습니다.</p>\n<p>관련 모델을 사용하면 추가적인 질의나 관련 데이터를 검색할 수 있습니다. 독자의 필요에 따라 관련 필드를 포함하는 맞춤 사용자 모델은 더 나은 선택이 될 수 있습니다. 하지만 프로젝트 앱에서 기본 사용자 모델의 관계를 유지시키면 추가 데이터베이스 로드를 정당화 할 수 있습니다.</p>\n</section>\n<section id=\"substituting-a-custom-user-model\">\n<span id=\"auth-custom-user\"></span><h2>맞춤 <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> 모델 대체하기<a class=\"heading-anchor\" href=\"#substituting-a-custom-user-model\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>몇몇 종류의 프로젝트는 Django의 빌트인 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 모델이 항상 적절하진 않은 인증 요구사항을 가지고 있을 수 있습니다. 예를 들어 어떤 사이트에서는 사용자 이름 대신 이메일 주소를 인증 토큰을 사용하는 것이 더 적합할 수 있습니다.</p>\n<p>Django는 독자가 맞춤 모델을 참조하는 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></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=\"n\">AUTH_USER_MODEL</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;myapp.MyUser&#39;</span>\n</code></pre></div>\n<p>이 점 쌍은 django 어플리케이션의(:setting:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>INSTALLED_APPS 에 있어야한다) :attr:<a href=\"#id3\"><span class=\"problematic\" id=\"id4\">`</span></a>~django.apps.AppConfig.label`와 사용자 모델로 사용하려고 하는 django 모델의 이름이다.</p>\n<section id=\"using-a-custom-user-model-when-starting-a-project\">\n<h3>프로젝트를 시작할 때 맞춤 사용자 모델 사용하기<a class=\"heading-anchor\" href=\"#using-a-custom-user-model-when-starting-a-project\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>만약 독자가 새로운 프로젝트를 시작한다면 기본 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">AbstractUser</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">User</span><span class=\"p\">(</span><span class=\"n\">AbstractUser</span><span class=\"p\">):</span>\n    <span class=\"k\">pass</span>\n</code></pre></div>\n<p>모델에 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></a> 을 가리키는 것을 잊지마세요. 이 작업은 마이그레이션을 생성하거나 <code class=\"docutils literal notranslate\"><span class=\"pre\">manage.py</span> <span class=\"pre\">migrate</span></code> 를 처음으로 실행시키기 전에 합니다.</p>\n<p>또한 앱의 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>admin.py``에 모델을 등록합니다:</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=\"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<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.admin</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">UserAdmin</span>\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\">User</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\">User</span><span class=\"p\">,</span> <span class=\"n\">UserAdmin</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n<section id=\"changing-to-a-custom-user-model-mid-project\">\n<h3>프로젝트 중간에 맞춤 사용자 모델 변경하기<a class=\"heading-anchor\" href=\"#changing-to-a-custom-user-model-mid-project\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>데이터베이스 테이블을 생성한 뒤 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></a> 를 변경하는 것은 예를 들면 변경이 외래 키와 다대다 관계에 영향을 주기 때문에 상당히 더 어렵습니다.</p>\n<p>이 변경은 자동으로는 불가능하고 수동으로 독자의 스키마를 수정하고 데이터를 이전 사용자 테이블에서 옮기고 몇 가지 마이그레이션을 어떻게해서든 수동으로 적용시킬 필요성이 있습니다. 단계들의 개요는 <a class=\"extlink-ticket reference external\" href=\"https://code.djangoproject.com/ticket/25313\">#25313</a> 에서 보실 수 있습니다.</p>\n<p>교환가능한 모델을 위한 Django의 동적 의존성 기능의 한계로 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></a> 로부터 참조된 모델은 앱의 첫 번째 마이그레이션에서 생성되어야만 합니다. (보통 <code class=\"docutils literal notranslate\"><span class=\"pre\">0001_initial</span></code> 로 불리는) 그렇지 않으면 독자는 의존성 이슈를 가지게 될 것입니다.</p>\n<p>또한, Django는 동적 의존성으로 인한 의존성 루프를 자동으로 해소해주지 않으므로 마이그레이션을 수행할 때 <code class=\"docutils literal notranslate\"><span class=\"pre\">CircularDependencyError</span></code>가 발생할 수 있습니다. 이 오류가 발생하면 사용자 모델에 의존하는 모델들을 두 번째 마이그레이션으로 옮김으로써 루프를 해소해야 합니다(일반적으로 어떻게 이뤄지는지 보고 싶다면 서로에 대해 <code class=\"docutils literal notranslate\"><span class=\"pre\">ForeignKey</span></code>를 갖는 두 개의 일반적인 모델을 만들고 <code class=\"docutils literal notranslate\"><span class=\"pre\">makemigrations</span></code>가 순환 의존성을 어떻게 다루는지 볼 수 있습니다).</p>\n</section>\n<section id=\"reusable-apps-and-auth-user-model\">\n<h3>재사용 가능 앱과 <code class=\"docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code><a class=\"heading-anchor\" href=\"#reusable-apps-and-auth-user-model\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>재사용 가능한 앱은 맞춤 사용자 모델을 구현하면 안 됩니다. 하나의 프로젝트는 많은 앱을 사용할 수 있고 맞춤 사용자 모델이 구현된 재사용 가능한 앱은 두 개가 동시에 사용될 수 없습니다. 만약 독자가 앱마다 사용자 정보를 저장할 필요가 있다면 아래에서 처럼  <a class=\"reference internal\" href=\"/ko/4.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> 또는  <a class=\"reference internal\" href=\"/ko/4.1/ref/models/fields/#django.db.models.OneToOneField\" title=\"django.db.models.OneToOneField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">OneToOneField</span></code></a> 를 <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.AUTH_USER_MODEL</span></code> 로 사용하세요.</p>\n</section>\n<section id=\"referencing-the-user-model\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> 모델 참조하기<a class=\"heading-anchor\" href=\"#referencing-the-user-model\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>만약 독자가 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> 를 직접 참조한다면 (예를 들어 외래 키로 참조하듯이), <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></a> 설정이 다른 사용자 모델로 변경된 프로젝트에서는 코드가 동작하지 않을 것입니다.</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.get_user_model\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_user_model</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.get_user_model\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>Instead of referring to <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> directly,\nyou should reference the user model using\n<code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.get_user_model()</span></code>. This method will return the\ncurrently active user model – the custom user model if one is specified, or\n<a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> otherwise.</p>\n<p>독자가 외래 키나 다대다 관계를 사용자 모델에 정의할 때 독자는 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.conf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">settings</span>\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\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Article</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\">author</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">ForeignKey</span><span class=\"p\">(</span>\n        <span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">AUTH_USER_MODEL</span><span class=\"p\">,</span>\n        <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=\"p\">)</span>\n</code></pre></div>\n<p>사용자 모델에서 받은 시그널을 연결할 때 독자는 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.conf</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">settings</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">post_save</span>\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">post_save_receiver</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"n\">instance</span><span class=\"p\">,</span> <span class=\"n\">created</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"k\">pass</span>\n\n<span class=\"n\">post_save</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">post_save_receiver</span><span class=\"p\">,</span> <span class=\"n\">sender</span><span class=\"o\">=</span><span class=\"n\">settings</span><span class=\"o\">.</span><span class=\"n\">AUTH_USER_MODEL</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>일반적으로 임포트 시간에 실행되는 코드의 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></a> 설정으로 사용자 모델을 참조하는 것이 가장 쉬운 방법입니다. 하지만 Django가 모델을 임포팅하는 동안에 <code class=\"docutils literal notranslate\"><span class=\"pre\">get_user_model()``를</span> <span class=\"pre\">호출하는</span> <span class=\"pre\">것도</span> <span class=\"pre\">가능한</span> <span class=\"pre\">벙법이므로</span> <span class=\"pre\">독자는</span> <span class=\"pre\">이런</span> <span class=\"pre\">식으로</span> <span class=\"pre\">``models.ForeignKey(get_user_model(),</span> <span class=\"pre\">...)</span></code> 사용할 수 있습니다.</p>\n<p>만약 독자의 앱이 여러 개의 사용자 모델로 테스트 되고, 예를 들어 <code class=\"docutils literal notranslate\"><span class=\"pre\">&#64;override_settings(AUTH_USER_MODEL=...)</span></code> 를 사용해서, 독자가 모듈 레벨의 변수에서``get_user_model()``의 결과를 캐시한다면 독자는 캐시를 지우기 위해 <a class=\"reference internal\" href=\"/ko/4.1/ref/signals/#django.test.signals.setting_changed\" title=\"django.test.signals.setting_changed\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">setting_changed</span></code></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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.apps</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">apps</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">get_user_model</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">setting_changed</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.dispatch</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">receiver</span>\n\n<span class=\"nd\">@receiver</span><span class=\"p\">(</span><span class=\"n\">setting_changed</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">user_model_swapped</span><span class=\"p\">(</span><span class=\"o\">*</span><span class=\"p\">,</span> <span class=\"n\">setting</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"k\">if</span> <span class=\"n\">setting</span> <span class=\"o\">==</span> <span class=\"s1\">&#39;AUTH_USER_MODEL&#39;</span><span class=\"p\">:</span>\n        <span class=\"n\">apps</span><span class=\"o\">.</span><span class=\"n\">clear_cache</span><span class=\"p\">()</span>\n        <span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">myapp</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">some_module</span>\n        <span class=\"n\">some_module</span><span class=\"o\">.</span><span class=\"n\">UserModel</span> <span class=\"o\">=</span> <span class=\"n\">get_user_model</span><span class=\"p\">()</span>\n</code></pre></div>\n</dd></dl>\n\n</section>\n<section id=\"specifying-a-custom-user-model\">\n<span id=\"specifying-custom-user-model\"></span><h3>맞춤 사용자 모델 명세하기<a class=\"heading-anchor\" href=\"#specifying-a-custom-user-model\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>커스텀 유저 모델로 프로젝트를 시작할 때 당신의 프로젝트에 알맞는 선택인지 아닌지 고려하는 것을 멈추세요.</p>\n<p>하나의 모델에서 모든 사용자 관련된 정보를 유지하는 것은 관련된 모델을 조회하기 위한 추가적인 또는 더욱 복잡한 데이터베이스 쿼리를 필요로 하지 않는다.  반면에, 맞춤 사용자 모델과 관련이 있는 하나의 모델에서 특정한 어플리케이션 사용자 정보 더욱 적합할 수 있다.  각 어플리케이션이 다른 어플리케이션에 의해 충돌하거나 깨질 수 있는 가정없이 자체 사용자 데이터 요구사항을 명시하도록 한다. 인증에 중점을 두고, 사용자 모델을 가능한 간단하게 하고, django가 기대하는 맞춤 사용자 모델과 맞도록 최소 요구사항을 따를 것을 의미한다.</p>\n<p>만약 독자가 기본 인증 백엔드를 사용한다면 모델은 인증 목적을 위해 사용될 수 있는 하나의 고유한 필드를 가져야합니다. 이 필드는 사용자 이름, 이메일 주소, 또는 다른 고유한 속성도 가능합니다. 고유하지 않은 사용자 이름 필드는 독자가 이것을 지원할 수 있는 맞춤 인증 백엔드를 사용한다면 허용됩니다.</p>\n<p>올바른 맞춤 사용자 모델을 만드는 가장 쉬운 방법은 <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a> 를 상속하는 것입니다. <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a> 은 해쉬 비밀번호와 토큰화된 비밀번호 재설정을 포함해서 사용자 모델의 핵심적인 구현을 제공합니다. 독자는 몇 가지 키 구현을 상세하게 제공해야 합니다.</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUser\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">models.</span></span><span class=\"sig-name descname\"><span class=\"pre\">CustomUser</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUser\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUser.USERNAME_FIELD\">\n<span class=\"sig-name descname\"><span class=\"pre\">USERNAME_FIELD</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUser.USERNAME_FIELD\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>A string describing the name of the field on the user model that is\nused as the unique identifier. This will usually be a username of some\nkind, but it can also be an email address, or any other unique\nidentifier. The field <em>must</em> be unique (e.g. have <code class=\"docutils literal notranslate\"><span class=\"pre\">unique=True</span></code> set\nin its definition), unless you use a custom authentication backend that\ncan support non-unique usernames.</p>\n<p>다음 예에서 <code class=\"docutils literal notranslate\"><span class=\"pre\">identifier</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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyUser</span><span class=\"p\">(</span><span class=\"n\">AbstractBaseUser</span><span class=\"p\">):</span>\n    <span class=\"n\">identifier</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\">40</span><span class=\"p\">,</span> <span class=\"n\">unique</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n    <span class=\"o\">...</span>\n    <span class=\"n\">USERNAME_FIELD</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;identifier&#39;</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUser.EMAIL_FIELD\">\n<span class=\"sig-name descname\"><span class=\"pre\">EMAIL_FIELD</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUser.EMAIL_FIELD\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>“User” model 에서 이메일 필드를 이름을 묘사하는 스트링. 이 값은 “models.AbstractBaseUser.get_email_field_name” 라는 메서드로 얻을수 있습니다.</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUser.REQUIRED_FIELDS\">\n<span class=\"sig-name descname\"><span class=\"pre\">REQUIRED_FIELDS</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUser.REQUIRED_FIELDS\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>djadmin ( = django-admin ) 의 createsuperuser 명령으로 user 를 만들때 입력대기 (prompted) 되는 필드 이름들 목록.\nuser 는 이들 필드들이 입력 되도록 합니다. 그것은 다음과 같은 필드들을 포함 시킵니다. 속성이 django.db.models.Field.blank 는 “False” 혹은 “undefined” 로 , 그리고 아마도 다른 필드들은 user 가 생성될때 상호작동 방식으로 입력 되도록 포함 될 수도 있습니다.</p>\n<p>예를 들어, 여기에 값이 제공되어야 하는 두개의 필드 - 생년월일, 키 - 를 갖는 User Model 에 대한 부분적인 정의(definition) 를 하였습니다.</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=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyUser</span><span class=\"p\">(</span><span class=\"n\">AbstractBaseUser</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n    <span class=\"n\">date_of_birth</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">DateField</span><span class=\"p\">()</span>\n    <span class=\"n\">height</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">FloatField</span><span class=\"p\">()</span>\n    <span class=\"o\">...</span>\n    <span class=\"n\">REQUIRED_FIELDS</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;date_of_birth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;height&#39;</span><span class=\"p\">]</span>\n</code></pre></div>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">참고</p>\n<p>요구되는 필드들(Required Fields) 는 여러분의 user model 에서 요구되는 필드의 모두 포함합니다만 “USERNAME_FIELD” 혹은 “Password” 필드는 제외합니다. 이들은 항상 입력이 되도록 하기 때문입니다.</p>\n</aside>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUser.is_active\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_active</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUser.is_active\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>사용자가 “active”로 간주되는지를 나타내는 불리언 속성이다. 이 속성은 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>AbstractBaseUser``에 대한 속성으로 디폴트로 “True”가 제공된다. 구현 방법은 선택된 인증 백엔드의 세부 세항에 따라 달라질 것이다.  세부 사항은 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_active\" title=\"django.contrib.auth.models.User.is_active\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_active</span> <span class=\"pre\">attribute</span> <span class=\"pre\">on</span> <span class=\"pre\">the</span> <span class=\"pre\">built-in</span> <span class=\"pre\">user</span> <span class=\"pre\">model</span></code></a> 문서를 참조하라.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUser.get_full_name\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_full_name</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUser.get_full_name\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>선택 가능한. 사용자의 풀네임과 같은 더 긴 공식 식별자이다. 구현된다면, :mod:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>django.contrib.admin`의 객체의 히스토리에 사용자명과 나란히 나타난다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUser.get_short_name\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_short_name</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUser.get_short_name\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>선택 가능한. 사용자의 성과 같은 짧은 비공식 식별자이다. 구현된다면, 사용자명을 :mod:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>django.contrib.admin`의 헤더에 있는 사용자에게 보내는 인사말로 치환하다.</p>\n</dd></dl>\n\n<aside class=\"admonition-importing-abstractbaseuser admonition\">\n<p class=\"admonition-title\">“AbstractBaseUser`”를 임포트</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser``과</span> <span class=\"pre\">``BaseUserManager``는</span> <span class=\"pre\">``django.contrib.auth.base_user</span></code> 에서 가져올 수 있어서 <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-INSTALLED_APPS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">INSTALLED_APPS</span></code></a>.에 있는 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>django.contrib.auth``를 포함하지 않고 임포트될 수 있다.</p>\n</aside>\n</dd></dl>\n\n<p>다음 속성과 메소드는 <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a>:의 모든 서브클래스에서 이용할 수 있다.</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">models.</span></span><span class=\"sig-name descname\"><span class=\"pre\">AbstractBaseUser</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.get_username\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_username</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.get_username\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>“USERNAME_FIELD”에 의해 지명된 필드의 값을 반환합니다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.clean\">\n<span class=\"sig-name descname\"><span class=\"pre\">clean</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.clean\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>:meth:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>normalize_username`을 호출함으로써 사용자명을 정규화한다. 이 메소드를 오버라이드하면,  정규화를 유지하기 위해 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>super()``을 호출해야 한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.get_email_field_name\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">classmethod</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">get_email_field_name</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.get_email_field_name\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><a class=\"reference internal\" href=\"#django.contrib.auth.models.CustomUser.EMAIL_FIELD\" title=\"django.contrib.auth.models.CustomUser.EMAIL_FIELD\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">EMAIL_FIELD</span></code></a> 속성으로 명시된 이메일 필드의 이름을 리턴한다. <code class=\"docutils literal notranslate\"><span class=\"pre\">'email'</span></code> if <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>EMAIL_FIELD``의 디폴트값은 명시되지 않았다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.normalize_username\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">classmethod</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">normalize_username</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">username</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.normalize_username\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>다른 유니코드의 코드 포인트를 가진 시각적으로 동일한 문자가 동일한 것으로 간주되도록 NFKC 유니코드 정규화를 사용자명에 적용하다.</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.is_authenticated\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_authenticated</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.is_authenticated\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>항상  <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True``(항상 ``False``인  `AnonymousUser.is_authenticated``와 반대이다) 인 읽기 전용 속성. 이는 사용자가 인증되었는지를 알려주는 방법이다. 모든 권한을 의미하는 것은 아니고 사용자가 활성 상태인지 유효한 세션이 있는지를 확인하는 것이 아니다.  그럼에도 불구하고, :class:`~django.contrib.auth.middleware.AuthenticationMiddleware (현재 로그인되어 있는 사용자를 나타낸다) 에 의해 덧붙여졌는지 알아내기 위해 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>request.user``의 속성을 확인할 것이고, 이 속성은 모든 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> instance에 대해 <a href=\"#id5\"><span class=\"problematic\" id=\"id6\">``</span></a>True``임을 알아야 한다.</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.is_anonymous\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_anonymous</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.is_anonymous\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>항상 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>False``인 읽기 전용 속성이다. <code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AnonymousUser</span></code> 객체를 차별화하는 방법이다. 일반적으로,  이 속성에 대해서는 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_authenticated\" title=\"django.contrib.auth.models.User.is_authenticated\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_authenticated</span></code></a> 이용하는 것이 좋다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.set_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">raw_password</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.set_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>패스워드 해싱을 처리하여, 주어진 원시 문자열로 사용자의 패스워드를 설정한다. <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a> 객체를 저장하지 않는다.</p>\n<p>raw_password가 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>None``이면, 마치 <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser.set_unusable_password\" title=\"django.contrib.auth.models.AbstractBaseUser.set_unusable_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_unusable_password()</span></code></a> 이 사용된 것처럼, 패스워드는 사용할 수 없는 패스워드로 설정한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.check_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">check_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">raw_password</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.check_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>주어진 원시 문자열이 사용자의 올바른 패스워드라면 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True``를 리턴한다. (비교를 할 때 패스워드 해싱을 처리한다.)</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.set_unusable_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">set_unusable_password</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.set_unusable_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>사용자가 패스워드를 설정하지 않은 것으로 표시한다. 빈 문자열을 패스워드로 가지는 것과 다르다. <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser.check_password\" title=\"django.contrib.auth.models.AbstractBaseUser.check_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">check_password()</span></code></a> 의 사용자에 대해 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True``를 절대 리턴하지 않을 것이다. <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a> 객체를 저장하지 않는다.</p>\n<p>애플리케이션에 대한 인증이 LDAP 디렉토리와 같은 기존 외부 소스에 대해 수행되는 경우 필요할 수 있다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.has_usable_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">has_usable_password</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.has_usable_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>이 사용자에 대해 <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser.set_unusable_password\" title=\"django.contrib.auth.models.AbstractBaseUser.set_unusable_password\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">set_unusable_password()</span></code></a> 가 호출되면, <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>False``를 리턴한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_session_auth_hash</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.get_session_auth_hash\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>패스워드 필드의 HMAC를 리턴한다. :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>session-invalidation-on-password-change`에 사용된다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractBaseUser.get_session_auth_fallback_hash\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_session_auth_fallback_hash</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractBaseUser.get_session_auth_fallback_hash\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><aside class=\"version-note version-added\" data-version=\"4.1.8\">\n<p class=\"version-note-title\">New in Django 4.1.8</p></aside>\n<p>Yields the HMAC of the password field using\n<a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-SECRET_KEY_FALLBACKS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">SECRET_KEY_FALLBACKS</span></code></a>. Used by <code class=\"docutils literal notranslate\"><span class=\"pre\">get_user()</span></code>.</p>\n</dd></dl>\n\n</dd></dl>\n\n<p><a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractUser\" title=\"django.contrib.auth.models.AbstractUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractUser</span></code></a> 하위 클래스 <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a>:</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractUser\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">models.</span></span><span class=\"sig-name descname\"><span class=\"pre\">AbstractUser</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractUser\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.AbstractUser.clean\">\n<span class=\"sig-name descname\"><span class=\"pre\">clean</span></span><span class=\"sig-paren\">(</span><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.AbstractUser.clean\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>:meth:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>.BaseUserManager.normalize_email`을 호출하여 이메일을 정규화하다. 이 메소드를 오버라이드한다면, 정규화를 유지하기 위해 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>super()``를 호출해야 한다.</p>\n</dd></dl>\n\n</dd></dl>\n\n</section>\n<section id=\"writing-a-manager-for-a-custom-user-model\">\n<h3>사용자 맞춤 모델을 위한 관리자 작성<a class=\"heading-anchor\" href=\"#writing-a-manager-for-a-custom-user-model\"><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\">username</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">email</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">is_staff</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">is_active</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">is_superuser</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">last_login</span></code> 및 <code class=\"docutils literal notranslate\"><span class=\"pre\">date_joined</span></code> 필드를 django의 디폴드 사용자와 동일하게 정의한다면, django의 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.UserManager\" title=\"django.contrib.auth.models.UserManager\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">UserManager</span></code></a> 를 설치할 수 있다. 그러나, 사용자 모델이 다른 필드를 정의하면, 두 개의 추가적인 메소드를 제공하는 :class:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>~django.contrib.auth.models.BaseUserManager`를 상속하는 맞춤 관리자를 정의해야한다.</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUserManager\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">models.</span></span><span class=\"sig-name descname\"><span class=\"pre\">CustomUserManager</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUserManager\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUserManager.create_user\">\n<span class=\"sig-name descname\"><span class=\"pre\">create_user</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">username_field</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">other_fields</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUserManager.create_user\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>create_user()``의 프로토 타입은 사용자명 필드와 모든 필수 필드를 인자로 허용해야 한다. 예를 들어, 사용자 모델이 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>email``을 사용자명 필드로 이용한다면,  <a href=\"#id5\"><span class=\"problematic\" id=\"id6\">``</span></a>date_of_birth``를 필수 필드로 가지고, <a href=\"#id7\"><span class=\"problematic\" id=\"id8\">``</span></a>create_user``는 정의되어야 한다.</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=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">create_user</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">email</span><span class=\"p\">,</span> <span class=\"n\">date_of_birth</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n    <span class=\"c1\"># create user here</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.CustomUserManager.create_superuser\">\n<span class=\"sig-name descname\"><span class=\"pre\">create_superuser</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">username_field</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">password</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">other_fields</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.CustomUserManager.create_superuser\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>create_superuser()``의 프로토 타입은 사용자명 필드와 모든 필수 필드를 인자로 허용해야 한다. 예를 들어, 사용자 모델이 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>email``을 사용자명 필드로 이용한다면,  <a href=\"#id5\"><span class=\"problematic\" id=\"id6\">``</span></a>date_of_birth``를 필수 필드로 가지고, <a href=\"#id7\"><span class=\"problematic\" id=\"id8\">``</span></a>create_superuser``는 정의되어야 한다.</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=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">create_superuser</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">email</span><span class=\"p\">,</span> <span class=\"n\">date_of_birth</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n    <span class=\"c1\"># create superuser here</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n</dd></dl>\n\n</dd></dl>\n\n<p>For a <a class=\"reference internal\" href=\"/ko/4.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> in <a class=\"reference internal\" href=\"#django.contrib.auth.models.CustomUser.USERNAME_FIELD\" title=\"django.contrib.auth.models.CustomUser.USERNAME_FIELD\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">USERNAME_FIELD</span></code></a> or\n<a class=\"reference internal\" href=\"#django.contrib.auth.models.CustomUser.REQUIRED_FIELDS\" title=\"django.contrib.auth.models.CustomUser.REQUIRED_FIELDS\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">REQUIRED_FIELDS</span></code></a>, these methods receive the value of the\n<a class=\"reference internal\" href=\"/ko/4.1/ref/models/fields/#django.db.models.ForeignKey.to_field\" title=\"django.db.models.ForeignKey.to_field\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">to_field</span></code></a> (the <a class=\"reference internal\" href=\"/ko/4.1/ref/models/fields/#django.db.models.Field.primary_key\" title=\"django.db.models.Field.primary_key\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">primary_key</span></code></a>\nby default) of an existing instance.</p>\n<p>:class:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>~django.contrib.auth.models.BaseUserManager`는 다음의 유틸리티 메소드를 제공한다.</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.BaseUserManager\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">models.</span></span><span class=\"sig-name descname\"><span class=\"pre\">BaseUserManager</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.BaseUserManager\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.BaseUserManager.normalize_email\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">classmethod</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">normalize_email</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">email</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.BaseUserManager.normalize_email\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>이메일 주소의 도메인 부분을 소문자 표기를 함으로써 이메일 주소를 정규화한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.BaseUserManager.get_by_natural_key\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_by_natural_key</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">username</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.BaseUserManager.get_by_natural_key\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p><a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>USERNAME_FIELD``에 의해 지명된 필드의 컨텐츠를 이용해 사용자 인스턴스를 반환한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.BaseUserManager.make_random_password\">\n<span class=\"sig-name descname\"><span class=\"pre\">make_random_password</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">length</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">10</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">allowed_chars</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.BaseUserManager.make_random_password\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>허용된 문자로 이루어진 주어진 길이와 문자열로 랜덤 패스워드를 리턴한다. <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>allowed_chars``의 디폴트 값은 다음과 같이 사용자에게 혼돈을 줄 수 있는 문자를 포함하지 않는다.</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">i</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">l</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">I</span></code>, 및 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>1``(소문자 i, 소문자 l, 대문자 i, 및 숫자 1)</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">o</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">O</span></code>, and <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>0``(소문자 o, 대문자 o, 및 숫자 0)</p></li>\n</ul>\n</dd></dl>\n\n</dd></dl>\n\n</section>\n<section id=\"extending-django-s-default-user\">\n<h3>Django의 기본 “User”를 확장<a class=\"heading-anchor\" href=\"#extending-django-s-default-user\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If you’re entirely happy with Django’s <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a>\nmodel, but you want to add some additional profile information, you could\nsubclass <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractUser\" title=\"django.contrib.auth.models.AbstractUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.models.AbstractUser</span></code></a> and add your custom\nprofile fields, although we’d recommend a separate model as described in\n<a class=\"reference internal\" href=\"#specifying-custom-user-model\"><span class=\"std std-ref\">맞춤 사용자 모델 명세하기</span></a>. <code class=\"docutils literal notranslate\"><span class=\"pre\">AbstractUser</span></code> provides the full\nimplementation of the default <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> as an\n<a class=\"reference internal\" href=\"/ko/4.1/topics/db/models/#abstract-base-classes\"><span class=\"std std-ref\">abstract model</span></a>.</p>\n</section>\n<section id=\"custom-users-and-the-built-in-auth-forms\">\n<span id=\"id2\"></span><h3>사용자 맞춤과 내장된 폼<a class=\"heading-anchor\" href=\"#custom-users-and-the-built-in-auth-forms\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>django의 내장된 <span class=\"xref std std-ref\">forms 1</span> 와 :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>forms 2`는 작업중인 사용자 모델에 대한 특정한 가정을 한다.</p>\n<p>다음 폼은 <a class=\"reference internal\" href=\"#django.contrib.auth.models.AbstractBaseUser\" title=\"django.contrib.auth.models.AbstractBaseUser\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser</span></code></a>:의 모든 서브 클래스와 양립할 수 있다.</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/ko/4.1/topics/auth/default/#django.contrib.auth.forms.AuthenticationForm\" title=\"django.contrib.auth.forms.AuthenticationForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AuthenticationForm</span></code></a>: :attr:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>~models.CustomUser.USERNAME_FIELD`에 의해 명시되는 사용자명 필드를 이용한다</p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/4.1/topics/auth/default/#django.contrib.auth.forms.SetPasswordForm\" title=\"django.contrib.auth.forms.SetPasswordForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">SetPasswordForm</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/4.1/topics/auth/default/#django.contrib.auth.forms.PasswordChangeForm\" title=\"django.contrib.auth.forms.PasswordChangeForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PasswordChangeForm</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/4.1/topics/auth/default/#django.contrib.auth.forms.AdminPasswordChangeForm\" title=\"django.contrib.auth.forms.AdminPasswordChangeForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AdminPasswordChangeForm</span></code></a></p></li>\n</ul>\n<p>다음 폼은 사용자 모델에 대한 가정을 하고 해당 가정이 충족되는 경우일 때, 있는 그대로로 사용된다.:</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/ko/4.1/topics/auth/default/#django.contrib.auth.forms.PasswordResetForm\" title=\"django.contrib.auth.forms.PasswordResetForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PasswordResetForm</span></code></a>: 사용자 모델이 비활성화 사용자의 패스워드를 재설정 하는 것을 막기 위해 사용자와  <code class=\"docutils literal notranslate\"><span class=\"pre\">is_active``의</span> <span class=\"pre\">불리언</span> <span class=\"pre\">필드를</span> <span class=\"pre\">식별하고</span> <span class=\"pre\">:meth:`~models.AbstractBaseUser.get_email_field_name`(`email</span></code> 의 디폴트값) 에 의해 리턴된 이름과 사용자의 이메일 주소를 저장하는 필드를 가지는 것으로 가정한다.</p></li>\n</ul>\n<p>마지막으로, 다음의 폼은 :class:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>~django.contrib.auth.models.User`와 연결되어 있으며 사용자 맞춤 모델을 사용하기 위해서는 다시 작성되거나 상속되어야 한다.</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/ko/4.1/topics/auth/default/#django.contrib.auth.forms.UserCreationForm\" title=\"django.contrib.auth.forms.UserCreationForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">UserCreationForm</span></code></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/ko/4.1/topics/auth/default/#django.contrib.auth.forms.UserChangeForm\" title=\"django.contrib.auth.forms.UserChangeForm\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">UserChangeForm</span></code></a></p></li>\n</ul>\n<p>사용자 맞춤 모델이  <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>AbstractUser``의 서브 클래스일 경우, 다음과 같은 방식으로 이 폼을 상속할 수 있다.</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.forms</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">UserCreationForm</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">myapp.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">CustomUser</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CustomUserCreationForm</span><span class=\"p\">(</span><span class=\"n\">UserCreationForm</span><span class=\"p\">):</span>\n\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">(</span><span class=\"n\">UserCreationForm</span><span class=\"o\">.</span><span class=\"n\">Meta</span><span class=\"p\">):</span>\n        <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">CustomUser</span>\n        <span class=\"n\">fields</span> <span class=\"o\">=</span> <span class=\"n\">UserCreationForm</span><span class=\"o\">.</span><span class=\"n\">Meta</span><span class=\"o\">.</span><span class=\"n\">fields</span> <span class=\"o\">+</span> <span class=\"p\">(</span><span class=\"s1\">&#39;custom_field&#39;</span><span class=\"p\">,)</span>\n</code></pre></div>\n</section>\n<section id=\"custom-users-and-django-contrib-admin\">\n<h3>커스텀 User 와 django.contrib.admin 모듈<a class=\"heading-anchor\" href=\"#custom-users-and-django-contrib-admin\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>커스텀 User Model 이 admin 에서도 작동 되길 원하면 추가적인 속성과 매서드를 정의해야 합니다. 이들 매서드들은 Admin 으로 하여금 admin content 에 그 User Model 을Access 할 수 있게 합니다.</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">models.</span></span><span class=\"sig-name descname\"><span class=\"pre\">CustomUser</span></span></dt>\n<dd></dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.is_staff\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_staff</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.is_staff\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>그 user 가 admin site 에 접근 가능하다면 “True” 를 반환합니다</p>\n</dd></dl>\n\n<dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.is_active\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_active</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.is_active\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>그 user 가 지금 현재 “active” 하다면  “True” 를 반환합니다</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\">\n<span class=\"sig-name descname\"><span class=\"pre\">has_perm(perm,</span> <span class=\"pre\">obj=None):</span></span></dt>\n<dd><p>사용자에게 명명된 권한이 있다면 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True``를 리턴한다. 만일  <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>obj``가 제공되면, 권한은 특정한 객체 인스턴스에 대해서 확인되어야한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\">\n<span class=\"sig-name descname\"><span class=\"pre\">has_module_perms(app_label):</span></span></dt>\n<dd><p>사용에게 주어진 어플리케이션에서 모델에 액세스할 권한이 있다면 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True``를 리턴한다.</p>\n</dd></dl>\n\n<p>관리자에게 사용자 맞춤 모델을 등록해야 할 것이다. 사용자 맞춤 모델이 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.models.AbstractUser``을</span> <span class=\"pre\">상속한다면,</span> <span class=\"pre\">django의</span> <span class=\"pre\">기존</span>&#160; <span class=\"pre\">``django.contrib.auth.admin.UserAdmin</span></code>  클래스를 사용할 수 있다. 그러나, 사용자 모델이 <code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AbstractBaseUser`을</span> <span class=\"pre\">상속한다면,</span> <span class=\"pre\">``ModelAdmin`</span></code> 맞춤 클래스를 정의해야 할 것이다. <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>django.contrib.auth.admin.UserAdmin``의 디폴트를 서브클래스화 하는 것을 가능하게 할 것이나, 사용자 맞춤 클래스에 없는 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>django.contrib.auth.models.AbstractUser``의 필드를 참조하는 모든 정의를 오버라이드 해야할 것이다.</p>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">참고</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">django.contrib.auth.admin.UserAdmin``의</span> <span class=\"pre\">서브</span> <span class=\"pre\">클래스인</span> <span class=\"pre\">맞춤</span> <span class=\"pre\">``ModelAdmin</span></code> 을 사용한다면, <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>fieldsets``(사용자를 편집하는 데에 사용되는 필드)와  <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>add_fieldsets``(사용자 생성에 사용되는 필드)에 맞춤 필드를 추가해야한다. 예를 들면, 다음과 같다:</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.admin</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">UserAdmin</span>\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">CustomUserAdmin</span><span class=\"p\">(</span><span class=\"n\">UserAdmin</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n    <span class=\"n\">fieldsets</span> <span class=\"o\">=</span> <span class=\"n\">UserAdmin</span><span class=\"o\">.</span><span class=\"n\">fieldsets</span> <span class=\"o\">+</span> <span class=\"p\">(</span>\n        <span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">(</span><span class=\"s1\">&#39;custom_field&#39;</span><span class=\"p\">,)}),</span>\n    <span class=\"p\">)</span>\n    <span class=\"n\">add_fieldsets</span> <span class=\"o\">=</span> <span class=\"n\">UserAdmin</span><span class=\"o\">.</span><span class=\"n\">add_fieldsets</span> <span class=\"o\">+</span> <span class=\"p\">(</span>\n        <span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">(</span><span class=\"s1\">&#39;custom_field&#39;</span><span class=\"p\">,)}),</span>\n    <span class=\"p\">)</span>\n</code></pre></div>\n<p>자세한 사항은  :ref:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>a full example 1`을 확인하라.</p>\n</aside>\n</section>\n<section id=\"custom-users-and-permissions\">\n<h3>사용자 커스터마이징 과 권한들<a class=\"heading-anchor\" href=\"#custom-users-and-permissions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>django의 권한 프레임워크를 자체 사용자 클래스에 쉽게 포함시키기 위해, django는 :class:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>~django.contrib.auth.models.PermissionsMixin`를 제공한다. 이는 사용자 모델에 클래스 계층 구조를 포함할 수 있는 추상 모델이며, django의 권한 모델을 지원하는 데에 필요한 모든 메소드와 데이터베이스 필드를 제공할 수 있다.</p>\n<p>다음의 메소드와 속성으로 <a class=\"reference internal\" href=\"#django.contrib.auth.models.PermissionsMixin\" title=\"django.contrib.auth.models.PermissionsMixin\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">PermissionsMixin</span></code></a> 을 제공한다.</p>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.PermissionsMixin\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-prename descclassname\"><span class=\"pre\">models.</span></span><span class=\"sig-name descname\"><span class=\"pre\">PermissionsMixin</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.PermissionsMixin\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"py attribute\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.PermissionsMixin.is_superuser\">\n<span class=\"sig-name descname\"><span class=\"pre\">is_superuser</span></span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.PermissionsMixin.is_superuser\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>불리언. 명시적으로 할당하지 않고 모든 권한을 사용자가 갖도록 지정한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.PermissionsMixin.get_user_permissions\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_user_permissions</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">obj</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.PermissionsMixin.get_user_permissions\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>사용자가 직접적으로 갖는 권한 문자열의 모음을 리턴한다</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">obj</span></code> 가 전달이 되면, 특정한 해당 객체에 대한 사용자 권한만 리턴한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.PermissionsMixin.get_group_permissions\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_group_permissions</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">obj</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.PermissionsMixin.get_group_permissions\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>그룹을 통해 사용자가 갖는 권한 문자열의 모음을 리턴한다.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">obj</span></code> 가 전달이 되면, 특정한 해당 객체에 대한 그룹 권한만 리턴한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.PermissionsMixin.get_all_permissions\">\n<span class=\"sig-name descname\"><span class=\"pre\">get_all_permissions</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">obj</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.PermissionsMixin.get_all_permissions\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>그룹과 사용자 권한을 통해 사용자가 갖는 권한 문자열의 모음을 리턴한다.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">obj</span></code> 가 전달이 되면, 특정한 해당 객체에 대한 권한만 리턴한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.PermissionsMixin.has_perm\">\n<span class=\"sig-name descname\"><span class=\"pre\">has_perm</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">perm</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">obj</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.PermissionsMixin.has_perm\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>특정한 권한을 사용자가 갖는다면,``True`` 를 리턴하고, <code class=\"docutils literal notranslate\"><span class=\"pre\">perm``은</span> <span class=\"pre\">``&quot;1.2&quot;</span></code> 안의 포맷이다(<span class=\"xref std std-ref\">permissions 3 참조). :attr:</span>. User.is_active` 및 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_superuser\" title=\"django.contrib.auth.models.User.is_superuser\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_superuser</span></code></a> 가 모두 <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True``이면, 이 메소드는 항상 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>True``를 리턴한다.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">obj</span></code> 가 전달이 되면, 이 메소드는 모델에 대한 권한이 아니라 특정 객체에 대한 권한을 체크한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.PermissionsMixin.has_perms\">\n<span class=\"sig-name descname\"><span class=\"pre\">has_perms</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">perm_list</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">obj</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.PermissionsMixin.has_perms\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>사용에게 각각의 특정한 권한이 주어진다면 , <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True``를 리턴하고, 각각의 perm은 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>”1.2” 안의 포맷이다. <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_active\" title=\"django.contrib.auth.models.User.is_active\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">User.is_active</span></code></a> 및 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_superuser\" title=\"django.contrib.auth.models.User.is_superuser\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_superuser</span></code></a> 가 모두 <a href=\"#id5\"><span class=\"problematic\" id=\"id6\">`</span></a>True``이면, 이 메소드는 항상 <a href=\"#id7\"><span class=\"problematic\" id=\"id8\">``</span></a>True``를 리턴한다.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">obj</span></code> 가 전달이 되면, 이 메소드는 모델에 대한 권한이 아니라 특정 객체에 대한 권한을 체크한다.</p>\n</dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.contrib.auth.models.PermissionsMixin.has_module_perms\">\n<span class=\"sig-name descname\"><span class=\"pre\">has_module_perms</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">package_name</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.contrib.auth.models.PermissionsMixin.has_module_perms\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><p>사용자가 주어진 패키지(django 애플리케이션 레이블)에 대한 모든 권한을 가지고 있으면, <a href=\"#id1\"><span class=\"problematic\" id=\"id2\">``</span></a>True``를 리턴한다. 만일, <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_active\" title=\"django.contrib.auth.models.User.is_active\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">User.is_active</span></code></a> 및 <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User.is_superuser\" title=\"django.contrib.auth.models.User.is_superuser\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">is_superuser</span></code></a>  모두 <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>True``라면, 이 메소드는 항상 <a href=\"#id5\"><span class=\"problematic\" id=\"id6\">``</span></a>True``를 리턴한다.</p>\n</dd></dl>\n\n</dd></dl>\n\n<aside class=\"admonition-permissionsmixin-and-modelbackend admonition\">\n<p class=\"admonition-title\"><code class=\"docutils literal notranslate\"><span class=\"pre\">PermissionsMixin</span></code> 및 <code class=\"docutils literal notranslate\"><span class=\"pre\">ModelBackend</span></code></p>\n<p>:class:<a href=\"#id1\"><span class=\"problematic\" id=\"id2\">`</span></a>~django.contrib.auth.models.PermissionsMixin`을 포함하지 않는다면, <a href=\"#id3\"><span class=\"problematic\" id=\"id4\">``</span></a>ModelBackend``에 있는 권한 메소드를 호출하지 않아야 한다. <a href=\"#id5\"><span class=\"problematic\" id=\"id6\">``</span></a>ModelBackend``는 특정한 필드가 사용자 모델에서 사용할 수 있다고 가정한다. 만약 사용자 모델이 이러한 필드를 제공하지 않는다면, 권한을 확인할 때 데이터베이스 오류가 발생할 것이다.</p>\n</aside>\n</section>\n<section id=\"custom-users-and-proxy-models\">\n<h3>사용자 커스터마이즈와 프록시 모델<a class=\"heading-anchor\" href=\"#custom-users-and-proxy-models\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>One limitation of custom user models is that installing a custom user model\nwill break any proxy model extending <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a>.\nProxy models must be based on a concrete base class; by defining a custom user\nmodel, you remove the ability of Django to reliably identify the base class.</p>\n<p>If your project uses proxy models, you must either modify the proxy to extend\nthe user model that’s in use in your project, or merge your proxy’s behavior\ninto your <a class=\"reference internal\" href=\"/ko/4.1/ref/contrib/auth/#django.contrib.auth.models.User\" title=\"django.contrib.auth.models.User\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">User</span></code></a> subclass.</p>\n</section>\n<section id=\"a-full-example\">\n<span id=\"custom-users-admin-full-example\"></span><h3>전체 예시<a class=\"heading-anchor\" href=\"#a-full-example\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Here is an example of an admin-compliant custom user app. This user model uses\nan email address as the username, and has a required date of birth; it\nprovides no permission checking beyond an <code class=\"docutils literal notranslate\"><span class=\"pre\">admin</span></code> flag on the user account.\nThis model would be compatible with all the built-in auth forms and views,\nexcept for the user creation forms. This example illustrates how most of the\ncomponents work together, but is not intended to be copied directly into\nprojects for production use.</p>\n<p>This code would all live in a <code class=\"docutils literal notranslate\"><span class=\"pre\">models.py</span></code> file for a custom\nauthentication app:</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=\"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.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"p\">(</span>\n    <span class=\"n\">BaseUserManager</span><span class=\"p\">,</span> <span class=\"n\">AbstractBaseUser</span>\n<span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyUserManager</span><span class=\"p\">(</span><span class=\"n\">BaseUserManager</span><span class=\"p\">):</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">create_user</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">email</span><span class=\"p\">,</span> <span class=\"n\">date_of_birth</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Creates and saves a User with the given email, date of</span>\n<span class=\"sd\">        birth and password.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"k\">if</span> <span class=\"ow\">not</span> <span class=\"n\">email</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"ne\">ValueError</span><span class=\"p\">(</span><span class=\"s1\">&#39;Users must have an email address&#39;</span><span class=\"p\">)</span>\n\n        <span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">model</span><span class=\"p\">(</span>\n            <span class=\"n\">email</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">normalize_email</span><span class=\"p\">(</span><span class=\"n\">email</span><span class=\"p\">),</span>\n            <span class=\"n\">date_of_birth</span><span class=\"o\">=</span><span class=\"n\">date_of_birth</span><span class=\"p\">,</span>\n        <span class=\"p\">)</span>\n\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">set_password</span><span class=\"p\">(</span><span class=\"n\">password</span><span class=\"p\">)</span>\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">_db</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"n\">user</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">create_superuser</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">email</span><span class=\"p\">,</span> <span class=\"n\">date_of_birth</span><span class=\"p\">,</span> <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n<span class=\"w\">        </span><span class=\"sd\">&quot;&quot;&quot;</span>\n<span class=\"sd\">        Creates and saves a superuser with the given email, date of</span>\n<span class=\"sd\">        birth and password.</span>\n<span class=\"sd\">        &quot;&quot;&quot;</span>\n        <span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">create_user</span><span class=\"p\">(</span>\n            <span class=\"n\">email</span><span class=\"p\">,</span>\n            <span class=\"n\">password</span><span class=\"o\">=</span><span class=\"n\">password</span><span class=\"p\">,</span>\n            <span class=\"n\">date_of_birth</span><span class=\"o\">=</span><span class=\"n\">date_of_birth</span><span class=\"p\">,</span>\n        <span class=\"p\">)</span>\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">is_admin</span> <span class=\"o\">=</span> <span class=\"kc\">True</span>\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">using</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">_db</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"n\">user</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyUser</span><span class=\"p\">(</span><span class=\"n\">AbstractBaseUser</span><span class=\"p\">):</span>\n    <span class=\"n\">email</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">EmailField</span><span class=\"p\">(</span>\n        <span class=\"n\">verbose_name</span><span class=\"o\">=</span><span class=\"s1\">&#39;email address&#39;</span><span class=\"p\">,</span>\n        <span class=\"n\">max_length</span><span class=\"o\">=</span><span class=\"mi\">255</span><span class=\"p\">,</span>\n        <span class=\"n\">unique</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n    <span class=\"p\">)</span>\n    <span class=\"n\">date_of_birth</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">DateField</span><span class=\"p\">()</span>\n    <span class=\"n\">is_active</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">BooleanField</span><span class=\"p\">(</span><span class=\"n\">default</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">)</span>\n    <span class=\"n\">is_admin</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">BooleanField</span><span class=\"p\">(</span><span class=\"n\">default</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n\n    <span class=\"n\">objects</span> <span class=\"o\">=</span> <span class=\"n\">MyUserManager</span><span class=\"p\">()</span>\n\n    <span class=\"n\">USERNAME_FIELD</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;email&#39;</span>\n    <span class=\"n\">REQUIRED_FIELDS</span> <span class=\"o\">=</span> <span class=\"p\">[</span><span class=\"s1\">&#39;date_of_birth&#39;</span><span class=\"p\">]</span>\n\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\">email</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">has_perm</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">perm</span><span class=\"p\">,</span> <span class=\"n\">obj</span><span class=\"o\">=</span><span class=\"kc\">None</span><span class=\"p\">):</span>\n        <span class=\"s2\">&quot;Does the user have a specific permission?&quot;</span>\n        <span class=\"c1\"># Simplest possible answer: Yes, always</span>\n        <span class=\"k\">return</span> <span class=\"kc\">True</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">has_module_perms</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">app_label</span><span class=\"p\">):</span>\n        <span class=\"s2\">&quot;Does the user have permissions to view the app `app_label`?&quot;</span>\n        <span class=\"c1\"># Simplest possible answer: Yes, always</span>\n        <span class=\"k\">return</span> <span class=\"kc\">True</span>\n\n    <span class=\"nd\">@property</span>\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">is_staff</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"s2\">&quot;Is the user a member of staff?&quot;</span>\n        <span class=\"c1\"># Simplest possible answer: All admins are staff</span>\n        <span class=\"k\">return</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">is_admin</span>\n</code></pre></div>\n<p>Then, to register this custom user model with Django’s admin, the following\ncode would be required in the app’s <code class=\"docutils literal notranslate\"><span class=\"pre\">admin.py</span></code> file:</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=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">forms</span>\n<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<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Group</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.admin</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">UserAdmin</span> <span class=\"k\">as</span> <span class=\"n\">BaseUserAdmin</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.contrib.auth.forms</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ReadOnlyPasswordHashField</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.exceptions</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">ValidationError</span>\n\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">customauth.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">MyUser</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">UserCreationForm</span><span class=\"p\">(</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">ModelForm</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;A form for creating new users. Includes all the required</span>\n<span class=\"sd\">    fields, plus a repeated password.&quot;&quot;&quot;</span>\n    <span class=\"n\">password1</span> <span class=\"o\">=</span> <span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">label</span><span class=\"o\">=</span><span class=\"s1\">&#39;Password&#39;</span><span class=\"p\">,</span> <span class=\"n\">widget</span><span class=\"o\">=</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">PasswordInput</span><span class=\"p\">)</span>\n    <span class=\"n\">password2</span> <span class=\"o\">=</span> <span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">CharField</span><span class=\"p\">(</span><span class=\"n\">label</span><span class=\"o\">=</span><span class=\"s1\">&#39;Password confirmation&#39;</span><span class=\"p\">,</span> <span class=\"n\">widget</span><span class=\"o\">=</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">PasswordInput</span><span class=\"p\">)</span>\n\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">MyUser</span>\n        <span class=\"n\">fields</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;email&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;date_of_birth&#39;</span><span class=\"p\">)</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">clean_password2</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Check that the two password entries match</span>\n        <span class=\"n\">password1</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">cleaned_data</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;password1&quot;</span><span class=\"p\">)</span>\n        <span class=\"n\">password2</span> <span class=\"o\">=</span> <span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">cleaned_data</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"s2\">&quot;password2&quot;</span><span class=\"p\">)</span>\n        <span class=\"k\">if</span> <span class=\"n\">password1</span> <span class=\"ow\">and</span> <span class=\"n\">password2</span> <span class=\"ow\">and</span> <span class=\"n\">password1</span> <span class=\"o\">!=</span> <span class=\"n\">password2</span><span class=\"p\">:</span>\n            <span class=\"k\">raise</span> <span class=\"n\">ValidationError</span><span class=\"p\">(</span><span class=\"s2\">&quot;Passwords don&#39;t match&quot;</span><span class=\"p\">)</span>\n        <span class=\"k\">return</span> <span class=\"n\">password2</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">save</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">commit</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Save the provided password in hashed format</span>\n        <span class=\"n\">user</span> <span class=\"o\">=</span> <span class=\"nb\">super</span><span class=\"p\">()</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">(</span><span class=\"n\">commit</span><span class=\"o\">=</span><span class=\"kc\">False</span><span class=\"p\">)</span>\n        <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">set_password</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"n\">cleaned_data</span><span class=\"p\">[</span><span class=\"s2\">&quot;password1&quot;</span><span class=\"p\">])</span>\n        <span class=\"k\">if</span> <span class=\"n\">commit</span><span class=\"p\">:</span>\n            <span class=\"n\">user</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n        <span class=\"k\">return</span> <span class=\"n\">user</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">UserChangeForm</span><span class=\"p\">(</span><span class=\"n\">forms</span><span class=\"o\">.</span><span class=\"n\">ModelForm</span><span class=\"p\">):</span>\n<span class=\"w\">    </span><span class=\"sd\">&quot;&quot;&quot;A form for updating users. Includes all the fields on</span>\n<span class=\"sd\">    the user, but replaces the password field with admin&#39;s</span>\n<span class=\"sd\">    disabled password hash display field.</span>\n<span class=\"sd\">    &quot;&quot;&quot;</span>\n    <span class=\"n\">password</span> <span class=\"o\">=</span> <span class=\"n\">ReadOnlyPasswordHashField</span><span class=\"p\">()</span>\n\n    <span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">Meta</span><span class=\"p\">:</span>\n        <span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">MyUser</span>\n        <span class=\"n\">fields</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;email&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;password&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;date_of_birth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;is_active&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;is_admin&#39;</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">UserAdmin</span><span class=\"p\">(</span><span class=\"n\">BaseUserAdmin</span><span class=\"p\">):</span>\n    <span class=\"c1\"># The forms to add and change user instances</span>\n    <span class=\"n\">form</span> <span class=\"o\">=</span> <span class=\"n\">UserChangeForm</span>\n    <span class=\"n\">add_form</span> <span class=\"o\">=</span> <span class=\"n\">UserCreationForm</span>\n\n    <span class=\"c1\"># The fields to be used in displaying the User model.</span>\n    <span class=\"c1\"># These override the definitions on the base UserAdmin</span>\n    <span class=\"c1\"># that reference specific fields on auth.User.</span>\n    <span class=\"n\">list_display</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;email&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;date_of_birth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;is_admin&#39;</span><span class=\"p\">)</span>\n    <span class=\"n\">list_filter</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;is_admin&#39;</span><span class=\"p\">,)</span>\n    <span class=\"n\">fieldsets</span> <span class=\"o\">=</span> <span class=\"p\">(</span>\n        <span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">(</span><span class=\"s1\">&#39;email&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;password&#39;</span><span class=\"p\">)}),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;Personal info&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">(</span><span class=\"s1\">&#39;date_of_birth&#39;</span><span class=\"p\">,)}),</span>\n        <span class=\"p\">(</span><span class=\"s1\">&#39;Permissions&#39;</span><span class=\"p\">,</span> <span class=\"p\">{</span><span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">(</span><span class=\"s1\">&#39;is_admin&#39;</span><span class=\"p\">,)}),</span>\n    <span class=\"p\">)</span>\n    <span class=\"c1\"># add_fieldsets is not a standard ModelAdmin attribute. UserAdmin</span>\n    <span class=\"c1\"># overrides get_fieldsets to use this attribute when creating a user.</span>\n    <span class=\"n\">add_fieldsets</span> <span class=\"o\">=</span> <span class=\"p\">(</span>\n        <span class=\"p\">(</span><span class=\"kc\">None</span><span class=\"p\">,</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;classes&#39;</span><span class=\"p\">:</span> <span class=\"p\">(</span><span class=\"s1\">&#39;wide&#39;</span><span class=\"p\">,),</span>\n            <span class=\"s1\">&#39;fields&#39;</span><span class=\"p\">:</span> <span class=\"p\">(</span><span class=\"s1\">&#39;email&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;date_of_birth&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;password1&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;password2&#39;</span><span class=\"p\">),</span>\n        <span class=\"p\">}),</span>\n    <span class=\"p\">)</span>\n    <span class=\"n\">search_fields</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;email&#39;</span><span class=\"p\">,)</span>\n    <span class=\"n\">ordering</span> <span class=\"o\">=</span> <span class=\"p\">(</span><span class=\"s1\">&#39;email&#39;</span><span class=\"p\">,)</span>\n    <span class=\"n\">filter_horizontal</span> <span class=\"o\">=</span> <span class=\"p\">()</span>\n\n\n<span class=\"c1\"># Now register the new UserAdmin...</span>\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\">MyUser</span><span class=\"p\">,</span> <span class=\"n\">UserAdmin</span><span class=\"p\">)</span>\n<span class=\"c1\"># ... and, since we&#39;re not using Django&#39;s built-in permissions,</span>\n<span class=\"c1\"># unregister the Group model from admin.</span>\n<span class=\"n\">admin</span><span class=\"o\">.</span><span class=\"n\">site</span><span class=\"o\">.</span><span class=\"n\">unregister</span><span class=\"p\">(</span><span class=\"n\">Group</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Finally, specify the custom model as the default user model for your project\nusing the <a class=\"reference internal\" href=\"/ko/4.1/ref/settings/#std-setting-AUTH_USER_MODEL\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">AUTH_USER_MODEL</span></code></a> setting in your <code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</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=\"n\">AUTH_USER_MODEL</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;customauth.MyUser&#39;</span>\n</code></pre></div>\n</section>\n</section>","rootId":"customizing-authentication-in-django","toc":[{"title":"다른 인증 소스들","anchor":"other-authentication-sources","children":[{"title":"인증 백엔드 명세하기","anchor":"specifying-authentication-backends","children":[]},{"title":"인증 백엔드 작성하기","anchor":"writing-an-authentication-backend","children":[]},{"title":"맞춤 백엔드 에서 인증 다루기","anchor":"handling-authorization-in-custom-backends","children":[{"title":"익명 사용자를 위한 인증","anchor":"authorization-for-anonymous-users","children":[]},{"title":"비활성 사용자를 위한 인증","anchor":"authorization-for-inactive-users","children":[]},{"title":"객체 권한 다루기","anchor":"handling-object-permissions","children":[]}]}]},{"title":"맞춤 권한","anchor":"custom-permissions","children":[]},{"title":"기존 User 모델 확장하기","anchor":"extending-the-existing-user-model","children":[]},{"title":"맞춤 User 모델 대체하기","anchor":"substituting-a-custom-user-model","children":[{"title":"프로젝트를 시작할 때 맞춤 사용자 모델 사용하기","anchor":"using-a-custom-user-model-when-starting-a-project","children":[]},{"title":"프로젝트 중간에 맞춤 사용자 모델 변경하기","anchor":"changing-to-a-custom-user-model-mid-project","children":[]},{"title":"재사용 가능 앱과 AUTH_USER_MODEL","anchor":"reusable-apps-and-auth-user-model","children":[]},{"title":"User 모델 참조하기","anchor":"referencing-the-user-model","children":[]},{"title":"맞춤 사용자 모델 명세하기","anchor":"specifying-a-custom-user-model","children":[]},{"title":"사용자 맞춤 모델을 위한 관리자 작성","anchor":"writing-a-manager-for-a-custom-user-model","children":[]},{"title":"Django의 기본 “User”를 확장","anchor":"extending-django-s-default-user","children":[]},{"title":"사용자 맞춤과 내장된 폼","anchor":"custom-users-and-the-built-in-auth-forms","children":[]},{"title":"커스텀 User 와 django.contrib.admin 모듈","anchor":"custom-users-and-django-contrib-admin","children":[]},{"title":"사용자 커스터마이징 과 권한들","anchor":"custom-users-and-permissions","children":[]},{"title":"사용자 커스터마이즈와 프록시 모델","anchor":"custom-users-and-proxy-models","children":[]},{"title":"전체 예시","anchor":"a-full-example","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Django 사용하기","url":"/ko/4.1/topics/"},{"docname":"topics/auth/index","title":"Django에서의 사용자 증명","url":"/ko/4.1/topics/auth/"}],"prev":{"docname":"topics/auth/passwords","title":"Password management in Django","url":"/ko/4.1/topics/auth/passwords/"},"next":{"docname":"topics/cache","title":"Django의 캐시 프레임워크","url":"/ko/4.1/topics/cache/"},"formats":{"html":"/ko/4.1/topics/auth/customizing/","markdown":"/ko/4.1/topics/auth/customizing.md","json":"/ko/4.1/topics/auth/customizing.json"},"source":"https://github.com/django/django/blob/stable/4.1.x/docs/topics/auth/customizing.txt","official":"https://docs.djangoproject.com/ko/4.1/topics/auth/customizing/","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","it","pt-br","ko","es","el","pl"]}