Django
20210206_Django 태그 기능, get_or_create, ManyToManyField, 배포(pythonanywhere)
Django 게시판 기능 보완
- 글 목록에서 제목 눌러서 글 보기 창 들어가기 (연결)
- table요소의 열 태그인
tr태그
에onclick
으로 연결해 주었고 - 추가적으로 포인터가 있으면 좋을 것 같아서
role="button"
을 통해서 마우스를 올리면 손가락 표시가 나타나게 하였다.
- table요소의 열 태그인
{% raw %}
{% extends "base.html" %}
{% block contents %}
<div class="row mt-5">
<div class="col-12">
<table class="table table-light">
<thead class="thead-light">
<tr>
<th>#</th>
<th>제목</th>
<th>아이디</th>
<th>일시</th>
</tr>
</thead>
<tbody class="text-dark">
{% for board in boards %}
<tr role="button" onclick="location.href='/board/detail/{{ board.id }}/'">
<th>{{ board.id }}</th>
<td>{{ board.title }}</td>
<td>{{ board.writer }}</td>
<td>{{ board.registered_dttm }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="row mt-2">
<div class="col-12">
<nav>
<ul class="pagination justify-content-center">
{% if boards.has_previous %}
<li class="page-item">
<a href="?p={{ boards.previous_page_number }}" class="page-link">이전으로</a>
</li>
{% else %}
<li class="page-item disabled">
<a href="#" class="page-link">이전으로</a>
</li>
{% endif %}
<li class="page-item active">
<a href="#" class="page-link">{{ boards.number }}/{{ boards.paginator.num_pages}}</a>
</li>
{% if boards.has_next %}
<li class="page-item">
<a href="?p={{ boards.next_page_number }}" class="page-link">다음으로</a>
</li>
{% else %}
<li class="page-item disabled">
<a href="#" class="page-link">다음으로</a>
</li>
{% endif %}
</ul>
</nav>
</div>
</div>
<div class="row mt-1">
<div class="col-2">
<buttton class="btn btn-primary btn-block" onclick="location.href='/board/write/'">글쓰기</buttton>
</div>
<div class="col-2">
<buttton class="btn btn-primary btn-block" onclick="location.href='/'">홈</buttton>
</div>
</div>
{% endblock %}
{% endraw %}
Django 태그 만들기
- model에서 게시글 구현을 위해서 user(writer) 와 board의 관계는 1:N 으로
ForeignKey()
를 사용하여 관계를 맺었음 - 태그 기능은 M:N 관계로 하나의 태그가 여러글에 들어갈수 있고 한개의 글에 여러개의 태그가 들어갈 수 있음
태그 app 만들기
django-admin startapp 앱이름
orpython manage.py startapp 앱이름
태그 model 만들기
from django.db import models
# Create your models here.
class Tag(models.Model):
name = models.CharField(max_length=32, verbose_name='태그명')
registered_dttm = models.DateTimeField(
auto_now_add=True, verbose_name="등록시간")
def __str__(self):
return self.name
class Meta:
db_table = 'slowbuscamp_tag'
verbose_name = '슬로우버스캠프 태그'
verbose_name_plural = '슬로우버스캠프 태그'
태그 admin 만들기
- model 가져오는것 잊지 말자!
from django.contrib import admin
from .models import Tag # 주의!
# Register your models here.
class TagAdmin(admin.ModelAdmin):
list_display = ('name', 'registered_dttm')
admin.site.register(Tag, TagAdmin)
settings에 태그 app 추가
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'board',
'sl_user',
'tag'
]
게시판 모델(board 모델) 수정하기
- 게시판 모델에도 태그정보가 들어가기 때문에 사용하기 위해서
- 다대다 관계 구현을 위한
ManyToManyField
를 사용함
from django.db import models
# Create your models here.
class Board(models.Model):
title = models.CharField(max_length=128, verbose_name='제목')
contents = models.TextField(verbose_name='내용')
writer = models.ForeignKey(
'sl_user.Sl_user', on_delete=models.CASCADE, verbose_name='작성자')
# on_delete=models.CASCADE 는 models의 key가 삭제 되면 해당 모델도 지우겠다.
tags = models.ManyToManyField('tag.Tag', verbose_name='태그')
registered_dttm = models.DateTimeField(
auto_now_add=True, verbose_name='등록시간')
def __str__(self):
return self.title
class Meta:
db_table = ' slowbuscamp_board'
verbose_name = '슬로우버스캠프 게시글' # 기본적으로 복수형을 지원하기 때문에 s가 자동으로 붙게 되어 있음
verbose_name_plural = '슬로우버스캠프 게시글' # 복수형이름을 따로 지정하여 자동으로 붙는 s를 제거 가능
태그 migrations, migrate 하기
python manage.py migrations
,python manage.py migrate
게시글 보기 화면에 태그 구현
board_detail.html
- 어차피 모델에서 따오면 되기 때문에 view에서 board를 모델로 지칭하고 있기 때문에
board
를 사용 - 대신 태그 필드(
ManyToManyField
)의 경우 필드 특성상 그냥으로는 안되고 all함수를 이용해야 QuerySet이 된다. 이를 통해 for문과 활용될수 있다. - ManyToManyField
|join:'문자'
를 통해서 각 요소들을 구분해주는 문자를 join을 통해 지정할수 있다.
{% raw %}
{% extends "base.html" %}
{% block contents %}
<div class="row mt-5">
<div class="col-12">
<div class="form-group">
<label for="title">제목</label>
<input type="text" class="form-control" id="title" value="{{ board.title }}" readonly>
<label for="contents">내용</label>
<textarea class="form-control" readonly>{{ board.contents }}</textarea>
<label for="tags">태그</label>
<span class="form-control" id='tags'>
{{ board.tags.all|join:", " }}
<!-- {% for tag in board.tags.all %}
{{ tag.name }}
{% endfor %} -->
</span>
</div>
<button class="btn btn-primary" onclick="location.href='/board/list/'">목록</button>
</div>
</div>
{% endblock %}
{% endraw %}
글쓰기 화면에 태그 구현
쭉 쓰면 ,를 구분자로 하여 tag를 인식하고 tag가 기존에 있던것이면 그냥 저장하고, tag가 기존에 없던 것이라면 만들고 저장하게 함
board_wrtie.html
의 경우 form형식을 사용함form 수정
- tags로 form필드 추가, 입력은 없어도 있어도 상관 없으므로
required=False
설정
- tags로 form필드 추가, 입력은 없어도 있어도 상관 없으므로
from django import forms
# 입력 받을 값은 제목과 내용 두개
class BoardForm(forms.Form):
title = forms.CharField(error_messages={
'required': '제목을 입력해 주세요.'
}, max_length=128, label="제목")
contents = forms.CharField(error_messages={
'required': '내용을 입력해 주세요.'
}, widget=forms.Textarea, label="내용")
tags = forms.CharField(required=False, label="태그")
- view 수정
- 기능 구현을 하기 위해서(있는거 없는거 구분해서)
- 주의할점은 필드 특성상 태그는 모델이 만들어져서 db에 저장이 되어야 태그데이터를 추가가능하다.
- get_or_create()함수 : 데이터 중복 방지시 좋음
def board_write(request):
if not request.session.get('user'):
return redirect('/sl_user/login/')
if request.method == "POST":
form = BoardForm(request.POST)
if form.is_valid():
user_id = request.session.get('user')
sl_user = Sl_user.objects.get(pk=user_id)
tags = form.cleaned_data['tags'].split(',')
# 입력 받아 타당하게 저장된 tag 값들을 ','로 구분해서 tags변수에 할당
board = Board()
board.title = form.cleaned_data['title']
board.contents = form.cleaned_data['contents']
board.writer = fcuser
board.save()
for tag in tags: # tags안에 있는 값들을 하나씩 꺼내서
if not tag:
continue
# Tag models에 있는 model중 name필드 값이 입력받은 tag와 같은 값을 가져오고, 없다면 모델에 만들어라 (create 데이터는 _을 통해 안받음)
_tag, _ = Tag.objects.get_or_create(name=tag)
board.tags.add(_tag) # 해당 태그들을 board 모델의 tags필드를 트리거함
return redirect('/board/list/')
else:
form = BoardForm()
return render(request, 'board_write.html', {'form': form})
배포
배포 django 설정
- DEBUG 모드 해제
- HOST 주소 설정
- STATIC 설정
- STATIC_ROOT는 해당 자료가 수집되는 곳을 알려주는 것임
import os
from pathlib import Path
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False # 화면에 개발할때 필요한 정보들을 보여주는지 설정
# pythonanywhere에서 가입한 id 적어주기 또는 주소, 다른 주소로 접속하는 것을 막는 역할
ALLOWED_HOSTS = [
'raccooncode96.pythonanywhere.com'
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = '/static/'
# STATICFILES_DIRS = [
# os.path.join(BASE_DIR, 'static')
# ]
# BASE_DIR 이 프로젝트 폴더를 의미, 프로젝트 폴더의 static 폴더
# 다른 곳에서 받아 올 것이기 때문에
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
Python anywhere 호스팅 설정
- python anywhere 가입
Python anywhere files
- 프로젝트 파일을 압축하여 python anywhere에 files들어가서 upload
Python anywhere 콘솔
- python anwhere의 consoles 창(bash 콘솔임)에가서
ls
를 통해서 현재 파일 확인 unzip 프로젝트 파일 이름.확장자
명령을 통해 파일 압축 풀기- pythonanywhere에 virtualenv가 원래 초기에 install 되어 있기 때문에 그냥
virtualenv --python=python버전 가상환경이름
을 통해서 콘솔에 가상환경 만들고, activate 할 것 (bash 콘솔이라서 source를 무조건 써주어야 함)source 가상환경이름/bin/activate
-> 활성화 됨
pip install django
장고 설치- 프로젝트 안에서 static파일들을 수집하는 명령어 수행
python manage.py collectstatic
->yes
- 기존에 프로젝트 파일에
db.sqlite
파일을 안넣었으면python manage.py makemigrations
,python manage.py migrate
통해 db구축 및 연결 exit
를 통해서 콘솔 종료
Python anywhere web
- Python anywhere의 web 에서
add web app
하여 app 추가- python web framework 설정에서
manual configuration
을 선택 가상환경을 포함하기 때문에 - python 버전은 알아서 맞추어서(3.x)
- python web framework 설정에서
- Code 설정하기
- Source code 경로 설정 :
/home/가입한 아이디/프로젝트이름
- WSGI 설정 : 옆에 경로의 wsgi.py 눌러 프레임 워크 설정
- 기본 hello world 설정은 주석처리(
ctrl+/
)시키고 django 부분 주석 해제해서 active 시킴 - django 코드의
path
를 자신의 프로젝트로 수정(기본 mysite라서) - 그리고 하단의 os.environ에서 mysite.settings를
프로젝트이름.settings
로 설정 save
- 기본 hello world 설정은 주석처리(
- Source code 경로 설정 :
- Vitualenv 설정 : 경로 넣기
/home/가입아이디/가상환경이름
Static files 설정 : url 은
/static/
directory는/home/가입아이디/static/
으로 설정 하는데 directory는 콘솔기준의 static 폴더 경로임- static의 경우 Bootstrap에서 가져온 CSS,JS등의 적용을 위해서 필요함
최상단 초록색 Reload버튼 누르면 업데이트됨
배포 확인
가입아이디.pythonanywhere.com
으로 들어가면 됨- pythonanywhere의 경우 배포가 무료인데 3개월에 한번씩 로그인해서 리로드해줘야 한다.
'Django' 카테고리의 다른 글
20210205_Django 예외 처리, 기능보완, request.get, request.GET, 페이징(paginator, page) (0) | 2021.02.06 |
---|---|
20210204_ Django 게시판 리스트 화면, 글쓰기 화면, 글 보기 화면 만들기, template language, form (0) | 2021.02.05 |
20210203_ Django 로그인,세션처리, render, redirect, is_valid, clean(), form 활용 (0) | 2021.02.04 |
20210202_ Django admin, template,view만들기, url연결 - 회원가입, 로그인 (0) | 2021.02.03 |
20210129_ Django 가상환경 설정, MVC, MVT (0) | 2021.01.29 |