티스토리 뷰
*장고가 깔려있는지 확인을 해보자.
$ python -c "import django; print(django.get_version())"
1.8.3
$ django-admin startproject mysite
Let’s look at what startproject created:
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
These files are:
- The outer mysite/ root directory is just a container for your project. Its name doesn’t matter to Django; you can rename it to anything you like.
- manage.py: A command-line utility that lets you interact with this Django project in various ways. You can read all the details about manage.py in django-admin and manage.py.
- The inner mysite/ directory is the actual Python package for your project. Its name is the Python package name you’ll need to use to import anything inside it (e.g. mysite.urls).
- mysite/__init__.py: An empty file that tells Python that this directory should be considered a Python package. (Read more about packages in the official Python docs if you’re a Python beginner.)
- mysite/settings.py: Settings/configuration for this Django project. Django settings will tell you all about how settings work.
- mysite/urls.py: The URL declarations for this Django project; a “table of contents” of your Django-powered site. You can read more about URLs in URL dispatcher.
- mysite/wsgi.py: An entry-point for WSGI-compatible web servers to serve your project. See How to deploy with WSGI for more details.
'ENGINE': 'django.db.backends.mysql',
mysql> show variables where Variable_name = 'datadir';
+---------------+-----------------------+
| Variable_name | Value |
+---------------+-----------------------+
| datadir | /usr/local/var/mysql/ |
+---------------+-----------------------+
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'junkyu',
'USER': 'dev',
'PASSWORD': '0000',
'HOST': 'localhost',
'PORT': '',
}
}
그리고 TIME_ZONE도 바꿔야하는데,
https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-TIME_ZONE
현재 시스템의 시간과 일치 하여야 한다.
TZ List: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
내 시스템의 시간대는 서울이므로
KR | +3733+12658 | Asia/Seoul | +09:00 | +09:00 |
TIME_ZONE = 'Asia/Seoul'
'Asia/Seoul'을 이용한다.
우리는 테이블을 쓰기 위해 테이블들을 생성할 필요가 있다. 이걸 하기위해 다음의 커맨드를 입력하자.
$ python manage.py migrate
그런데 에러가 난다.
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb
It looks like you don't have the python mysql package installed, try:
$pip install mysql-python
or if not using a virtual environment(on *nix hosts):
$sudo pip install mysql-python
그 후 다시 커맨드를 입력하자.
$ python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: staticfiles, messages
Apply all migrations: admin, contenttypes, auth, sessions
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying sessions.0001_initial... OK
EminentStarui-MacBook-Pro:mysite eminentstar$
mysql> show tables;
+----------------------------+
| Tables_in_junkyu |
+----------------------------+
| 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 |
| test |
+----------------------------+
11 rows in set (0.00 sec)
mysql>
$ python manage.py run server
그러면 다음의 텍스트들을 볼 수 있을 것이다.
Performing system checks...
System check identified no issues (0 silenced).
July 29, 2015 - 08:34:52
Django version 1.8.3, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
방금 장고 개발 서버를 시작했다.(A lightweight Web server written purely in Python)
간단한 웹서버로 빠르게 개발이 가능하고, Apache와 같은 production server를 configuring하는 것과 고군분투 할 필요가 없다.(production할 준비가 되기 전까지는)
Now's a good time to note: don't use this server in anything resembling a production environment. It's intended only for use while developing.(We're in the business of making Web frameworks, not Web servers.)
방금 서버가 실행 됬고, http://127.0.0.1:8000을 웹 브라우저와 함꼐 방문하라. 그럼 "Welcome to Django" 페이지가 뜰 것 이다. (라이트 블루 파스텔과 함께)
디폴트로 runserver 커맨드는 개발 서버를 내부 IP상에서 8000 포트에서 시작한다.
만약 포트를 바꾸고 싶다면 커맨드 라인 매개변수를 넘겨야한다.
$ python manage.py runserver 8080
서버의 IP도 바꾸고 싶다면 바꿀 아이피를 포트 이전에 pass시켜야 한다.
$ python manage.py runserver 0.0.0.0:8000
$ python manage.py startapp polls
polls
├── __init__.py
├── admin.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.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)
Philosophy
Django apps are “pluggable”: You can use an app in multiple projects, and you can distribute apps, because they don’t have to be tied to a given Django installation.
mysite/settings.py 파일을 다시 수정하라. INSTALLED_APPS 부분을 'polls'가 포함되도록 변경해라.
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls',
)
$ python manage.py makemigrations polls
Migrations for 'polls':
0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice
$ 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(6) 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;
- 정확한 아웃풋을 우리가 쓰고있는 데이터베이스에 따라 변할 수 있다.
- 테이블 명은 자동적으로 우리의 앱이름(polls)와 결합되어 생성된다.
- Primary keys(IDs)는 자동적으로 추가된다.
- By convention, 장고는 "_id"를 외래키 필드명에 추가한다.
- 외래키 관계는 FOREIGN KEY constraint에 의해 명확하게(explicit) 생성된다.
- 우리가 쓰고있는 데이터베이스에 맞춰서 데이터베이스 특수 필드 타입이 자동적으로 조절된다.
- sqlmigrate 커맨드는 사실상 우리의 DB에 migration을 실행하지 않는다. 이것은 단지 장고가 어떤 sql이 필요되어지는지를 우리가 볼 수 있게 한다.
$ python manage.py check;
System check identified no issues (0 silenced).
$ 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
- Change your models (in models.py)
- Run "python manage.py makemigrations" to create migrations for those changes.
- Run "python manage.py migrate" to apply those changes to the database.
$ python manage.py shell
'python' 커맨드를 수행하는 대신 이것을 쓰는데, manage.py는 DJANGO_SETTINGS_MODULE 환경 변수를 설정하기 때문이다. 이 환경 변수는 django에게 python import path to your mysite/settings.py file를 준다.
자 쉘상에서 database API를 탐험해보자.
>>> 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 renew????? | 2015-07-30 16:21:02.316926 |
+----+-------------------+----------------------------+
1 row in set (0.00 sec)
잠깐만....[<Question: Question object>] 이건 완전 도움이 되지 않는 객체의 표현 방식 이다. 그래서 이것을 Question Model을 수정함으로써 고쳐보자.(in the polls/models.py file) 그리고 __str__() 메소드를 Question and Choice 두 모델에 추가해보자.
from django.db import models
# Create your models here.
class Question(models.Model):# Inherited 'django.db.models.Model'
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self): # __unicode__ on Python 2
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self): # __unicode__ on Python 2
return self.choice_text
대화형 프롬프트에서 다룰때 우리의 편리함을 위함 뿐만 아니라, 객체의 표현이 Django's automatically-generated admin을 통해 사용되기 때문에 __str__ 메소드를 우리의 모델에 추가하는 것은 중요하다.
__str__ or __unicode__?
On Python 3, it’s easy, just use __str__().
On Python 2, you should define __unicode__() methods returning unicodevalues instead. Django models have a default __str__() method that calls__unicode__() and converts the result to a UTF-8 bytestring. This means that unicode(p) will return a Unicode string, and str(p) will return a bytestring, with characters encoded as UTF-8. Python does the opposite: object has a __unicode__ method that calls __str__ and interprets the result as an ASCII bytestring. This difference can create confusion.
If all of this is gibberish to you, just use Python 3.
Note these are normal Python methods. Let’s add a custom method, just for demonstration:
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
Save these changes and start a new Python interactive shell by running python manage.pyshell again:
>>> 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()
mysql> select * from polls_choice;
+----+--------------------+-------+-------------+
| id | choice_text | votes | question_id |
+----+--------------------+-------+-------------+
| 1 | Not much | 0 | 1 |
| 2 | The sky | 0 | 1 |
| 3 | Just hacking again | 0 | 1 |
+----+--------------------+-------+-------------+
3 rows in set (0.01 sec)
// c.delete() 후에
mysql> select * from polls_choice;
+----+-------------+-------+-------------+
| id | choice_text | votes | question_id |
+----+-------------+-------+-------------+
| 1 | Not much | 0 | 1 |
| 2 | The sky | 0 | 1 |
+----+-------------+-------+-------------+
2 rows in set (0.00 sec)
'Server Side > Django' 카테고리의 다른 글
Django 보일러플레이트 셋팅 (0) | 2017.02.09 |
---|---|
종속성이 명시적으로 선언되고 분리된 장고 프로젝트 시작하기(Starting a django Project with explicitly declaring and isolating Dependencies ) (0) | 2016.09.05 |
Django app 시작하기 Part 3: Views and templates (0) | 2015.08.01 |
Django app 시작하기 Part 2: The admin site (0) | 2015.07.31 |
장고 설치하기 (0) | 2015.07.29 |
- Total
- Today
- Yesterday
- async
- logging facade
- object
- Apache
- logging
- webserver
- slf4j
- java
- log
- Spring
- NGINX
- logback
- TaskExecutor
- lood
- log level
- linux
- JVM
- good practice
- runtime data areas
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |