티스토리 뷰

Getting started with simple application

저번 시간에 Installation Guide를 진행하였다. ( 아래 URL 참조 )

http://rocksea.tistory.com/306

이번엔 Django의 기본적인 구조 및 간단한 Application 개발을 진행 하고자 한다.


step 1. Project 생성.

project를 생성한다. 

$ django-admin startproject rocksea


기본 프로젝트 구조

rocksea/

    manage.py

    rocksea/

        __init__.py

        settings.py

        urls.py

        wsgi.py


Project 생성 후 기본으로 사용할 DB 셋팅 후 Migration을 진행한다.

(자세한 설정방법은 http://rocksea.tistory.com/306 참조)

python manage.py migrate


Project를 생성하고 개발 할 app을 생성한다. app과 project에 대한 차이에 대해 

궁금 할 수 있을텐데, Project는 어떤 거대한 site의 관점이며, 그 site내에 포함된 

application을 app이라고 볼 수 있다. 하나의 Project는 여러개의 app을 

포함할 수 있으며, 하나의 앱은 여러 Project에 포함 될 수 있다.

$ python manage.py startapp polls


app 구조 ( 기본구조를 살짝 변경하였다.)

polls/

    __init__.py

    admin.py

    migrations/

        __init__.py

    models.py

    tests.py

    views/

        __init__.py

        main.py

    views.py


step 2. App 코드 작성

trabi/urls.py

/polls 로 접근하는 URL에 대한 매핑을 추가한다.

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    # Examples:
    # url(r'^$', 'trabi.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^admin/', include(admin.site.urls)),
    url(r'^polls/', include('polls.urls'))
]


polls/urls.py

polls url에 대한 Mapping 파일을 생성 후 index 파일을 생성한다.

from django.conf.urls import include, url
import views.main as main

urlpatterns = [
  url(r'^$', main.index, name='index'),
]


polls/views.py

view 페이지에 대한 index를 생성한다.

from django.http import HttpResponse
from django.shortcuts import render

# Create your views here.
def index(request):
  return HttpResponse("Hello, world. You're at the polls index.")
~


이제 MVC의 기본적인 구조는 갖추었으니 서버를 시작하여 확인 해 본다.

$ python manage.py runserver 0.0.0.0:8000


[그림 1] Django Web Server 실행 화면


step 3. 데이터 베이스 테이블 생성

INSTALLED_APPS에 polls를 추가한다.

rocksea/settings.py

INSTALLED_APPS = (

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

    #2015.07.06 by rocksea - polls

    'polls',

)


rocksea/models.py

from django.db import models # Create your models here. class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') class Choice(models.Model): question = models.ForeignKey(Question) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0)


이제 Django에 모델이 변경되었다는걸 알려주도록 한다.

$ python manage.py makemigrations pollsMigr

  0001_initial.py:

    - Create model Choice

    - Create model Question

    - Add field question to choice

ations for 'polls'


위 명령을 수행하면 polls/migrations/0001_initial.py 파일이 생성이된다. 

0001 버전에 대한 SQL문이 어떻게 생성되는지 미리 확인 해 볼 수 있다.(현재까지 파일로만 저장된 상태)

$ python manage.py sqlmigrate polls 0001
BEGIN;
CREATE TABLE `polls_choice` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL);
CREATE TABLE `polls_question` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_date` datetime NOT NULL);
ALTER TABLE `polls_choice` ADD COLUMN `question_id` integer NOT NULL;
ALTER TABLE `polls_choice` ALTER COLUMN `question_id` DROP DEFAULT;
CREATE INDEX `polls_choice_7aa0f6ee` ON `polls_choice` (`question_id`);
ALTER TABLE `polls_choice` ADD CONSTRAINT `polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id` FOREIGN KEY (`question_id`) REFERENCES `polls_question` (`id`);

COMMIT;


이제 Migration을 통해 생성한 Model에 대한 DB Table을 생성하도록 한다.

$ python manage.py migrate

Operations to perform:

  Synchronize unmigrated apps: staticfiles, messages

  Apply all migrations: admin, contenttypes, polls, auth, sessions

Synchronizing apps without migrations:

  Creating tables...

    Running deferred SQL...

  Installing custom SQL...

Running migrations:

  Rendering model states... DONE

  Applying polls.0001_initial... OK


DB테이블을 조회를 통해 polls_choice, polls_question 테이블이 추가된 것을 확인 할 수 있다.  

mysql> show  tables;

+----------------------------+

| Tables_in_rocksea          |

+----------------------------+

| auth_group                 |

| auth_group_permissions     |

| auth_permission            |

| auth_user                  |

| auth_user_groups           |

| auth_user_user_permissions |

| django_admin_log           |

| django_content_type        |

| django_migrations          |

| django_session             |

| polls_choice               |

| polls_question             |

+----------------------------+



이제 shell모드에서 직접 Table안에 데이터를 입력하고 수정하는 방법에 대해 확인해 보도록 한다.

$ python manage.py shell



아래의 절차대로 객체를 선언한 뒤 값을 binding 후 save()를 호출하면 값이 DB에 저장된다.
>>> from polls.models import Question, Choice # Import the model classes we just wrote.
# No questions are in the system yet.
>>> Question.objects.all()
[]
# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID. Note that this might say "1L" instead of "1", depending
# on which database you're using. That's no biggie; it just means your
# database backend prefers to return integers as Python long integer
# objects.
>>> q.id
1
# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all() displays all the questions in the database.
>>> Question.objects.all()
[<Question: Question object>]


mysql> select * from polls_question;

+----+---------------+---------------------+

| id | question_text | pub_date            |

+----+---------------+---------------------+

|  1 | What's up?    | 2015-07-06 06:06:40 |

+----+---------------+---------------------+


조회 및 삭제도 아래의 예제를 따라하면 된다. 

( create(), get(), filter(), delete() 등을 통해 생성,조회 및 삭제를 해보도록 한다. )

>>> from polls.models import Question, Choice
# Make sure our __str__() addition worked.
>>> Question.objects.all()
[<Question: What's up?>]
# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
[<Question: What's up?>]
>>> Question.objects.filter(question_text__startswith='What')
[<Question: What's up?>]
# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>
# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)
# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
[]
# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>
# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> q.choice_set.count()
3
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

List자료형태로 조회 할 경우 

Question.objects.filter(question_text__startswith='What')[0].question_text 

위와 같이 필드에 접근 한다.


이제 관리자에서 polls을 관리 할 수 있도록 추가한다.

(아래 register를 추가해야 관리자에서 볼 수 있다.)

polls/admin.py

from django.contrib import admin

# Register your models here.
from .models import Question
admin.site.register(Question)


이제 appserver 실행 후 admin에 접속한 뒤 확인해 보도록 한다.

$ python manage.py runserver 0.0.0.0:8000

Performing system checks...


System check identified no issues (0 silenced).

July 06, 2015 - 07:53:17

Django version 1.8, using settings 'trabi.settings'

Starting development server at http://0.0.0.0:8000/

Quit the server with CONTROL-C.


(* admin 계정 생성 방법)

$ python manage.py createsuperuser

Username: admin

Email address: admin@rocksea.kr

Password:

Password (again):

Superuser created successfully.



admin 화면 ( http://127.0.0.1:8000/admin/ )

[그림 1] admin 프로젝트


[그림 2] polls 어플리케이션 관리


[그림 3] Question 데이터 관리


이번 포스팅에선 객체 및 DB 생성 및 Access까지 다루었으며,

다음장에선 Django Persistent connections을 이용한 Connection Pool 관리,  

기본 Rest API 서버 구현을 통해 좀더 심화과정을 다뤄보도록 하겠다.


출처 : https://media.readthedocs.org/pdf/django/latest/django.pdf

댓글