Notice
Recent Posts
Recent Comments
관리 메뉴

안까먹을라고 쓰는 블로그

[Python_Django_VSCode] Django Tutorials - 13 (데이터, 데이터 모델 및 마이그레이션 작업) 본문

Language/Python(Django)

[Python_Django_VSCode] Django Tutorials - 13 (데이터, 데이터 모델 및 마이그레이션 작업)

YawnsDuzin 2022. 1. 19. 17:58

 

반응형


https://code.visualstudio.com/docs/python/tutorial-django

 

Python and Django tutorial in Visual Studio Code

Python Django tutorial demonstrating IntelliSense, code navigation, and debugging for both code and templates in Visual Studio Code, the best Python IDE.

code.visualstudio.com


데이터, 데이터 모델 및 마이그레이션 작업


많은 웹 앱은 데이터베이스에 저장된 정보로 작동하며 Django는 모델을 사용하여 해당 데이터베이스의 객체를 쉽게 나타낼 수 있습니다. Django에서 모델은 특정 데이터베이스 개체, 일반적으로 테이블을 나타내는 django.db.models.Model 에서 파생된 Python 클래스입니다. 이러한 클래스를 앱의 models.py 파일에 배치합니다.

Django를 사용하면 코드에서 정의한 모델을 통해 거의 독점적으로 데이터베이스를 사용합니다. 
Django의 "마이그레이션"은 시간이 지남에 따라 모델을 발전시키면서 기본 데이터베이스의 모든 세부 정보를 자동으로 처리합니다. 일반적인 작업 흐름은 다음과 같습니다. 

 1. models.py 파일에서 모델을 변경하십시오.
 2. python manage.py makemigrations 를 실행하여 데이터베이스를 현재 상태에서 새 상태로 마이그레이션하는 migrations  폴더에 스크립트를 생성합니다.
 3. python manage.py migrate 를 실행하여 스크립트를 실제 데이터베이스에 적용합니다.

마이그레이션 스크립트는 시간 경과에 따라 데이터 모델에 대한 모든 증분 변경 사항을 효과적으로 기록합니다. 마이그레이션을 적용하면 Django는 모델과 일치하도록 데이터베이스를 업데이트합니다. 각 증분 변경에는 자체 스크립트가 있기 때문에 Django는 이전 버전의 데이터베이스(새 데이터베이스 포함)를 현재 버전으로 자동 마이그레이션할 수 있습니다. 결과적으로 기본 데이터베이스 스키마나 마이그레이션 스크립트가 아닌 models.py 의 모델에만 관심을 가지면 됩니다. Django가 그 역할을 하도록 했습니다!

코드에서도 모델 클래스와 독점적으로 작업하여 데이터를 저장하고 검색합니다. Django는 기본 세부 정보를 처리합니다. 한 가지 예외는 Django 관리 유틸리티 loaddata command 를 사용하여 데이터베이스에 데이터를 쓸 수 있다는 것입니다. 이 유틸리티는 migrate 명령이 스키마를 초기화한 후 데이터 세트를 초기화하는 데 자주 사용됩니다.

db.sqlite3 파일을 사용할 때 SQLite browser 와 같은 도구를 사용하여 데이터베이스와 직접 작업할 수도 있습니다. 이러한 도구를 사용하여 테이블에 레코드를 추가하거나 삭제하는 것은 괜찮지만 데이터베이스 스키마를 변경하지 마십시오. 그러면 데이터베이스가 앱 모델과 동기화되지 않기 때문입니다. 대신 모델을 변경하고 makemigrations 를 실행한 다음 migrate 를 실행하십시오.


데이터베이스 유형

기본적으로 Django에는 개발 작업에 적합한 앱 데이터베이스용 db.sqlite3 파일이 포함되어 있습니다.
SQLite를 사용해야 하는 경우(sqlite.org)에 설명된 대로 SQLite는 하루에 100,000번 미만의 적중률을 보이는 트래픽이 낮거나 중간 정도인 사이트에서 제대로 작동하지만 더 많은 볼륨에는 권장되지 않습니다. 
또한 단일 컴퓨터로 제한되므로 부하 분산 및 지역 복제와 같은 다중 서버 시나리오에서 사용할 수 없습니다.

이러한 이유로 PostgreSQL, MySQLSQL Server 와 같은 프로덕션 수준 데이터 저장소를 사용하는 것이 좋습니다. 다른 데이터베이스에 대한 Django 지원에 대한 정보는 데이터베이스 설정을 참조하세요. Python용 Azure SDK를 사용하여 테이블 및 Blob과 같은 Azure 저장소 서비스를 사용할 수도 있습니다.

모델 정의

Django 모델은 다시 django.db.model.Models 에서 파생된 Python 클래스이며 앱의 models.py 파일에 배치합니다. 데이터베이스에서 각 모델에는 id 라는 고유한 ID 필드가 자동으로 부여됩니다. 
다른 모든 필드는 django.db.models 의 유형을 사용하여 클래스의 속성으로 정의됩니다.
CharField(텍스트 제한), TextField(텍스트 무제한), EmailField, URLField, IntegerField, DecimalField, BooleanFieldDateTimeField, ForeignKeyManyToMany 등이 있습니다. (자세한 내용은 Django 설명서의 Model 필드 참조를 참조하세요.)

각 필드는 max_length와 같은 일부 속성을 사용합니다. blank=True 속성은 필드가 선택 사항임을 의미합니다. null=true는 값이 선택 사항임을 의미합니다. 값을 데이터 값/표시 값 튜플 배열의 값으로 제한하는 choices 속성도 있습니다.

예를 들어, hello/models.py에 다음 클래스를 추가하여 간단한 메시지 로그에서 날짜가 표시된 항목을 나타내는 데이터 모델을 정의합니다.

from django.db import models
from django.utils import timezone

class LogMessage(models.Model):
    message = models.CharField(max_length=300)
    log_date = models.DateTimeField("date logged")

    def __str__(self):
        """Returns a string representation of a message."""
        date = timezone.localtime(self.log_date)
        return f"'{self.message}' logged on {date.strftime('%A, %d %B, %Y at %X')}"


모델 클래스에는 다른 클래스 속성에서 계산된 값을 반환하는 메서드가 포함될 수 있습니다. 모델에는 일반적으로 인스턴스의 문자열 표현을 반환하는 __str__ 메서드가 포함됩니다.

 


데이터베이스 마이그레이션

models.py 를 편집하여 데이터 모델을 변경했으므로 데이터베이스 자체를 업데이트해야 합니다. VS Code에서 가상 환경이 활성화된 터미널을 열고(터미널: 새 터미널 만들기 명령, Ctrl+Shift+` 사용) 프로젝트 폴더로 이동하여 다음 명령을 실행합니다.

python manage.py makemigrations
python manage.py migrate


makemigrations가 생성하는 스크립트를 보려면 migrations 폴더를 살펴보십시오. 데이터베이스 자체를 보고 스키마가 업데이트되었는지 확인할 수도 있습니다.

명령을 실행할 때 오류가 표시되면 가상 환경이 활성화되지 않았을 수 있으므로 이전 단계에서 남은 디버깅 터미널을 사용하고 있지 않은지 확인하십시오.


모델을 통해 데이터베이스 사용

Model 이 제자리에 있고 데이터베이스가 migration 되면 Model만 사용하여 데이터를 저장하고 검색할 수 있습니다. 이 섹션에서는 메시지를 기록할 수 있는 양식 페이지를 앱에 추가합니다. 그런 다음 해당 메시지를 표시하도록 홈 페이지를 수정합니다. 여기에서 많은 코드 파일을 수정하므로 세부 사항에 유의하십시오.

1. hello 폴더(views.py가 있는 곳)에서 다음 코드를 사용하여 forms.py 라는 새 파일을 만듭니다. 이 파일은 데이터 모델 LogMessage 에서 가져온 필드가 포함된 Django 양식을 정의합니다.

from django import forms
from hello.models import LogMessage

class LogMessageForm(forms.ModelForm):
    class Meta:
        model = LogMessage
        fields = ("message",)   # NOTE: the trailing comma is required


2. hello/templates/hello 폴더에서 다음 내용으로 log_message.html 이라는 새 템플릿을 만듭니다. 이 템플릿은 템플릿에 양식 본문을 정의하는 form 이라는 변수가 제공된다고 가정합니다. 그런 다음 "Log" 레이블이 있는 submit 버튼을 추가합니다.

{% extends "hello/layout.html" %}
{% block title %}
    Log a message
{% endblock %}
{% block content %}
    <form method="POST" class="log-form">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="save btn btn-default">Log</button>
    </form>
{% endblock %}


참고: 
Django의 {% csrf_token %} 태그는 사이트 간 요청 위조로부터 보호합니다. 자세한 내용은 Django 문서에서 Cross Site Request Forgery 보호를 참조하세요.

3. 앱의 hello/static/hello/site.css 파일에서 입력 양식을 더 넓게 만드는 규칙을 추가합니다.

input[name=message] {
    width: 80%;
}


4. 앱의 hello/rls.py 파일에서 새 페이지에 대한 경로를 추가합니다.

path("log/", views.log_message, name="log"),


5. hello/views.py 에서 log_message 라는 뷰를 정의합니다(URL 경로로 참조됨). 이 보기는 HTTP GET 및 POST 케이스를 모두 처리합니다. GET의 경우(else: 섹션) 이전 단계에서 정의한 양식만 표시합니다. POST의 경우 양식에서 데이터를 데이터 개체(message)로 검색하고 타임스탬프를 설정한 다음 데이터베이스에 기록되는 시점에 해당 개체를 저장합니다.

# Add these to existing imports at the top of the file:
from django.shortcuts import redirect
from hello.forms import LogMessageForm
from hello.models import LogMessage

# Add this code elsewhere in the file:
def log_message(request):
    form = LogMessageForm(request.POST or None)

    if request.method == "POST":
        if form.is_valid():
            message = form.save(commit=False)
            message.log_date = datetime.now()
            message.save()
            return redirect("home")
    else:
        return render(request, "hello/log_message.html", {"form": form})


6. 모든 것을 시도할 준비가 되기 전에 한 단계 더! hello/templates/hello/layout.html 에서 메시지 로깅 페이지의 "navbar" div에 링크를 추가합니다.

<!-- Insert below the link to Home -->
<a href="{% url 'log' %}" class="navbar-item">Log Message</a>


7. 앱을 실행하고 브라우저에서 홈 페이지를 엽니다. 메시지 로깅 페이지를 표시해야 하는 탐색 모음에서 로그 메시지 링크를 선택합니다.

8. 메시지를 입력하고 로그를 선택하면 홈 페이지로 돌아갑니다. 홈 페이지에는 아직 기록된 메시지가 표시되지 않습니다(잠시 해결). 몇 가지 더 많은 메시지를 자유롭게 기록하십시오. 원하는 경우 SQLite Browser와 같은 도구를 사용하여 데이터베이스를 들여다보고 레코드가 생성되었는지 확인합니다. 데이터베이스를 읽기 전용으로 열거나 앱을 사용하기 전에 데이터베이스를 닫아야 합니다. 그렇지 않으면 데이터베이스가 잠겨 있기 때문에 앱이 실패합니다.

9. 완료되면 앱 중지

10. 이제 기록된 메시지를 표시하도록 홈 페이지를 수정합니다. 앱의 hello/templates/hello/home.html 파일 내용을 아래 마크업으로 교체하여 시작합니다. 이 템플릿에는 message_list 라는 컨텍스트 변수가 필요합니다. 하나를 수신하면( {% if message_list %} 태그로 확인) 해당 목록( {% for message in message_list %} 태그)을 반복하여 각 메시지에 대한 테이블 행을 생성합니다. 그렇지 않으면 페이지에 메시지가 아직 기록되지 않았음을 나타냅니다.

{% extends "hello/layout.html" %}
{% block title %}
    Home
{% endblock %}
{% block content %}
    <h2>Logged messages</h2>

    {% if message_list %}
        <table class="message_list">
            <thead>
            <tr>
                <th>Date</th>
                <th>Time</th>
                <th>Message</th>
            </tr>
            </thead>
            <tbody>
            {% for message in message_list %}
                <tr>
                    <td>{{ message.log_date | date:'d M Y' }}</td>
                    <td>{{ message.log_date | time:'H:i:s' }}</td>
                    <td>
                        {{ message.message }}
                    </td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
    {% else %}
        <p>No messages have been logged. Use the <a href="{% url 'log' %}">Log Message form</a>.</p>
    {% endif %}
{% endblock %}


11. hello/static/hello/site.css 에서 테이블 형식을 약간 지정하는 규칙을 추가합니다.

.message_list th,td {
    text-align: left;
    padding-right: 15px;
}


12. hello/views.py 에서 Django의 일반 ListView 클래스를 가져옵니다. 이 클래스를 사용하여 홈페이지를 구현합니다.

from django.views.generic import ListView


13. 또한 views.py 에서 home 함수를 istView 에서 파생된 HomeListView 라는 클래스로 교체합니다. 이 클래스는 자신을 LogMessage 모델에 연결하고 get_context_data 함수를 구현하여 템플릿에 대한 컨텍스트를 생성합니다.

# Remove the old home function if you want; it's no longer used

class HomeListView(ListView):
    """Renders the home page, with a list of all messages."""
    model = LogMessage

    def get_context_data(self, **kwargs):
        context = super(HomeListView, self).get_context_data(**kwargs)
        return context


14. 앱의 hello/urls.py 에서 데이터 모델을 가져옵니다

from hello.models import LogMessage


15. 또한 hello/urls.py 에서 가장 최근의 LogMessage 객체 5개를 내림차순으로 검색한 다음(데이터베이스를 쿼리함을 의미함) 템플릿 컨텍스트(message_list)의 데이터 이름을 제공하는 새 보기에 대한 변수를 만듭니다. 사용할 템플릿을 식별합니다.

home_list_view = views.HomeListView.as_view(
    queryset=LogMessage.objects.order_by("-log_date")[:5],  # :5 limits the results to the five most recent
    context_object_name="message_list",
    template_name="hello/home.html",
)


16. hello/urls.py 에서 home_list_view 변수를 사용하도록 홈페이지 경로를 수정합니다.

    # Replace the existing path for ""
    path("", home_list_view, name="home"),


17. 앱을 시작하고 브라우저에서 홈 페이지를 열면 이제 메시지가 표시됩니다.



18. 완료되면 앱 중지


끝~~

반응형
Comments