앞서 포스팅했던 게시물을 통해 주요 설정이 완료되었으니
갼단하게 이메일 주소록 관리 앱 개발을 시작해보겠습니다.
addressesapp 생성하기
다음과 같은 명령어를 통해 먼저 addressesapp을 생성합니다.
python manage.py startapp addressesapp
명령어를 수행하면 다음과 같이 addressesapp 폴더가 생긴 것을 확인할 수 있습니다.
앱을 추가했으니 다음과 같이 settings.py에도 등록합니다.
모델 정의하기
장고에서 테이블은 모델(model)이라고 부르며 models.py에 정의됩니다.
테이블 칼럼(Column)은 모델의 필드(field)로 정의됩니다.
test_server\addressesapp에 위치한 models.py 파일의 내용을 다음과 같이 추가합니다.
<models.py>
from django.db import models
from django.utils.translation import ugettext_lazy as _
class Person(models.Model):
name = models.CharField(_('Name'), max_length=255, unique=True)
mail = models.EmailField(max_length=255, blank=True)
#display name on admin panel
def __unicode__(self):
return self.name
모델을 SQLite에 반영하기
아래 명령어를 통해 모델을 SQLite에 반영해봅시다.
makemigrations : 모델의 변경 사항을 마이그레이션(migrations) 파일로 변환
migrate: 모델 변경 사항을 데이터베이스 스키마에 반영
python manage.py makemigrations
python manage.py migrate
마이그레이션 파일은 test_server\addressesapp 폴더 안에 위치해있습니다.
API 구현하기
API를 다음과 같이 구현합니다.
<api.py>
from rest_framework import generics
from rest_framework.permissions import AllowAny
from rest_framework.pagination import PageNumberPagination
from addressesapp.serializers import AddressesSerializer
from addressesapp.models import Person
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
class AddressesList(generics.ListAPIView):
serializer_class = AddressesSerializer
permission_classes = (AllowAny,)
pagination_class = LargeResultsSetPagination
def get_queryset(self):
query = self.request.query_params.get
if query('name'):
return Person.objects.filter(name=query('name'))
else:
return Person.objects.all()
Person객체를 JSON 포맷으로 REST API 실행 결과를 반환하기 위해
test_server\addressesapp에 위치한 serializers.py에 AddressesSerializer를 생성합니다.
<serializers.py>
from addressesapp.models import Person
from rest_framework import serializers
class AddressesSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Person
fields = ('id', 'name', 'mail')
CSS, JS 추가하기
먼저, 아래 깃허브 url에서 소스를 다운받습니다.
github.com/ai2010/machine_learning_for_the_web/tree/master/chapter_6/test_server/static
chapert_6 > test_server > static에 위치한 css, js 폴더를 복사하여
test_server > static에 붙여넣기 해줍니다.
HTML 추가하기
home.html, base.html, book.html 세 가지 파일을
test_server\templates\addressesapp 위치에 추가합니다.
<home.html>
{% extends "addressesapp/base.html" %}
{% block content %}
<form action="" method="POST">
{% csrf_token %}
<h2 align = Center>Add person to address book </h2>
<p> <br><br></p>
<p align = Center><input type="search" class="span3" placeholder="person" name="name" id="search" autofocus /> </p>
<p align = Center><input type="search" class="span3" placeholder="email" name="email" id="search" autofocus /> </p>
<p align = Center><button type="submit" class="btn btn-primary btn-large pull-center">Add »</button></p>
</form>
{% endblock content %}
<base.html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Email address book</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
{% block stylesheets %}
<!-- Bootstrap provided CSS files. -->
<link href="/static/css/bootstrap.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
</style>
<link href="/static/css/bootstrap-responsive.css" rel="stylesheet">
{% endblock stylesheets %}
{% block javascript %}
<!-- Bootstrap related javascript files -->
<script src="/static/js/jquery.js"></script>
<script src="/static/js/bootstrap-transition.js"></script>
<script src="/static/js/bootstrap-alert.js"></script>
<script src="/static/js/bootstrap-modal.js"></script>
<script src="/static/js/bootstrap-dropdown.js"></script>
<script src="/static/js/bootstrap-scrollspy.js"></script>
<script src="/static/js/bootstrap-tab.js"></script>
<script src="/static/js/bootstrap-tooltip.js"></script>
<script src="/static/js/bootstrap-popover.js"></script>
<script src="/static/js/bootstrap-button.js"></script>
<script src="/static/js/bootstrap-collapse.js"></script>
<script src="/static/js/bootstrap-carousel.js"></script>
<script src="/static/js/bootstrap-typeahead.js"></script>
{% endblock javascript %}
</head>
<body>
{% block header %}
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active"><a href="/">Home</a></li>
<li class=""><a href="/book">Emails Book</a></li>
</ul>
</div>
<form class="navbar-search pull-left" action="{% url 'get_contacts' %}" method="GET">
{% csrf_token %}
<div style="overflow: hidden; padding-right: .5em;">
<input type="text" name="term" style="width: 70%;" />
<input type="submit" name="search" value="Find" size="30" style="float: right" />
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock header %}
<div class="container">
<div class="hero-unit">
{% block content %}
{% endblock content %}
{% block footer %}
<section id="lines"><hr></section>
<section id="footer">
Provided by AI
</section>
{% endblock footer %}
</div>
</div>
</body>
</html>
<book.html>
{% extends "addressesapp/base.html" %}
{% block content %}
<h2 align = Center>Email address book</h2>
<P align=Center>[
{% for letter in alphabet %}
<a href="{% url 'addressesbook' %}?letter={{letter}}" > {{letter}} </a>
{% endfor %}
|<a href="addressesapp/book.html"> Index </a> ] </P>
<section id="gridSystem">
{% for contact in contacts %}
<div class="row show-grid">
<p align = Center><strong> name: </strong>{{ contact.name }} <strong>email:</strong> {{ contact.mail }}    
<a class="right" href="{% url 'delete_person' contact.name %}" > delete </a>
</p>
</div>
{% endfor %}
</section>
{% endblock content %}
URL 선언하기
test_server\test_server 폴더 안에 위치한 urls.py 파일을 다음과 같이 수정합니다.
<urls.py>
from django.conf.urls import url
from django.contrib import admin
from addressesapp.api import AddressesList
from addressesapp.views import main, get_contacts, addressesbook, delete_person, notfound
from rest_framework_swagger.views import get_swagger_view
schema_view = get_swagger_view(title='API name')
urlpatterns = [
url(r'^docs/', schema_view)
]
urlpatterns += [
#url(r'^docs/', include('rest_framework_swagger.urls')),
url(r'^$',main, name='main'),
url(r'^book/',addressesbook,name='addressesbook'),
url(r'^delete/(?P<name>.*)/',delete_person, name='delete_person'),
url(r'^book-search/',get_contacts, name='get_contacts'),
url(r'^addresses-list/', AddressesList.as_view(), name='addresses-list'),
url(r'^notfound/',notfound, name='notfound'),
url(r'^admin/', admin.site.urls),
]
test_server\addressesapp 폴더 안에 위치한 views.py 파일을 다음과 같이 수정합니다.
<views.py>
from django.shortcuts import render
import datetime
import os
import urllib
import json
from django.urls import reverse
from django.shortcuts import redirect
from django.template import RequestContext
from django.template import loader
from addressesapp.models import Person
from ast import literal_eval
from django.conf import settings
import logging
def main(request):
context={}
if request.method == 'POST':
post_data = request.POST
data = {}
data['name'] = post_data.get('name', None)
data['email'] = post_data.get('email', None)
if data:
return redirect('%s?%s' % (reverse('main'),
urllib.parse.urlencode({'q': data})))
elif request.method == 'GET':
get_data = request.GET
data= get_data.get('q',None)
if not data:
return render(
request, 'addressesapp/home.html', context)
data = literal_eval(get_data.get('q',None))
print(data)
if not data['name'] and not data['email']:
return render(
request, 'addressesapp/home.html', context)
#add person to emails address book or update
if Person.objects.filter(name=data['name']).exists():
p = Person.objects.get(name=data['name'])
p.mail=data['email']
p.save()
else:
p = Person()
p.name=data['name']
p.mail=data['email']
p.save()
#restart page
return render(
request, 'addressesapp/home.html', context)
def addressesbook(request):
context = {}
logging.debug('address book')
get_data = request.GET
letter = get_data.get('letter',None)
if letter:
contacts = Person.objects.filter(name__iregex=r"(^|\s)%s" % letter)
else:
contacts = Person.objects.all()
#sorted alphabetically
contacts = sort_lower(contacts,"name")#contacts.order_by("name")
context['contacts']=contacts
alphabetstring='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
context['alphabet']=[l for l in alphabetstring]
return render(
request, 'addressesapp/book.html', context)
def sort_lower(lst, key_name):
return sorted(lst, key=lambda item: getattr(item, key_name).lower())
def delete_person(request,name):
if Person.objects.filter(name=name).exists():
p = Person.objects.get(name=name)
p.delete()
context = {}
contacts = Person.objects.all()
#sorted alphabetically
contacts = sort_lower(contacts,"name")#contacts.order_by("name")
context['contacts']=contacts
return render(
request, 'addressesapp/book.html', context)
def get_contacts(request):
logging.debug('here')
if request.method == 'GET':
get_data = request.GET
data= get_data.get('term','')
print('get contacts:',data)
if data == '':
return render(
request, 'addressesapp/nopersonfound.html', {})
else:
return redirect('%s?%s' % (reverse('addressesbook'),
urllib.parse.urlencode({'letter': data})))
def notfound(request):
context ={}
return render(
request, 'addressesapp/nopersonfound.html', context)
서버 실행하기
다음 명령을 통해 앱을 8080 포트로 실행해보겠습니다.
python manage.py runserver 8080
다음과 같이 이메일 주소록 관리 앱 개발이 완료되었습니다.
관리자(어드민) 인터페이스 추가하기
<admin.py>
from django.contrib import admin
from .models import Person
admin.site.register(Person)
pip 명령어를 통해 계정을 생성합니다.
python manage.py createsuperuser
http://127.0.0.1:8080/admin/으로 접속하여 생성한 계정으로 로그인하면
정상적으로 관리자 화면에 접속되는 것을 확인할 수 있습니다.
Person을 클릭하여 데이터를 관리할 수 있습니다.
이렇게 간단하게 이메일 주소록 관리 앱 개발하기를 해보았습니다!
저도 이번에 장고를 처음 공부해봐서 어려운 점이 많았습니다ㅠㅠ
이번 게시물을 시작으로 장고를 더 깊게 공부해보려고해요!!
게시물과 관련하여 질문 있으시면 답글 남겨주세요~!
감사합니당ㅎㅎ
'Back end > Django' 카테고리의 다른 글
[Django] 장고 시작 - 애플리케이션 설정(REST 프레임워크 설치, logging 라이브러리) (0) | 2020.09.15 |
---|---|
[Django] 장고 시작 - 장고 설치 및 프로젝트 생성 (2) | 2020.09.15 |