Django 자습서 #6: 홈 페이지

이 자습서의 소스 코드를 다운로드할 수 있습니다.
Download the Source Code
이 글에서부터 우리는 우리가 배운 Django에 관한 지식을 현실 생활에 응용하기 시작할 것이다.너희들을 압도하지 않기 위해서 우리는 더욱 간단한 일부터 시작할 것이다.본문에서, 우리는 홈페이지를 하나만 만들 것이다.이 홈페이지는 매우 간단할 것이다. 우리는 로고, 사이트 이름과 설명이 필요하다.그러나 이 예를 통해 모델, 보기, 템플릿 층이 어떻게 협동적으로 작동하는지 정확하게 볼 수 있습니다.
다음 사항은 빠른 알림으로 새 Django 프로젝트를 만드는 방법입니다.
python -m pip install Django
django-admin startproject example
cd example
python manage.py startapp blog
본 논문(https://www.ericsdevblog.com/index.php/2022/01/django-tutorial-1-setup-the-project/)에서 논의한 바와 같이 설정 파일(settings.py)에 필요한 변경 사항을 기억하세요.

모델 레이어
이제 모델층부터 시작합시다.우리는 하나의 홈페이지만 구축하기 때문에 모든 데이터를 하나의 모델로 저장할 수 있다. 우리는 home이라고 부른다.이 모델에서 우리는 세 개의 필드가 필요하다. 그것이 바로 title, descriptionlogo이다.
from django.db import models

class Home(models.Model):
    title = models.CharField(max_length=255)
    description = models.TextField()
    logo = models.ImageField(upload_to='uploads/images/logo')
logoImageField입니다.이 필드는 이미지 위치를 가리키는 경로를 저장하고 upload_to 속성으로 정의한 열을 데이터베이스에 생성합니다.잠시 후 어떻게 일을 하는지 보실 수 있습니다.
또한 ImageField을 사용하려면 Pillow 패키지를 설치해야 합니다.패키지를 설치하지 않은 경우 패키지를 설치하는 방법은 다음과 같습니다.
python -m pip install --upgrade pip
python -m pip install --upgrade Pillow
그런 다음 마이그레이션 파일을 생성하여 데이터베이스에 적용할 수 있습니다.
python manage.py makemigrations
python manage.py migrate
이것이 바로 데이터베이스의 외관이다.logo열의 유형은 VARCHAR입니다. 이것은 문자열이어야 한다는 것을 의미합니다.


보기, 템플릿 및 URL
다음은 보기와 템플릿을 처리할 때입니다.홈페이지를 만드는 데 몇 개의 보기와 템플릿이 필요한지 먼저 스스로에게 물어보자.
앞서 언급한 바와 같이 웹 개발 분야에는 CRUD(창설, 읽기, 업데이트와 삭제)라는 작업이 있다.기본적으로 우리는 사용자가 데이터베이스 테이블의 항목을 조회하고 항목의 상세한 정보를 읽으며 새로운 항목을 만들고 이를 데이터베이스에 저장하며 항목을 업데이트할 수 있도록 확보해야 한다. 물론 항목도 삭제할 수 있다.
완전한 CRUD 작업을 생성하려면 최소 7개의 뷰 함수가 필요합니다.
  • index() - 항목 목록을 표시합니다.
  • show(id) - 지정된 항목을 표시합니다.
  • create() - 새 프로젝트를 만드는 데 사용할 양식을 표시합니다.
  • store(request) - 새로 만든 항목을 데이터베이스에 저장합니다.
  • edit(id) - 지정된 항목을 편집하는 데 사용되는 양식을 표시합니다.
  • update(request, id) - 데이터베이스에서 지정된 항목을 업데이트합니다.
  • destroy(id) - 데이터베이스에서 지정한 항목을 삭제합니다.
  • 저희 홈페이지에 대해 index()을 필요로 하지 않습니다. 데이터베이스에 하나의 항목만 있기 때문에 edit()update()을 토론하지 않습니다. 왜냐하면 그들은 기본적으로 create()store()과 같기 때문입니다.
    템플릿에 대해, 우리는 표를 표시하기 위해 create.html페이지가 필요합니다. 우리는 그것을 사용하여 새로운 Home을 만들 수 있습니다.새 success.html페이지를 성공적으로 만들었거나 삭제했음을 알려 주는 Home 페이지마지막으로 홈 페이지의 home.html페이지를 표시합니다.

    만들다
    그럼, 페이지를 만드는 것부터 시작합시다.layout.htmlcreate.html 파일이 필요합니다.나는 모든 템플릿을 templates 디렉터리에 두었다.settings.py 파일의 해당 설정을 변경한 것을 기억하십시오.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
    
        {% block meta %} {% endblock %}
    
        <!-- Bootstrap -->
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"
            integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    </head>
    
    <body>
        <!-- Responsive navbar-->
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <div class="container">
                <a class="navbar-brand" href="#">{{ title }}</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse"
                    data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
                    aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
                        <li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
                        <li class="nav-item"><a class="nav-link" href="#">Link</a></li>
                        <li class="nav-item dropdown">
                            <a class="nav-link dropdown-toggle" id="navbarDropdown" href="#" role="button"
                                data-bs-toggle="dropdown" aria-expanded="false">Dropdown</a>
                            <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                                <li><a class="dropdown-item" href="#">Action</a></li>
                                <li><a class="dropdown-item" href="#">Another action</a></li>
                                <li>
                                    <hr class="dropdown-divider" />
                                </li>
                                <li><a class="dropdown-item" href="#">Something else here</a></li>
                            </ul>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
        <!-- Page content-->
        <div class="container">
            {% block content %} {% endblock %}
        </div>
        <!-- Bootstrap core JS-->
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous">
        </script>
    </body>
    
    </html>
    
    {% extends 'layout.html' %}
    
    {% block meta %}
    <meta name="description" content="{{ title }}" />
    <title>{{ title }}</title>
    {% endblock %}
    
    {% block content %}
    <br>
    <form action="/save/" method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <div class="mb-3">
            <label for="inputTitle" class="form-label">Website Title</label>
            <input type="text" class="form-control" id="inputTitle" name="title">
        </div>
        <div class="mb-3">
            <label for="inputDescription" class="form-label">Website Description</label>
            <textarea type="text" class="form-control" id="inputDescription" name="description"></textarea>
        </div>
        <div class="mb-3">
            <label for="inputLogo" class="form-label">Choose a logo</label>
            <input type="file" class="form-control" id="inputLogo" name="logo">
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
    {% endblock %}
    
    이 표에서 우리는 세 가지 일을 토론해야 한다.
    우선 10행에서 action 속성은 Submit 단추를 눌렀을 때 브라우저가 요청할 URL을 정의합니다.method 속성은 이 HTTP 요청 방법을 정의했고 우리의 예는 POST이다.enctype 속성은 데이터의 암호화 방식을 정의합니다. 왜냐하면 우리는 이미지 파일을 업로드하고 있기 때문입니다. multipart/form-data은 우리의 유일한 옵션입니다.다른 옵션에 관심이 있다면 본문(https://www.w3schools.com/tags/att_form_enctype.asp)을 읽어 보십시오.
    둘째, 14, 18, 22줄.모두 name 속성이 있습니다.이것은 매우 중요합니다. 우리는 그것을 사용하여 상응하는 사용자 입력을 검색할 것입니다. 우리는 뒤에서 토론할 것입니다.
    마지막으로 단추의 유형은 submit이어야 합니다. 그렇지 않으면 폼이 아무런 역할을 하지 않습니다.
    다음은 상응하는 보기를 만듭니다.create()페이지를 표시하는 create.html 방법이 필요합니다.
    from django.shortcuts import render
    from blog.models import Home
    
    def create(request):
    
        return render(request, 'create.html', {
            'title': "Create a new Home",
        })
    
    create()은 비교적 간단합니다.템플릿에 title 변수를 전달하기만 하면 됩니다.

    구원하다
    페이지를 저장하려면 데이터가 저장되어 있음을 알려주는 success.html페이지가 필요합니다.
    {% extends 'layout.html' %}
    
    {% block meta %}
    <meta name="description" content="{{ description }}" />
    <title>{{ title }}</title>
    {% endblock %}
    
    {% block content %}
    <div class="text-center mt-5">
        <h1>Success!</h1>
    </div>
    {% endblock %}
    
    def save(request):
        home = Home(
            title = request.POST.get('title', ''),
            description = request.POST.get('description', ''),
            logo = request.FILES['logo'],
        )
    
        home.save()
    
        return render(request, 'success.html', {
            'title': "Success",
            'description': "Successfully Saved"
        })
    
    save() 보기에서 두 번째 줄부터 여섯 번째 줄까지 우리는 Home의 새로운 실례를 만들었다. 우리의 Home 모델은 세 가지 속성을 가지고 있어야 한다는 것을 기억해 주십시오. title, descriptionlogo이다.
    3행 request.POST.get('title', '')은 HTTP POST 요청의 주체에 액세스하는 방법입니다.get() 방법은 두 가지 파라미터가 있는데 첫 번째 파라미터는 'title'이고 우리가 방금 언급한 name 속성의 값과 일치한다.두 번째 매개 변수는 기본값이며 사용자가 입력한 값이 비어 있으면 기본값(빈 문자열 '')이 지정됩니다.
    5행 request.FILES['logo']은 이미지 파일을 저장하는 방법입니다.Django에서는 업로드된 파일을 처리하는 것이 좀 까다롭다.우리는 settings.py 파일에 약간의 내용을 추가해야 한다.
    import os
    
    MEDIA_ROOT =  os.path.join(BASE_DIR, 'media')
    MEDIA_URL = '/media/'
    
    이 코드는 Django가 업로드한 미디어 파일을 어디에 두었는지, 이 파일에 접근하려고 시도할 때 사용하는 URL을 알려 줍니다.우리의 예에서 미디어 파일은 media 디렉터리에 놓일 것이다.
    현재, 그림을 올릴 때, 이 그림 파일은 media/uploads/images/logo 디렉터리에 저장됩니다. 저희 모델에 정의된 대로.이미지 파일을 가리키는 경로가 데이터베이스에 저장됩니다.
    URL dispatchers 추가:
    from blog import views
    from django.urls import path
    
    urlpatterns = [
        ...
        path('create/', views.create),
        path('save/', views.save),
    ]
    
    http://127.0.0.1:8000/create/으로 이동하여 페이지를 만들고 저장하는 것을 테스트할 수 있습니다.



    나타내다
    지금 페이지를 보여주는 것은 너에게 매우 간단할 것이다.우선, 우리는 home.html 문건이 필요하다.
    {% extends 'layout.html' %}
    
    {% block meta %}
    <meta name="description" content="{{ description }}" />
    <title>{{ title }}</title>
    {% endblock %}
    
    {% block content %}
    <div class="text-center mt-5">
        <img src="{{ logo }}" width="200px">
        <h1>{{ title }}</h1>
        <p>{{ description }}</p>
    
        <form action="/delete/" method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <button type="submit" class="btn btn-danger">Delete Home</button>
        </form>
    
    </div>
    {% endblock %}
    
    기능을 보려면 다음과 같이 하십시오.
    def show(request):
        home  = Home.objects.first()
    
        title = home.title
        description = home.description
        logo = home.logo.url
    
        return render(request, 'home.html', {
            'title': title,
            'description': description,
            'logo': logo,
        })
    
    6행 home.logo.url에서는 템플릿에서 직접 사용할 수 있도록 이미지에 대한 URL을 검색합니다.
    사이트 주소:
    path('', views.show),
    
    그러나 http://127.0.0.1:8000/으로 이동하면 이미지 파일이 불러오지 않았지만 링크가 정확한 위치를 가리키는 것을 알 수 있습니다.기본적으로 Django는 미디어 파일을 제공하지 않기 때문에 이 점을 바꾸려면 url.py 파일에 다른 줄을 추가해야 합니다.
    from django.conf import settings
    from django.conf.urls.static import static
    
    urlpatterns = [
        ...
    ]
    
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    
    이제 브라우저를 새로 고칩니다. 모든 것이 정상입니다.이것이 바로 우리가 개발 환경에서 중간 문서를 위해 서비스를 제공하는 방식이라는 것을 명심하십시오. 생산 환경에서 우리는 반드시 다른 일을 해야 합니다. 이것은 장래에 토론할 것입니다.

    삭제home.html 파일에는 URL /delete/을 가리키는 또 다른 양식이 있습니다.이것은 우리로 하여금 본문의 마지막 부분으로 들어가 보기를 삭제하도록 인도할 것이다.시간을 절약하기 위해서, 우리는 같은 success.html 파일을 사용하지만, 실제 응용 프로그램에서는 다른 템플릿을 사용해야 할 수도 있습니다.
    def delete(request):
        home  = Home.objects.first()
    
        home.delete()
    
        return render(request, 'success.html', {
            'title': "Success",
            'description': "Successfully Deleted"
        })
    
    이 뷰를 실행하면 Home 모델에서 첫 번째 레코드를 찾아 삭제합니다.

    좋은 웹페이지 즐겨찾기