반응형
  • Template 만들기
  • 사진이 화면에 업로드 할 수 있도록 만들기

<Template 만들기>

1. 템플릿 만들기

  • photo/templates/photo 폴더 생성

    • 그 아래에 html 파일들 생성해주기

    • 많은 앱들 생성 시, 겹치는 문제 해결 위해 photo 폴더를 다시 생성해주고 html 파일 생성

  • photo/layout 폴더 생성

    • 그 아래에 layout.html 파일 생성

    • 모든 html 파일 안에 들어갈 base가 될 layout.html 생성

    •  setting에 templates 경로에 layout 경로 찾을 수 있도록 지정 

layout/base.html 경로

/instagram/config/settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'layout')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

 

 

<Bootstrap 사용>

  1. Bootstrap · The most popular HTML, CSS, and JS library in the world. 에 접속합니다.

  2. base.html 파일에 부트스트랩을 사용하기 위해 필요한 css 및 javascript 링크를 넣습니다.

    1. css 파일은 head의 마지막에 위치

    2. javascript 파일은 body의 마지막에 위치

#css 
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> 

#javascript

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

  3. 마음에 드는 포맷을 찾으면 해당 포맷을 적용할 html에 넣어줍니다.

  • 지금은 base.html에 넣어줍니다.(body tag내 위치)

  • 파일들을 적절하게 수정하고 클릭시 연결할 링크를 연결해줍니다.

    1. <a href = " " > 내 위치

    2. { url 'photo:index' } 등과 같이 연결

  • block content를 만들어서 다른 템플릿에서 추가할 수 있도록 구성합니다.

  • Home / 사진 올리기

  • 아래쪽에 { block content } { endblock } 을 구성

  • Dstagram 제목 설정 및 Home, 사진 올리기 url 연결하기

/photo/layout/base.html

<!DOCTYPE html>
<html lang = "en">


<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}</title>

    #css 
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> 

</head>

<body>

#navbar
<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">Dstagram</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-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 mr-auto">
        <li class="nav-item active">
          <a class="nav-link" href="{% url 'photo:index' %}">Home<span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="{% url 'photo:create'%}">사진 올리기</a>
        </li>
      </ul>
      <form class="form-inline my-2 my-lg-0">
        <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
        <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
      </form>
    </div>
  </nav>

  {%block content%}

  {% endblock %}

  #javascript bootstrap
  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

</body>



</html>

 

<Photo 템플릿 수정>

/photo/templates/photo/photo_list.html

  • for문으로 models를 통해 생성된 object의 list를 하나씩 

  • img의 경로는 image.url 을 통해 연결

{% extends 'base.html' %}
{% block title %}
{% endblock %}

{% block content %}

<div class='container'>
    <div class="row">
        <div class="col"></div>
        <div class="col-5">
            {% for object in object_list %}

            <div class="card">
                <div class="card-header">
                    {{ object.author }}
                </div>
                <img src=" {{ object.image.url }}" class="card-img-top" alt="...">
                <div class="card-body">
                    <p class="card-text"> {{ object.text }} </p>
                </div>
                <ul class="list-group list-group-flush">
                    <li class="list-group-item">생성일 : {{ object.created }}</li>
                    <li class="list-group-item">수정일 : {{ object.updated }}</li>
                </ul>
                <div class="card-body">
                    <a href="{% url 'photo:detail' object.id %}" class="card-link">댓글달기</a>
                    <a href="{% url 'photo:update' object.id %}" class="card-link">수정하기</a>
                    <a href="{% url 'photo:delete' object.id %}" class="card-link">삭제하기</a>

                </div>

            </div>
            {% endfor %}
        </div>

        <div class = "col"></div>
    </div>
</div>
{% endblock %}

 

/photo/templates/photo/photo_create.html

  • form을 활용하여 입력창 생성

  • post형식으로 전송

  • { csrf_token }을 작성하여 보안문제 해결

  • {{ form.as_p }} 를 적어줌으로서 한줄씩 띄우면서 create의 field에 등록된 것을 가지고 옴

- html의 폼형태에서 입력할 때는 모두 text 파일로 인식 ->  따라서 form에 image 파일이라는 것을 인식시켜줌!

 

{% extends 'base.html' %}
{% block content %}
<div class="row">
    <div class="col"></div>
    <div class="col-12 col-xl-8 col-md-8">
        <div class="alert alert-primary" role="alert">
            모든 부분을 다 채워넣어주세요!!
        </div>
        <form action="" method="post" enctype='multipart/form-data'>
            {% csrf_token %}

            {{form.as_p}}
            <input type="submit" value="Upload" class="btn btn-primary">
        </form>
    </div>
    <div class="col"></div>
</div>
{% endblock %}

 

 

/photo/templates/photo/photo_detail.html

  • 해당 컨텐츠의 작성자 / text를 보여준다.

  • 수정과 삭제를 할 수 있도록 링크 연결

{% extends 'base.html' %}
{% block title %}
{% endblock %}

{% block content %}
<div class="row">
    <div class="col"></div>
    <div class="col-12 col-xl-4 col-md-4">
        <div class="card" style="">
            <img src=" {{ object.image.url }}" class="card-img-top" alt="...">
            <div class="card-body">

                <h5 class="card-title">{{ object.author }}</h5>
                <p class="card-text"> {{ object.text }} </p>
            </div>
            <div class="card-body">
                <a href="{% url 'photo:update' object.id %}" class="card-link">수정하기</a>
                <a href="{% url 'photo:delete' object.id %}" class="card-link">삭제하기</a>
            </div>
        </div>
    </div>

    <div class="col"></div>
</div>
{% endblock %}

 

 

/photo/templates/photo/photo_delete.html

  • form 형식으로 구현

  • 한번 더 실제로 지울지를 확인하는 페이지로 구성

  • form 을 다시 보여줄 필요는 없다

{% extends 'base.html' %}
{% block content %}

<div class="alert alert-primary" role="alert">
  진짜로 {{object}}를 지우실 건가요?
</div>

<form action="" method ="post">
    {% csrf_token%}
    <input type="submit" value="Delete OK">
</form>
{% endblock %}

 

 

/photo/templates/photo/photo_update.html

  • create와 비슷하게 구현

  • 폼 형태로 입력할 수 있도록 구현

{% extends 'base.html' %}
{% block content %}
<div class="row">
    <div class="col"></div>
    <div class="col-12 col-xl-8 col-md-8">
        <form action="" method="post">
            {% csrf_token %}
            {{form.as_p}}
            <input type="submit" value="Create">
        </form>
    </div>
    <div class="col"></div>
</div>
{% endblock %}

 

 

 

<화면에 사진 업로드 할 수 있도록 만들기>

- photo을 생성하는데 user_id가 확인되어야 하므로 views.py 수정

/photo/views.py

class PhotoCreate(CreateView):
    model = Photo
    fields = ['text', 'image']
    template_name_suffix = '_create'
    success_url = '/'


    def form_valid(self, form):
        form.instance.author_id = self.request.user.id
        if form.is_valid():
            form.instance.save()
            return redirect('/')
        else:
            # 올바르지 않다면
            return self.render_to_response({'form': form})

 

- 메인 화면에 사진이 오류가 뜸

  1. static으로 url 지정
  2. photo/urls.py 수정
urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

 

 

아래와 같이 나온다면 성공!

 

반응형

'Web > Django' 카테고리의 다른 글

[Django] Instagram 클론 코딩(5)  (0) 2020.03.26
[Django] Instagram 클론 코딩(4)  (0) 2020.03.25
[Django] Instagram 클론 코딩(2)  (0) 2020.03.19
[Django_심화]4 - (1)pagination  (0) 2020.03.18
[Django] Instagram 클론 코딩(1)  (0) 2020.03.17
반응형
https://github.com/syujisu/Django_instagram

 

초기 설정

photo app 생성

모델 설계

<초기 설정>

- 가상환경 생성
$ python -m venv myvenv

- 가상환경 실행
$ source myvenv/Scripts/activate
(myvenv) 

 

-장고 설치 
$ pip install django 

 

- 프로젝트 시작
$ django-admin startproject config
(myvenv) 


- DB 초기화 (project 상단 이름을 바꿔줍니다 -> instagram)

$ cd instagram

$ python manage.py migrate

 

 

 

<photo app>

- app 생성(/instagram)

$ python manage.py startapp photo

 

- settings.py에 installed app에 photo 추가해주기

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'photo.apps.PhotoConfig'
]

 

- photo model 생성(/instagram/photo/models.py)

class Photo(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user')
    #장고에서 구현하는 user 불러와 photo를 fk로 연결
    text = models.TextField(blank=True)
    image = models.ImageField(upload_to = 'timeline_photo/%Y/%m/%d')
    #timeline_photo 폴더에 연, 월, 일 만들어 사진 저장
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return "text : " + self.text
        #admin 사이트 화면 표시 구현 

    class Meta:
        ordering = ['-created']
        #ordering 정렬

 

-settings.py 에서 media 루트 설정 (/instagram/config/settings.py)

STATIC_URL = '/static/'



MEDIA_URL = '/res/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
#MEDIA_URL 을 설정하고 ROOT를 잡아주어서 저기로 사진이 저장되도록 한다.

 

-모델 설계 이후 migration

  1. Image파일을 업로드 하기 위해 pip install Pillow를 해줘야 한다.
    1. pip install Pillow
  2. python manage.py makemigrations photo
  3. python manage.py migrate

-admin site 등록(/instagram/photo/admin.py)

from django.contrib import admin
from .models import Photo
# Register your models here.

admin.site.register(Photo)

 

- 확인해보기

$ python manage.py createsuperuser
Username (leave blank to use 'user'): admin
Email address: 282532@naver.com
Password: 
Password (again):
This password is too short. It must contain at least 8 characters.
This password is too common.
This password is entirely numeric.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
  1. python manage.py runserver (기본값은 8000 포트 입니다)
  2. 해당 링크의 /admin으로 이동하여 글 등록해보기

admin 사이트
사진 올려서 이렇게 나오면 완성 :)

반응형

'Web > Django' 카테고리의 다른 글

[Django] Instagram 클론 코딩(2)  (0) 2020.03.19
[Django_심화]4 - (1)pagination  (0) 2020.03.18
[Django_심화]3 - viewset & router  (2) 2019.11.03
[Django_심화]2 - Rest, Serializer  (0) 2019.11.03
[Django_심화]1 - 준비운동  (0) 2019.11.02

+ Recent posts