본문 바로가기

Python/Django

[Django] 기존 프로젝트에 장고앱 추가

이번에는 기존 프로젝트에 장고앱을 추가하는 과정을 알아보겠습니다.

템플릿을 만들어, 실제로 템플릿을 렌더링하는 뷰를 만들어, URL에 연결하여, cars용 모델을 만들어보겠습니다.

 

Create Views

Connect with URLs(Routing)

General NavBar

Empty Templates - List, Add, Delete

 

 

기존에 만들어진 프로젝트에 장고앱을 추가하기 때문에 프로젝트 생성 명령어는 생략했습니다.

(django) ~\review_01> python manage.py startapp cars

 

루트 폴더에 templates 폴더를 만들고 base.html 파일을 생성

    CSS bootstrap 및 js 추가, 네비게이션바 추가합니다.

 

앱레벨에 templates 폴더를 만들고 list.html, add.html, delete.html 파일을 생성

 

앱레벨의 views.py 파일 수정 - 상세 로직은 차후 구현, 현재는 render 만 가능한 기본만 구현

 

앱레벨의 urls.py 파일 생성 - app_name 을 선언하고 urlpatterns 추가할 것(name 옵션도 설).

 

프로젝트 레벨의 urls.py 파일 수정.

 

프로젝트 레벨의 settings.py 파일 수정.

    INSTALLED_APPS에 config 정보 추가.

        INSTALLED_APPS = [
            'first_app.apps.FirstAppConfig', # <=== 앱인식을 위한 추가
            'cars.apps.CarsConfig',          # <=== 앱인식을 위한 추가

 

    APP_DIRS 가 True 인지 확인 필수 - 'APP_DIRS': True,

    TEMPLATES 에 DIRS 설정 추가 - 'DIRS': [os.path.join(BASE_DIR,'templates')],

 

모든 html 파일 작성 - 기본 더미 내용만 추가

    base.html

    list.html, add.html, delete.html

 

 

여기까지는 models 이 없기때문에 migration 이 필요 없습니다.

 

 


 

여기부터는 models 을 추가할 예정이므로 migration 과정이 필요합니다. 아래 상세내용 참고하세요.

 

Create Model for Cars

Add functionality to Views connecting to Model

Create HTML forms to send information back to the Views

TestCRUD functionality

 

 

앱레벨의 ./review_01/cars/models.py 수정

 

from django.db import models

# Create your models here.
class Car(models.Model):
    # pk 
    brand = models.CharField(max_length=30) 
    year = models.IntegerField() 

    def __str__(self):
        return f"[PK: {self.id}] Car is {self.brand} {self.year}"

 

 

makemigrations - python manage.py makemigrations cars

 

(django) D:\workspace\Python\Django\DJANGO4\DJANGO_COURSE_V2\review_01>python manage.py makemigrations cars
Migrations for 'cars':
  cars\migrations\0001_initial.py
    - Create model Car

(django) D:\workspace\Python\Django\DJANGO4\DJANGO_COURSE_V2\review_01>

 

 

migrate - python manage.py migrate

 

(django) D:\workspace\Python\Django\DJANGO4\DJANGO_COURSE_V2\review_01>python manage.py migrate            
Operations to perform:
  Apply all migrations: admin, auth, cars, contenttypes, first_app, sessions
Running migrations:
  Applying cars.0001_initial... OK

(django) D:\workspace\Python\Django\DJANGO4\DJANGO_COURSE_V2\review_01>

 

 

views.py - ./review_01/cars/views.py 수정

 

from django.shortcuts import render,redirect 
from django.urls import reverse 
from . import models

# Create your views here.
def list(request):
    all_cars = models.Car.objects.all()
    context = {'all_cars':all_cars}

    return render(request,'cars/list.html', context=context) #

def add(request):
    if request.POST:
        brand = request.POST['brand']
        year = int(request.POST['year'])
        models.Car.objects.create(brand=brand,year=year)
        # if user submitted new car ---> List.html
        return redirect(reverse('cars:list')) # <=== 앱레벨의 urls.py 에서 app_name, name 와 관련됨
    else:
        return render(request,'cars/add.html')

def delete(request):
    if request.POST:
        # delete the car
        pk = request.POST['pk']
        try:
            models.Car.objects.get(pk=pk).delete()
            return redirect(reverse('cars:list'))
        except:
            messages.warning(request, "해당 PK[{}]가 없습니다.".format(pk))
            print('pk not found!')
            # return redirect(reverse('cars:list'))
            return redirect(reverse('cars:delete'))
    else:
        return render(request,'cars/delete.html')

 

base.html - ./review_01/templates/base.html

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- CSS only -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <!-- JavaScript Bundle with Popper -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <title>Cars</title>
</head>
<body>
  <!-- NAVBAR -->
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container-fluid"> 
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
        <div class="navbar-nav"> 
          <a class="nav-link" href="{% url 'cars:list' %}">LIST</a>
          <a class="nav-link" href="{% url 'cars:add' %}">ADD</a> 
          <a class="nav-link" href="{% url 'cars:delete' %}">DELETE</a> 
        </div>
      </div>
    </div>
  </nav>    
  {%block content%}
  {%endblock%}
</body>
</html>

 

list.html - ./review_01/cars/templates/cars/list.html

 

{% extends "base.html" %}

{% block content %}
<div class='container'>
    <h1>LIST.HTML</h1>
        <ul>
            {% for car in all_cars%}
                <li>{{car}}</li>
            {% endfor %}
        </ul>
</div>
{% endblock %}

 

add.html - ./review_01/cars/templates/cars/add.html

 

{% extends "base.html" %}

{% block content %}
<div class='container'>
    <h1>ADD.html</h1>
    <h2>Add a new car to the database:</h2>
    <br>
    <form action="" method='POST'>
        {% csrf_token %}
        <div  class="form-group">
            <label for="brand">Brand:</label>
            <input class="form-control" type="text" id='brand' name='brand'>
        </div>
        <br>
        <div  class="form-group">
            <label for="year">Year:</label>
            <input class="form-control" type="text" is='year' name='year'>
        </div>
        <br>
        <input class='btn btn-primary' type="submit">
    </form>

</div>
{% endblock %}

 

delete.html - ./review_01/cars/templates/cars/delete.html

 

{% extends "base.html" %}

{% block content %}
<div class='container'>
    <h1>DELETE.HTML</h1>
    <h2>Enter pk to delete car!</h2>
    <br>
    <form action="" method='POST'>

        {% csrf_token %}
            <div class='form-group'>
                <label for="pk">PK Number:</label>
                <input class='form-control' type="text" id='pk' name='pk'>
            </div>
            <br>
            <input class='btn btn-primary' type="submit">

    </form>

    {% for message in messages %}
        <div class="alert {{ message.tags }} alert-auto-dismissible alert-dismissible notification-container text-center" role="alert">
            {{ message }}
        </div>
    {% endfor %}    

</div>
{% endblock %}

 

 

 

최종 화면