정적 파일 관리하기
- 지금까지 만든 프로젝트 구조에 이제 부트스트랩을 적용시켜 보자!
포스트 목록 페이지에 부트스트랩 적용하기
- blog_list.html 다시 사용하기. 이 내용을 post_list.html에 덮어 씌워준다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog</title>
<link href="bootstrap4/css/bootstrap.min.css" rel="stylesheet" type="text/css">
<script src="https://kit.fontawesome.com/a013733e0e.js" crossorigin="anonymous"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="index.html">Do It Django</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown"
aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item active">
<a class="nav-link" href="index.html">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="./blog_list.html">Blog</a>
</li>
<li class="nav-item">
<a class="nav-link" href="about_me.html">About Me</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown link
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="#">Action</a>
<a class="dropdown-item" href="#">Another action</a>
<a class="dropdown-item" href="#">Something else here</a>
</div>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="#" data-toggle="modal" data-target="#loginModal">Log In</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Modal -->
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-labelledby="logInModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="loginModalLabel"><i class="fas fa-sign-in-alt"></i>  Log In</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<button type="button" class="btn btn-outline-dark btn-block btn-sm "><i
class="fab fa-google"></i>   Log in with Google</button>
<button type="button" class="btn btn-outline-dark btn-block btn-sm "><i
class="far fa-envelope"></i>   Log in with E-mail</button>
</div>
<div class="col-md-6">
<button type="button" class="btn btn-outline-dark btn-block btn-sm"><i
class="far fa-envelope"></i>   Sign Up with E-mail</button>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="container my-3">
<div class="row">
<div class="col-md-8 col-lg-9">
<h1>Blog</h1>
<!-- Blog post-->
<div class="card mb-4">
<a href="#!"><img class="card-img-top" src="https://dummyimage.com/700x350/dee2e6/6c757d.jpg"
alt="..." /></a>
<div class="card-body">
<div class="small text-muted">January 1, 2022</div>
<h2 class="card-title h4">Post Title</h2>
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reiciendis
aliquid atque, nulla.</p>
<a class="btn btn-primary" href="#!">Read more →</a>
</div>
<div class="card-footer text-muted">
Posted on January 1, 2017 by
<a href="#">Start Bootstrap</a>
</div>
</div>
<!-- Blog Post -->
<div class="card mb-4">
<img class="card-img-top" src="http://placehold.it/750x300" alt="Card image cap">
<div class="card-body">
<h2 class="card-title">Post Title</h2>
<p class="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reiciendis
aliquid atque, nulla? Quos cum ex quis soluta, a laboriosam. Dicta expedita corporis animi
vero voluptate voluptatibus possimus, veniam magni quis!</p>
<a href="#" class="btn btn-primary">Read More →</a>
</div>
<div class="card-footer text-muted">
Posted on January 1, 2017 by
<a href="#">Start Bootstrap</a>
</div>
</div>
<!-- Pagination -->
<ul class="pagination justify-content-center mb-4">
<li class="page-item">
<a class="page-link" href="#">← Older</a>
</li>
<li class="page-item disabled">
<a class="page-link" href="#">Newer →</a>
</li>
</ul>
</div>
<div class="col-md-4 col-lg-3">
<!-- Search widget-->
<div class="card mb-4">
<div class="card-header">Search</div>
<div class="card-body">
<div class="input-group">
<input class="form-control" type="text" placeholder="Enter search term..."
aria-label="Enter search term..." aria-describedby="button-search" />
<button class="btn btn-primary" id="button-search" type="button">Go!</button>
</div>
</div>
</div>
<!-- Categories widget-->
<div class="card mb-4">
<div class="card-header">Categories</div>
<div class="card-body">
<div class="row">
<div class="col-sm-6">
<ul class="list-unstyled mb-0">
<li><a href="#!">Web Design</a></li>
<li><a href="#!">HTML</a></li>
<li><a href="#!">Freebies</a></li>
</ul>
</div>
<div class="col-sm-6">
<ul class="list-unstyled mb-0">
<li><a href="#!">JavaScript</a></li>
<li><a href="#!">CSS</a></li>
<li><a href="#!">Tutorials</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Footer-->
<footer class="py-5 bg-dark">
<div class="container">
<p class="m-0 text-center text-white">Copyright © SangHui Website 2022</p>
</div>
</footer>
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js"
integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s"
crossorigin="anonymous"></script>
</body>
</html>
- 결과 화면
- static 폴더 만들고 css 파일 넣기(blog 폴더 아래!)
- post_list.html 수정하기
<!DOCTYPE html>
{%load static%}
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Blog</title>
<link href="{% static 'blog/bootstrap4/bootstrap.min.css'%}" rel="stylesheet" type="text/css">
<script src="https://kit.fontawesome.com/a013733e0e.js" crossorigin="anonymous"></script>
</head>
- 실제 포스트 내용이 표시되도록 수정하기
- post_list.html에 <!--Blog Post --->라고 되있는것중 하나 삭제후 코드를 다음과 같이 수정해 준다.
<h1>Blog</h1>
{% for p in post_list %}
<!-- Blog Post -->
<div class="card mb-4">
<img class="card-img-top" src="http://placehold.it/750x300" alt="Card image cap">
<div class="card-body">
<h2 class="card-title">{{p.title}}</h2>
<p class="card-text">{{p.content}}</p>
<a href="{{p.get_absolute_url}}" class="btn btn-primary">Read More →</a>
</div>
<div class="card-footer text-muted">
Posted on {{p.created_at}} by
<a href="#">작성자명 쓸 위치(개발예정)</a>
</div>
</div>
{%endfor%}
- 그러면 아까 우리가 등록해논대로 목록 제목과 content가 표시된다.
포스트 상세 페이지에 부트스트랩 적용하기
- startboot strap 싸이트에서 무료 템플릿을 다운 받는다.
- Blog Post 디자인을 적용한다.
- post_detail.html을 다음과 같이 수정해준다.
<!DOCTYPE html>
{% load static %}
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>{{ post.title }} - Blog</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="{% static 'blog/bootstrap4/bootstrap.min.css' %}" media="screen">
<!-- Custom styles for this template -->
<link rel="stylesheet" href="{% static 'blog/css/blog-post.css' %}" media="screen">
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
<div class="container">
<a class="navbar-brand" href="#">Start Bootstrap</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive"
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home
<span class="sr-only">(current)</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Services</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
<!-- Page Content -->
<div class="container">
<div class="row">
<!-- Post Content Column -->
<div class="col-lg-8">
<!-- Title -->
<h1 class="mt-4">{{ post.title }}</h1>
<!-- Author -->
<p class="lead">
by
<a href="#">작성자명 쓸 위치(개발예정)</a>
</p>
<hr>
<!-- Date/Time -->
<p>Posted on {{ post.created_at }}</p>
<hr>
<!-- Preview Image -->
<img class="img-fluid rounded" src="http://placehold.it/900x300" alt="">
<hr>
<!-- Post Content -->
<p>{{ post.content }}</p>
<hr>
<!-- Comments Form -->
<div class="card my-4">
<h5 class="card-header">Leave a Comment:</h5>
<div class="card-body">
<form>
<div class="form-group">
<textarea class="form-control" rows="3"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
<!-- Single Comment -->
<div class="media mb-4">
<img class="d-flex mr-3 rounded-circle" src="http://placehold.it/50x50" alt="">
<div class="media-body">
<h5 class="mt-0">Commenter Name</h5>
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio,
vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec
lacinia congue felis in faucibus.
</div>
</div>
<!-- Comment with nested comments -->
<div class="media mb-4">
<img class="d-flex mr-3 rounded-circle" src="http://placehold.it/50x50" alt="">
<div class="media-body">
<h5 class="mt-0">Commenter Name</h5>
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus odio,
vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate fringilla. Donec
lacinia congue felis in faucibus.
<div class="media mt-4">
<img class="d-flex mr-3 rounded-circle" src="http://placehold.it/50x50" alt="">
<div class="media-body">
<h5 class="mt-0">Commenter Name</h5>
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus
odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate
fringilla. Donec lacinia congue felis in faucibus.
</div>
</div>
<div class="media mt-4">
<img class="d-flex mr-3 rounded-circle" src="http://placehold.it/50x50" alt="">
<div class="media-body">
<h5 class="mt-0">Commenter Name</h5>
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin. Cras purus
odio, vestibulum in vulputate at, tempus viverra turpis. Fusce condimentum nunc ac nisi vulputate
fringilla. Donec lacinia congue felis in faucibus.
</div>
</div>
</div>
</div>
</div>
<!-- Sidebar Widgets Column -->
<div class="col-md-4">
<!-- Search Widget -->
<div class="card my-4">
<h5 class="card-header">Search</h5>
<div class="card-body">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search for...">
<span class="input-group-append">
<button class="btn btn-secondary" type="button">Go!</button>
</span>
</div>
</div>
</div>
<!-- Categories Widget -->
<div class="card my-4">
<h5 class="card-header">Categories</h5>
<div class="card-body">
<div class="row">
<div class="col-lg-6">
<ul class="list-unstyled mb-0">
<li>
<a href="#">Web Design</a>
</li>
<li>
<a href="#">HTML</a>
</li>
<li>
<a href="#">Freebies</a>
</li>
</ul>
</div>
<div class="col-lg-6">
<ul class="list-unstyled mb-0">
<li>
<a href="#">JavaScript</a>
</li>
<li>
<a href="#">CSS</a>
</li>
<li>
<a href="#">Tutorials</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Side Widget -->
<div class="card my-4">
<h5 class="card-header">Side Widget</h5>
<div class="card-body">
You can put anything you want inside of these side widgets. They are easy to use, and feature the new
Bootstrap 4 card containers!
</div>
</div>
</div>
</div>
<!-- /.row -->
</div>
<!-- /.container -->
<!-- Footer -->
<footer class="py-5 bg-dark">
<div class="container">
<p class="m-0 text-center text-white">Copyright © Your Website 2020</p>
</div>
<!-- /.container -->
</footer>
<!-- Bootstrap core JavaScript -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
</body>
</html>
- 결과 화면
- 네비게이션 바에 페이지 윗부분이 가려지는 문제 해결하기
- static/blog 아래 다음과 같이 css파일을 하나 생성해준다.
- 적용 결과 화면
미디어 파일 관리하기
포스트에 이미지 올리기
- 이미지 폴더 지정하기
- 프로젝트/settings.py
import os
from pathlib import Path
(생략)
STATIC_URL = 'static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, '_media')
- blog/models.py
from django.db import models
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
head_image = models.ImageField(upload_to='blog/images/%Y/%m/%d/', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'[{self.pk}]{self.title}'
def get_absolute_url(self):
return f'/blog/{self.pk}/'
- Pillow 라이브러리 설치하고 마이그레이션 하기
- 모델을 변경하면 마이그레이션을 해야한다.
- 이미지 업로드 테스트하기
- 저장이 잘 되는것을 확인할 수 있다.
- 미디어 파일을 위한 URL 지정하기
- 장고 어드민 환경에서 저장된 이미지를 클릭해보면 FileNotFound Error가 난다.
- 아직 이미지 URL을 설정해 주지 않았기 때문
- 프로젝트/urls.py파일을 다음과 같이 수정한다.
from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('blog/', include('blog.urls')),
path('admin/', admin.site.urls),
path('', include('single_pages.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
- _media 폴더를 버전 관리에서 제외해준다.
- 포스트 상세 페이지에 이미지를 나타내준다.
- post_detail.html <!---preview image ---> 부분을 수정해준다.
<!-- Preview Image -->
<img class="img-fluid rounded" src="{{post.head_image.url}}" alt="">
포스트에 파일 올리기
- file_upload 필드 만들기
- blog/models.py에 FileField 만들기
from django.db import models
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
head_image = models.ImageField(upload_to='blog/images/%Y/%m/%d/', blank=True)
file_upload = models.FileField(upload_to='blog/files/%Y/%m/%d', blank=True) # 추가된 내용
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'[{self.pk}]{self.title}'
def get_absolute_url(self):
return f'/blog/{self.pk}/'
- 파일 업로드 test
- 잘된다!
'Programming > Django' 카테고리의 다른 글
테스트 주도 개발 적용해보기 (0) | 2023.03.25 |
---|---|
장고(Django) 페이지 구성 개선하기 (0) | 2023.03.19 |
장고(Django) 웹 페이지 만들기 (0) | 2023.03.18 |
장고(django) 프로젝트에서 앱 만들기 (0) | 2023.03.18 |
장고(django) 기초 (0) | 2023.03.18 |