웹사이트 검색

Django 모델을 만드는 방법


소개

이전 자습서 "Django 앱을 만들고 데이터베이스에 연결하는 방법\에서는 MySQL 데이터베이스를 만드는 방법, Django 애플리케이션을 만들고 시작하는 방법, MySQL 데이터베이스에 연결하는 방법을 다루었습니다.

이 자습서에서는 저장할 블로그 애플리케이션 데이터의 필드와 동작을 정의하는 Django 모델을 만듭니다. 이러한 모델은 Django 애플리케이션의 데이터를 데이터베이스에 매핑합니다. 이것은 Django가 "모델\이라고 하는 객체 관계 매핑(ORM) API를 통해 데이터베이스 테이블을 생성하는 데 사용하는 것입니다.

전제 조건

이 자습서는 Django 개발 시리즈의 일부이며 해당 시리즈의 연속입니다.

이 시리즈를 따르지 않은 경우 다음과 같이 가정합니다.

  • Django 버전 4 이상이 설치되어 있습니다.
  • Django 앱을 데이터베이스에 연결했습니다. 우리는 MySQL을 사용하고 있으며 Django 시리즈의 2부인 "Django 앱을 만들고 데이터베이스에 연결하는 방법\을 따라 이 연결을 달성할 수 있습니다.
  • 당신은 Unix 기반 운영 체제로 작업하고 있으며 Ubuntu 22.04 클라우드 서버가 우리가 테스트한 시스템인 것이 바람직합니다. 유사한 환경에서 Django를 설정하려면 "Ubuntu 22.04에서 Django를 설치하고 개발 환경을 설정하는 방법\ 자습서를 참조하세요.

이 튜토리얼은 주로 Django 모델을 다루므로 설정이 다소 다르더라도 따라할 수 있습니다.

1단계 — Django 애플리케이션 생성

모듈화에 대한 Django 철학과 일관되게 블로그 웹 사이트를 만드는 데 필요한 모든 파일을 포함하는 프로젝트 내에서 Django 앱을 만들 것입니다.

Python 및 Django에서 작업을 시작할 때마다 Python 가상 환경을 활성화하고 앱의 루트 디렉터리로 이동해야 합니다. 시리즈를 따라했다면 다음을 입력하여 이를 달성할 수 있습니다.

  1. cd ~/my_blog_app
  2. . env/bin/activate
  3. cd blog

여기에서 다음 명령을 실행해 보겠습니다.

  1. python manage.py startapp blogsite

이렇게 하면 blogsite 디렉토리와 함께 앱이 생성됩니다.

자습서 시리즈의 이 시점에서 프로젝트에 대해 다음과 같은 디렉터리 구조를 갖게 됩니다.

my_blog_app/
└── blog
    ├── blog
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-38.pyc
    │   │   ├── settings.cpython-38.pyc
    │   │   ├── urls.cpython-38.pyc
    │   │   └── wsgi.cpython-38.pyc
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── blogsite
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    └── manage.py

이 튜토리얼에서 중점적으로 다룰 파일은 blogsite 디렉토리에 있는 models.py 파일입니다.

2단계 - 게시물 모델 추가

먼저 post 모델을 생성하기 위한 코드를 포함하도록 models.py 파일을 열고 편집해야 합니다. Post 모델에는 다음 데이터베이스 필드가 포함됩니다.

  • 제목 — 블로그 게시물의 제목입니다.
  • slug — 웹 페이지에 대해 유효한 URL이 저장되고 생성되는 위치입니다.
  • content — 블로그 게시물의 텍스트 콘텐츠입니다.
  • created_on — 게시물이 생성된 날짜입니다.
  • author — 게시물을 작성한 사람입니다.

이제 models.py 파일이 있는 디렉토리로 이동합니다.

  1. cd ~/my_blog_app/blog/blogsite

터미널에 파일 내용을 표시하려면 cat 명령을 사용하십시오.

  1. cat models.py

파일에는 이 models.py 파일에 배치할 항목을 설명하는 주석과 함께 모델을 가져오는 다음 코드가 있어야 합니다.

from django.db import models

# Create your models here.

즐겨 사용하는 텍스트 편집기를 사용하여 models.py 파일에 다음 코드를 추가합니다. 우리는 텍스트 편집기로 nano를 사용하지만 원하는 것을 사용할 수 있습니다.

  1. nano models.py

이 파일에는 모델 API를 가져오기 위한 코드가 이미 추가되어 있으므로 다음 주석을 삭제할 수 있습니다. 그런 다음 문자열에서 슬러그를 생성하기 위해 slugify를 가져오고 인증을 위해 Django의 User를 가져오며 django.urlsreverse를 가져옵니다. > URL 생성에 더 큰 유연성을 제공합니다.

from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse

그런 다음 Post를 호출할 모델 클래스에 title, slug, 데이터베이스 필드와 함께 클래스 메서드를 추가합니다. content, created_onauthor. 수입 명세서 아래에 추가하십시오.

...
class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

다음으로 URL 생성 기능과 게시물 저장 기능을 추가하겠습니다. 이는 고유한 게시물과 일치하는 고유한 링크를 생성하기 때문에 매우 중요합니다.

...
    def get_absolute_url(self):
        return reverse('blog_post_detail', args=[self.slug])

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

이제 게시물이 어떻게 정렬되고 웹 페이지에 표시되는지 모델에 알려야 합니다. 이에 대한 논리는 중첩된 내부 Meta 클래스에 추가됩니다. Meta 클래스는 일반적으로 데이터베이스 필드 정의와 관련되지 않은 다른 중요한 모델 논리를 포함합니다.

...
    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title

마지막으로 이 파일에 Comment 모델을 추가합니다. 여기에는 서명에 models.Models가 있는 Comment라는 또 다른 클래스를 추가하고 다음 데이터베이스 필드를 정의하는 작업이 포함됩니다.

  • name — 댓글을 게시한 사람의 이름입니다.
  • email — 댓글을 게시한 사람의 이메일 주소입니다.
  • text — 주석 자체의 텍스트입니다.
  • 게시물 — 댓글이 달린 게시물입니다.
  • created_on — 댓글이 생성된 시간입니다.

...
class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)

이 시점에서 models.py가 완료됩니다. models.py 파일이 다음과 일치하는지 확인하십시오.

from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse


class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(unique=True, max_length=255)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    author = models.TextField()

    def get_absolute_url(self):
        return reverse('blog_post_detail', args=[self.slug])
    
    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super(Post, self).save(*args, **kwargs)

    class Meta:
        ordering = ['created_on']

        def __unicode__(self):
            return self.title


class Comment(models.Model):
    name = models.CharField(max_length=42)
    email = models.EmailField(max_length=75)
    website = models.URLField(max_length=200, null=True, blank=True)
    content = models.TextField()
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)


파일을 저장하고 닫으십시오. nano를 사용하는 경우 CTRLX를 입력한 다음 Y를 입력하고 ENTER를 입력하면 됩니다. .

models.py 파일이 설정되면 계속해서 settings.py 파일을 업데이트할 수 있습니다.

3단계 - 설정 업데이트

애플리케이션에 모델을 추가했으므로 방금 추가한 blogsite 앱의 존재를 프로젝트에 알려야 합니다. settings.pyINSTALLED_APPS 섹션에 추가하면 됩니다.

settings.py가 있는 디렉토리로 이동합니다.

  1. cd ~/my_blog_app/blog/blog

여기에서 예를 들어 nano로 settings.py 파일을 엽니다.

  1. nano settings.py

파일을 연 상태에서 아래와 같이 파일의 INSTALLED_APPS 섹션에 blogsite 앱을 추가합니다.

# Application definition
INSTALLED_APPS = [
    'blogsite',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

blogsite 앱이 추가되면 파일을 저장하고 종료할 수 있습니다.

이제 이러한 변경 사항을 적용할 준비가 되었습니다.

4단계 - 마이그레이션 수행

PostComment 모델이 추가되었으므로 다음 단계는 MySQL 데이터베이스 스키마가 이를 인식하고 필요한 테이블을 생성하도록 이러한 변경 사항을 적용하는 것입니다. .

먼저 makemigrations 명령을 사용하여 모델 변경 사항을 개별 마이그레이션 파일로 패키징해야 합니다. 이러한 파일은 Git과 같은 버전 제어 시스템의 커밋 파일과 유사합니다.

이제 ~/my_blog_app/blog/blogsite/migrations로 이동하여 ls를 실행하면 __init__.py 파일입니다. 마이그레이션을 추가하면 변경됩니다.

다음과 같이 cd를 사용하여 블로그 디렉토리로 변경합니다.

  1. cd ~/my_blog_app/blog

그런 다음 manage.py에서 makemigrations 명령을 실행합니다.

  1. python manage.py makemigrations

그러면 터미널 창에 다음 출력이 표시됩니다.

Output
Migrations for 'blogsite': blogsite/migrations/0001_initial.py - Create model Post - Create model Comment

/~/my_blog_app/blog/blogsite/migrations로 이동했을 때 __init__.py 파일만 있었던 것을 기억하십니까? 이제 해당 디렉터리로 다시 cd하면 __pycache__0001_initial.py라는 두 항목이 추가되었음을 알 수 있습니다. 0001_initial.py 파일은 makemigrations를 실행할 때 자동으로 생성되었습니다. makemigrations를 실행할 때마다 유사한 파일이 생성됩니다.

파일에 포함된 내용을 읽으려면 해당 디렉토리에서 less 0001_initial.py를 실행하세요.

이제 ~/my_blog_app/blog로 이동합니다.

  1. cd ~/my_blog_app/blog

마이그레이션 파일을 만들었으므로 migrate 명령을 사용하여 이 파일이 설명하는 변경 사항을 데이터베이스에 적용해야 합니다. 그러나 먼저 showmigrations 명령을 사용하여 현재 존재하는 마이그레이션을 확인하겠습니다.

  1. python manage.py showmigrations
Output
admin [X] 0001_initial [X] 0002_logentry_remove_auto_add [X] 0003_logentry_add_action_flag_choices auth [X] 0001_initial [X] 0002_alter_permission_name_max_length [X] 0003_alter_user_email_max_length [X] 0004_alter_user_username_opts [X] 0005_alter_user_last_login_null [X] 0006_require_contenttypes_0002 [X] 0007_alter_validators_add_error_messages [X] 0008_alter_user_username_max_length [X] 0009_alter_user_last_name_max_length [X] 0010_alter_group_name_max_length [X] 0011_update_proxy_permissions blogsite [ ] 0001_initial contenttypes [X] 0001_initial [X] 0002_remove_content_type_name sessions [X] 0001_initial

PostComment 모델로 방금 생성한 0001_initial에 대한 마이그레이션을 제외한 모든 마이그레이션이 확인되었음을 알 수 있습니다.

이제 다음 명령을 사용하여 마이그레이션을 수행하면 어떤 SQL 문이 실행되는지 확인하겠습니다. 마이그레이션 및 마이그레이션 제목을 인수로 사용합니다.

  1. python manage.py sqlmigrate blogsite 0001_initial

아래에 공개된 것은 배후에서 수행되는 실제 SQL 쿼리입니다.

Output
-- -- Create model Post -- CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL); -- -- Create model Comment -- CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL); ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);

이제 마이그레이션을 수행하여 MySQL 데이터베이스에 적용해 보겠습니다.

  1. python manage.py migrate

다음 출력을 받게 됩니다.

Output
Operations to perform: Apply all migrations: admin, auth, blogsite, contenttypes, sessions Running migrations: Applying blogsite.0001_initial... OK

이제 마이그레이션을 성공적으로 적용했습니다.

Django 설명서에 명시된 대로 MySQL을 백엔드로 사용하는 Django 마이그레이션에는 세 가지 주의 사항이 있음을 명심하는 것이 중요합니다.

  • 스키마 변경 작업에 대한 트랜잭션 지원 부족. 즉, 마이그레이션이 성공적으로 적용되지 않으면 다른 마이그레이션을 시도하기 위해 변경 사항을 수동으로 선택 해제해야 합니다. 실패한 마이그레이션에서 변경 사항이 적용되기 전에는 이전 시점으로 롤백할 수 없습니다.
  • 대부분의 스키마 변경 작업에서 MySQL은 테이블을 완전히 다시 작성합니다. 최악의 경우 시간 복잡도는 열을 추가하거나 제거할 테이블의 행 수에 비례합니다. Django 문서에 따르면 이 작업은 백만 행당 1분 정도로 느릴 수 있습니다.
  • MySQL에는 열, 테이블 및 인덱스의 이름 길이에 약간의 제한이 있습니다. 모든 열과 인덱스 표지의 결합된 크기에도 제한이 있습니다. 일부 다른 백엔드는 Django에서 생성된 더 높은 제한을 지원할 수 있지만 동일한 인덱스는 MySQL 백엔드에서 생성되지 않습니다.

Django와 함께 사용하기 위해 고려하는 각 데이터베이스에 대해 각각의 장점과 단점을 비교해야 합니다.

5단계 - 데이터베이스 스키마 확인

마이그레이션이 완료되면 Django 모델을 통해 생성한 MySQL 테이블이 성공적으로 생성되었는지 확인해야 합니다.

이렇게 하려면 터미널에서 다음 명령을 실행하여 MySQL에 로그인합니다. 이전 튜토리얼에서 생성한 djangouser를 사용할 것입니다.

  1. mysql blog_data -u djangouser

이제 데이터베이스 blog_data를 선택합니다. 사용 중인 데이터베이스를 모르는 경우 SQL에서 SHOW DATABASES;를 사용하여 모든 데이터베이스를 표시할 수 있습니다.

  1. USE blog_data;

그런 다음 다음 명령을 입력하여 테이블을 봅니다.

  1. SHOW TABLES;

이 SQL 쿼리는 다음을 표시해야 합니다.

Output
+----------------------------+ | Tables_in_blog_data | +----------------------------+ | auth_group | | auth_group_permissions | | auth_permission | | auth_user | | auth_user_groups | | auth_user_user_permissions | | blogsite_comment | | blogsite_post | | django_admin_log | | django_content_type | | django_migrations | | django_session | +----------------------------+ 12 rows in set (0.01 sec)

테이블 중에는 blogsite_commentblogsite_post가 있습니다. 이것은 우리가 방금 만든 모델입니다. 우리가 정의한 필드가 포함되어 있는지 확인합시다.

  1. DESCRIBE blogsite_comment;
Output
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | name | varchar(42) | NO | | NULL | | | email | varchar(75) | NO | | NULL | | | website | varchar(200) | YES | | NULL | | | content | longtext | NO | | NULL | | | created_on | datetime(6) | NO | | NULL | | | post_id | int | NO | MUL | NULL | | +------------+--------------+------+-----+---------+----------------+ 7 rows in set (0.00 sec)
  1. DESCRIBE blogsite_post;
Output
+------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | title | varchar(255) | NO | | NULL | | | slug | varchar(255) | NO | UNI | NULL | | | content | longtext | NO | | NULL | | | created_on | datetime(6) | NO | | NULL | | | author | longtext | NO | | NULL | | +------------+--------------+------+-----+---------+----------------+ 6 rows in set (0.00 sec)

Django 모델 마이그레이션에서 데이터베이스 테이블이 성공적으로 생성되었음을 확인했습니다.

CTRL + D를 사용하여 MySQL을 종료하고 Python 환경을 종료할 준비가 되면 deactivate 명령을 실행할 수 있습니다.

  1. deactivate

프로그래밍 환경을 비활성화하면 터미널 명령 프롬프트로 돌아갑니다.

결론

이 자습서에서는 블로그 웹 애플리케이션의 기본 기능에 대한 모델을 성공적으로 추가했습니다. 모델 코딩 방법, 마이그레이션 작동 방법 및 Django 모델을 실제 MySQL로 변환하는 프로세스를 배웠습니다. 데이터베이스 테이블.