반응형

5.1 새로운 애플리케이션 만들기

5.1.1 애플리케이션 설계하기

5.1.2 프로젝트 뼈대 만들기 애플리케이션 추가

경로 이동

C:\Users\NB-0308>cd ..

 

C:\Users>cd ..

 

C:\>cd project

 

C:\project>cd webprogram

 

C:\project\webprogram>dir

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram 디렉터리

 

2020-06-22  오후 02:53    <DIR>          .

2020-06-22  오후 02:53    <DIR>          ..

2020-06-22  오전 11:40    <DIR>          ch3

2020-06-24  오전 11:14    <DIR>          ch4

               0개 파일                   0 바이트

               4개 디렉터리  137,605,287,936 바이트 남음

 

C:\project\webprogram>django-admin startproject mysite

 

C:\project\webprogram>dir

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram 디렉터리

 

2020-06-24  오후 02:03    <DIR>          .

2020-06-24  오후 02:03    <DIR>          ..

2020-06-22  오전 11:40    <DIR>          ch3

2020-06-24  오전 11:14    <DIR>          ch4

2020-06-24  오후 02:03    <DIR>          mysite

               0개 파일                   0 바이트

               5개 디렉터리  137,605,050,368 바이트 남음

 

C:\project\webprogram>dir mysite

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram\mysite 디렉터리

 

2020-06-24  오후 02:03    <DIR>          .

2020-06-24  오후 02:03    <DIR>          ..

2020-06-24  오후 02:03               647 manage.py

2020-06-24  오후 02:03    <DIR>          mysite

               1개 파일                 647 바이트

               3개 디렉터리  137,605,050,368 바이트 남음

 

C:\project\webprogram>dir mysite\mysite

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram\mysite\mysite 디렉터리

 

2020-06-24  오후 02:03    <DIR>          .

2020-06-24  오후 02:03    <DIR>          ..

2020-06-24  오후 02:03               405 asgi.py

2020-06-24  오후 02:03             3,208 settings.py

2020-06-24  오후 02:03               769 urls.py

2020-06-24  오후 02:03               405 wsgi.py

2020-06-24  오후 02:03                 0 __init__.py

               5개 파일               4,787 바이트

               2개 디렉터리  137,605,050,368 바이트 남음

 

C:\project\webprogram>move mysite ch5

        1개의 디렉터리를 이동했습니다.

 

C:\project\webprogram\ch5>python manage.py startapp books

 

C:\project\webprogram\ch5>dir books

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram\ch5\books 디렉터리

 

2020-06-24  오후 04:02    <DIR>          .

2020-06-24  오후 04:02    <DIR>          ..

2020-06-24  오후 04:02                66 admin.py

2020-06-24  오후 04:02                90 apps.py

2020-06-24  오후 04:02    <DIR>          migrations

2020-06-24  오후 04:02                60 models.py

2020-06-24  오후 04:02                63 tests.py

2020-06-24  오후 04:02                66 views.py

2020-06-24  오후 04:02                 0 __init__.py

               6개 파일                 345 바이트

               3개 디렉터리  137,512,517,632 바이트 남음

 

 

C:\project\webprogram\ch5>dir polls

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram\ch5\polls 디렉터리

 

2020-06-24  오후 04:08    <DIR>          .

2020-06-24  오후 04:08    <DIR>          ..

2020-06-24  오후 04:08                66 admin.py

2020-06-24  오후 04:08                90 apps.py

2020-06-24  오후 04:08    <DIR>          migrations

2020-06-24  오후 04:08                60 models.py

2020-06-24  오후 04:08                63 tests.py

2020-06-24  오후 04:08                66 views.py

2020-06-24  오후 04:08                 0 __init__.py

               6개 파일                 345 바이트

               3개 디렉터리  137,508,081,664 바이트 남음

settings.py

INSTALLED_APPS = [
   
'django.contrib.admin',
   
'django.contrib.auth',
   
'django.contrib.contenttypes',
   
'django.contrib.sessions',
   
'django.contrib.messages',
   
'django.contrib.staticfiles',
   
'polls.apps.PollsConfig',#추가
   
'books.apps.BooksConfig', #추가
]

 

 

C:\project\webprogram\ch5>cd books

models.py

 

from django.db import models

# Create your models here.
from django.db import models

class Book(models.Model):
    title = models.CharField(
max_length=100)
    authors = models.ManyToManyField(
'Author')
    publisher = models.ForeignKey(
'Publisher' , on_delete=models.CASCADE)
    publication_date = models.DateField()

   
def __str__(self):
       
return self.title

admin.py
class Author(models.Model):
    name = models.CharField(
max_length=50)
    salutation = models.CharField(
max_length=100)
    email = models.EmailField()

   
def __str__(self):
       
return self.name


class Publisher(models.Model):
    name = models.CharField(
max_length = 50)
    address = models.CharField(
max_length=100)
    website = models.URLField()

   
def __str__(self):
       
return self.name

 

 

 

from django.contrib import admin

# Register your models here.
from django.contrib import admin
from books.models import Book, Author,Publisher

admin.site.register(Book)
admin.site.register(Author)
admin.site.register(Publisher)

C:\project\webprogram\ch5>python manage.py makemigrations

Migrations for 'books':

  books\migrations\0001_initial.py

    - Create model Author

    - Create model Publisher

    - Create model Book

 

C:\project\webprogram\ch5>python manage.py migrate

Operations to perform:

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

Running migrations:

  Applying contenttypes.0001_initial... OK

  Applying auth.0001_initial... OK

  Applying admin.0001_initial... OK

  Applying admin.0002_logentry_remove_auto_add... OK

  Applying admin.0003_logentry_add_action_flag_choices... 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 auth.0007_alter_validators_add_error_messages... OK

  Applying auth.0008_alter_user_username_max_length... OK

  Applying auth.0009_alter_user_last_name_max_length... OK

  Applying auth.0010_alter_group_name_max_length... OK

  Applying auth.0011_update_proxy_permissions... OK

  Applying books.0001_initial... OK

Applying sessions.0001_initial... OK

 

 

 

 

출처: Django로 배우는 쉽고 빠른 웹 개발 파이썬 웹 프로그래밍

반응형
반응형

4.1 Admin 사이트 꾸미기

http://127.0.0.1:8000/admin/

 

4.1.1 데이터 입력 및 수정

장고에서 제공하는

우리가 만든

Models.py

# Create your models here.
class Question(models.Model):
   question_text = models.CharField(
max_length=200)
   pub_date = models.DateTimeField(
'date published')

  
def __str__(self):
     
return self.question_text

 

 

 

4.1.2 필드 순서 변경하기

테이블의 데이터를 변경하는 것이 아니라  , 테이블을 보여 주는 UI양식을 변경하려면 POLLS/ADMIN.PY파일을 변경하면 됩니다.

admin.py

from django.contrib import admin
from polls.models import Question, Choice
# Register your models here.

class QuestionAdmin(admin.ModelAdmin):
    fields = [
'pub_date','question_text'] #필드 순서 변경


admin.site.register(Question)
admin.site.register(Choice)

 

 

from django.contrib import admin
from polls.models import Question, Choice
# Register your models here.

class QuestionAdmin(admin.ModelAdmin):
    fields = [
'pub_date','question_text'] #필드 순서 변경

admin.site.register(Question,QuestionAdmin)
admin.site.register(Choice)

 

 

 

class QuestionAdmin(admin.ModelAdmin):
    filedsets = [
        (
'Question Statement',{'fields' :['question_text']}),
       
('Date Information',{'fields':['pub_date']})
    ]
admin.site.register(Question
,QuestionAdmin)
admin.site.register(Choice)

 

 

4.1.4 필드 접기

 

4.1.5 외래키 관계 화면

QuestionChoice모델 클래스 는 1:N관계로 이루어져 있고 , 서로 외래키로 연결되어 있습니다.

 

4.1.6 QuestionChoice를 한 화면에서 변경하기

Model.py

from django.contrib import admin
from polls.models import Question, Choice
# Register your models here.

'''
class QuestionAdmin(admin.ModelAdmin):
    fields = ['pub_date','question_text'] #
필드 순서 변경
'''
class ChoiceInline(admin.StackedInline):
    model = Choice
    extra =
2

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (
'None',{'fields':['question_text']}),
       
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
   
]
    inlines = [ChoiceInline]
#Choice 모델 클래스 같이 보기

admin.site.register(Question,QuestionAdmin)
admin.site.register(Choice)

 

우리의  예제에서는 Seoul 이라는 Choice text는 이미 들어있던 것이므로 , 그 외에 2개의 항목을 추가로 입력할 수 있습니다.

4.1.7 테이블 형식으로 보여주기

 

#class ChoiceInline(admin.StackedInline):
class ChoiceInline(admin.TabularInline):
    model = Choice
    extra =
2

 

 

 

4.1.8 레코드 리스트 컬럼 지정하기

models.py

Admin사이트의 첫 페이지에서 테이블명을 클릭하면 , 행당 테이블의 레코드 리스트가 나타납니다. 이때 각 레코드의 제목은 어디서 정하는 것일까요 ?

admin.py

class QuestionAdmin(admin.ModelAdmin):
    fields = ['pub_date','question_text'] #
필드 순서 변경
'''
#class ChoiceInline(admin.StackedInline):
class ChoiceInline(admin.TabularInline):
    model = Choice
    extra =
2

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (
'None',{'fields':['question_text']}),
       
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
   
]
    inlines = [ChoiceInline]
#Choice 모델 클래스 같이 보기
   
list_display = ('question_text','pub_date')#렠코드 리스트 컬럼 지정

admin.site.register(Question,QuestionAdmin)
admin.site.register(Choice)

 

4.1.9 list_filter필터

admin.py

class ChoiceInline(admin.TabularInline):
    model = Choice
    extra =
2

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (
'None',{'fields':['question_text']}),
       
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    
]
    inlines = [ChoiceInline]
#Choice 모델 클래스 같이 보기
   
list_display = ('question_text','pub_date')#렠코드 리스트 컬럼 지정
   
list_filter = ['pub_date']

admin.site.register(Question
,QuestionAdmin)
admin.site.register(Choice)

 

4.1.10 search_fields

class ChoiceInline(admin.TabularInline):
    model = Choice
    extra =
2

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (
'None',{'fields':['question_text']}),
       
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
   
]
    inlines = [ChoiceInline]
#Choice 모델 클래스 같이 보기
   
list_display = ('question_text','pub_date')#렠코드 리스트 컬럼 지정
   
list_filter = ['pub_date']
    search_fields = [
'question_text']

admin.site.register(Question
,QuestionAdmin)
admin.site.register(Choice)

 

 

 

4.1.11 polls/admin.py 변경 내역 정리

from django.contrib import admin
from polls.models import Question, Choice
# Register your models here.

'''
class QuestionAdmin(admin.ModelAdmin):
    fields = ['pub_date','question_text'] #
필드 순서 변경
'''
#class ChoiceInline(admin.StackedInline):
class ChoiceInline(admin.TabularInline):
    model = Choice
    extra =
2

class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (
'None',{'fields':['question_text']}),
       
('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
   
]
    inlines = [ChoiceInline]
#Choice 모델 클래스 같이 보기
   
list_display = ('question_text','pub_date')#렠코드 리스트 컬럼 지정
   
list_filter = ['pub_date']
    search_fields = [
'question_text']

admin.site.register(Question
,QuestionAdmin)
admin.site.register(Choice)

 

 

 

4.1.12 Admin사이트 템플릿 수정

C:\project\webprogram>django-admin startproject ch4

 

C:\project\webprogram>dir

 

C:\project\webprogram>rd /s ch4

ch4, 계속하시겠습니까(Y/N)? y

 

C:\project\webprogram>dir

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram 디렉터리

 

2020-06-22  오후 01:26    <DIR>          .

2020-06-22  오후 01:26    <DIR>          ..

2020-06-22  오전 11:40    <DIR>          ch3

2020-06-22  오후 01:24    <DIR>          templates

               0개 파일                   0 바이트

               4개 디렉터리  138,620,039,168 바이트 남음

 

C:\project\webprogram>rd /s templates

templates, 계속하시겠습니까(Y/N)? y

 

C:\project\webprogram>

C:\project\webprogram>django-admin startproject mysite

C:\project\webprogram>cd ch4

 

C:\project\webprogram\ch4>python manage.py startapp polls

 

C:\project\webprogram\ch4>

 

C:\project\webprogram>dir

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram 디렉터리

 

2020-06-22  오후 01:27    <DIR>          .

2020-06-22  오후 01:27    <DIR>          ..

2020-06-22  오전 11:40    <DIR>          ch3

2020-06-22  오후 01:27    <DIR>          mysite

               0개 파일                   0 바이트

               4개 디렉터리  138,620,768,256 바이트 남음

 

C:\project\webprogram>dir mysite

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram\mysite 디렉터리

 

2020-06-22  오후 01:27    <DIR>          .

2020-06-22  오후 01:27    <DIR>          ..

2020-06-22  오후 01:27               647 manage.py

2020-06-22  오후 01:27    <DIR>          mysite

               1개 파일                 647 바이트

               3개 디렉터리  138,620,768,256 바이트 남음

 

C:\project\webprogram>dir mysite\mysite

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 C:\project\webprogram\mysite\mysite 디렉터리

 

2020-06-22  오후 01:27    <DIR>          .

2020-06-22  오후 01:27    <DIR>          ..

2020-06-22  오후 01:27               405 asgi.py

2020-06-22  오후 01:27             3,208 settings.py

2020-06-22  오후 01:27               769 urls.py

2020-06-22  오후 01:27               405 wsgi.py

2020-06-22  오후 01:27                 0 __init__.py

               5개 파일               4,787 바이트

               2개 디렉터리  138,620,768,256 바이트 남음

 

C:\project\webprogram>move mysite ch4

        1개의 디렉터리를 이동했습니다.

C:\project\webprogram\ch4>mkdir templates

 

C:\project\webprogram\ch4>mkdir templates/admin

명령 구문이 올바르지 않습니다.

 

C:\project\webprogram\ch4>mkdir templates\admin

 

C:\project\webprogram\ch4>copy C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin templates\admin\

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\404.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\500.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\actions.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\app_index.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\base.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\base_site.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\change_form.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\change_form_object_tools.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\change_list.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\change_list_object_tools.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\change_list_results.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\date_hierarchy.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\delete_confirmation.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\delete_selected_confirmation.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\filter.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\index.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\invalid_setup.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\login.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\object_history.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\pagination.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\popup_response.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\prepopulated_fields_js.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\search_form.html

C:\Users\NB-0308\anaconda3\Lib\site-packages\django\contrib\admin\templates\admin\submit_line.html

       24개 파일이 복사되었습니다.

 

settings.py

ALLOWED_HOSTS = ['192.168.56.101','localhost','127.0.0.1']

 

 

LANGUAGE_CODE = 'Asia/Seoul'

 

'DIRS': [os.path.join(BASE_DIR, 'templates')],

 

C:\project\webprogram\ch4>cd templates\admin

 

C:\project\webprogram\ch4\templates\admin>notepad base_site.html

 

C:\project\webprogram\ch4\templates\admin>

 

python manage.py runserver 0.0.0.0:8000

 

 

C:\project\webprogram\ch4>cd templates

 

C:\project\webprogram\ch4\templates>cd admin

 

C:\project\webprogram\ch4\templates\admin>notepad base_site.html

 

{% extends "admin/base.html" %}

{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}

{% block branding %}
<!--<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1>-->
<h1 id="site-name"><a href="{% url 'admin:index' %}">SHK Polls Administration</a></h1>
{% endblock %}

{% block nav-global %}{% endblock %}

 

 

C:\project\webprogram\ch4>python manage.py migrate

Operations to perform:

  Apply all migrations: admin, auth, contenttypes, sessions

Running migrations:

  Applying contenttypes.0001_initial... OK

  Applying auth.0001_initial... OK

  Applying admin.0001_initial... OK

  Applying admin.0002_logentry_remove_auto_add... OK

  Applying admin.0003_logentry_add_action_flag_choices... 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 auth.0007_alter_validators_add_error_messages... OK

  Applying auth.0008_alter_user_username_max_length... OK

  Applying auth.0009_alter_user_last_name_max_length... OK

  Applying auth.0010_alter_group_name_max_length... OK

  Applying auth.0011_update_proxy_permissions... OK

  Applying sessions.0001_initial... OK

 

C:\project\webprogram\ch4>python manage.py runserver 0.0.0.0:8000

 

migrate안하면 오류 난다.

C:\project\webprogram\ch4>python manage.py createsuperuser

사용자 생성

 

 

4.2 장고 파이썬 쉘로 데이터 조작하기

 

C:\project\webprogram\ch4>python manage.py shell

Python 3.7.6 (default, Jan  8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)]

Type 'copyright', 'credits' or 'license' for more information

IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.

 

In [1]:

 

DJANGO_SETTINGS_MODULE

속셩을 이용하여 미리 mysite.settings.py모듈을 임포트 한다는 것입니다.

 

 

 

C:\project\webprogram\ch4>python manage.py startapp polls

 

C:\project\webprogram\ch4>cd polls
models.py

 

from django.db import models

# Create your models here.
from django.db import models

class Question(models.Model):
    question_text = models.CharField(
max_length=200)
    pub_date = models.DateField(
'date published')

   
def __str__(self):
       
return self.question_text

class Choice(models.Model):
    question = models.ForeignKey(Question
, on_delete=models.CASCADE)
    choice_text = models.CharField(
max_length=200)
    votes = models.IntegerField(
default=0)

   
def __str__(self):
       
return self.choice_text

 

 

 

C:\project\webprogram\ch4\polls>notepad admin.py

 

from django.contrib import admin
from polls.models import Question, Choice
# Register your models here.

admin.site.register(Question)
admin.site.register(Choice)

 

C:\project\webprogram\ch4>python manage.py makemigrations

No changes detected

 

C:\project\webprogram\ch4>python manage.py migrate

Operations to perform:

  Apply all migrations: admin, auth, contenttypes, sessions

Running migrations:

  No migrations to apply.

 

C:\project\webprogram\ch4>

 

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

 

 

C:\project\webprogram\ch4>python manage.py makemigrations

Migrations for 'polls':

  polls\migrations\0001_initial.py

    - Create model Question

    - Create model Choice

 

C:\project\webprogram\ch4>python manage.py migrate

Operations to perform:

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

Running migrations:

  Applying polls.0001_initial... OK

 

C:\project\webprogram\ch4>python manage.py runserver 0.0.0.0:8000

Watching for file changes with StatReloader

Performing system checks...

 

System check identified no issues (0 silenced).

June 22, 2020 - 15:05:14

Django version 3.0.7, using settings 'mysite.settings'

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

Quit the server with CTRL-BREAK.

 

 

In [1]: from polls.models import Questin, Choice

---------------------------------------------------------------------------

ImportError                               Traceback (most recent call last)

<ipython-input-1-e97d395e2540> in <module>

----> 1 from polls.models import Questin, Choice

 

ImportError: cannot import name 'Questin' from 'polls.models' (C:\project\webprogram\ch4\polls\models.py)

 

In [2]: from polls.models import Question,Choice

 

In [3]: from django.utils import timezone

 

In [4]: q = Question(question_text="What's new?",pub_date=timezone.now())

 

In [5]: q.save

Out[5]: <bound method Model.save of <Question: What's new?>>

 

In [6]: q.save()

 

In [7]:

 

In [5]: Question.objects.filter(

   ...:     question_text_startswith='What'

   ...: ).exclue(

   ...:     pub_date_gte = datetime.date.today()

   ...: ).filter(

   ...:     pub_date_gte = datetime(2005,1,30)

   ...: )

---------------------------------------------------------------------------

FieldError                                Traceback (most recent call last)

<ipython-input-5-960ef36d3940> in <module>

      1 Question.objects.filter(

----> 2     quesstion_text_startswith='What'

      3 ).exclue(

      4     pub_date_gte = datetime.date.today()

      5 ).filter(

 

~\anaconda3\lib\site-packages\django\db\models\manager.py in manager_method(self, *args, **kwargs)

     80         def create_method(name, method):

     81             def manager_method(self, *args, **kwargs):

---> 82                 return getattr(self.get_queryset(), name)(*args, **kwargs)

     83             manager_method.__name__ = method.__name__

     84             manager_method.__doc__ = method.__doc__

 

~\anaconda3\lib\site-packages\django\db\models\query.py in filter(self, *args, **kwargs)

    902         """

    903         self._not_support_combined_queries('filter')

--> 904         return self._filter_or_exclude(False, *args, **kwargs)

    905

    906     def exclude(self, *args, **kwargs):

 

~\anaconda3\lib\site-packages\django\db\models\query.py in _filter_or_exclude(self, negate, *args, **kwargs)

    921             clone.query.add_q(~Q(*args, **kwargs))

    922         else:

--> 923             clone.query.add_q(Q(*args, **kwargs))

    924         return clone

    925

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in add_q(self, q_object)

   1349         # So, demotion is OK.

   1350         existing_inner = {a for a in self.alias_map if self.alias_map[a].join_type == INNER}

-> 1351         clause, _ = self._add_q(q_object, self.used_aliases)

   1352         if clause:

   1353             self.where.add(clause, AND)

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in _add_q(self, q_object, used_aliases, branch_negated, current_negated, allow_joins, split_subq, simple_col, check_filterable)

   1380                     current_negated=current_negated, allow_joins=allow_joins,

   1381                     split_subq=split_subq, simple_col=simple_col,

-> 1382                     check_filterable=check_filterable,

   1383                 )

   1384                 joinpromoter.add_votes(needed_inner)

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in build_filter(self, filter_expr, branch_negated, current_negated, can_reuse, allow_joins, split_subq, reuse_with_filtered_relation, simple_col, check_filterable)

   1249         if not arg:

   1250             raise FieldError("Cannot parse keyword query %r" % arg)

-> 1251         lookups, parts, reffed_expression = self.solve_lookup_type(arg)

   1252

   1253         if check_filterable:

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in solve_lookup_type(self, lookup)

   1086             if expression:

   1087                 return expression_lookups, (), expression

-> 1088         _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())

   1089         field_parts = lookup_splitted[0:len(lookup_splitted) - len(lookup_parts)]

   1090         if len(lookup_parts) > 1 and not field_parts:

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in names_to_path(self, names, opts, allow_many, fail_on_missing)

   1482                     ])

   1483                     raise FieldError("Cannot resolve keyword '%s' into field. "

-> 1484                                      "Choices are: %s" % (name, ", ".join(available)))

   1485                 break

   1486             # Check if we need any joins for concrete inheritance cases (the

 

FieldError: Cannot resolve keyword 'quesstion_text_startswith' into field. Choices are: choice, id, pub_date, question_text

 

In [6]: Question.objects.filter(

   ...:     question_text_startswith='What'

   ...: ).exclue(

   ...:     pub_date_gte = datetime.date.today()

   ...: ).filter(

   ...:     pub_date_gte = datetime(2005,1,30)

   ...: )

---------------------------------------------------------------------------

FieldError                                Traceback (most recent call last)

<ipython-input-6-779424d2cb55> in <module>

      1 Question.objects.filter(

----> 2     question_text_startswith='What'

      3 ).exclue(

      4     pub_date_gte = datetime.date.today()

      5 ).filter(

 

~\anaconda3\lib\site-packages\django\db\models\manager.py in manager_method(self, *args, **kwargs)

     80         def create_method(name, method):

     81             def manager_method(self, *args, **kwargs):

---> 82                 return getattr(self.get_queryset(), name)(*args, **kwargs)

     83             manager_method.__name__ = method.__name__

     84             manager_method.__doc__ = method.__doc__

 

~\anaconda3\lib\site-packages\django\db\models\query.py in filter(self, *args, **kwargs)

    902         """

    903         self._not_support_combined_queries('filter')

--> 904         return self._filter_or_exclude(False, *args, **kwargs)

    905

    906     def exclude(self, *args, **kwargs):

 

~\anaconda3\lib\site-packages\django\db\models\query.py in _filter_or_exclude(self, negate, *args, **kwargs)

    921             clone.query.add_q(~Q(*args, **kwargs))

    922         else:

--> 923             clone.query.add_q(Q(*args, **kwargs))

    924         return clone

    925

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in add_q(self, q_object)

   1349         # So, demotion is OK.

   1350         existing_inner = {a for a in self.alias_map if self.alias_map[a].join_type == INNER}

-> 1351         clause, _ = self._add_q(q_object, self.used_aliases)

   1352         if clause:

   1353             self.where.add(clause, AND)

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in _add_q(self, q_object, used_aliases, branch_negated, current_negated, allow_joins, split_subq, simple_col, check_filterable)

   1380                     current_negated=current_negated, allow_joins=allow_joins,

   1381                     split_subq=split_subq, simple_col=simple_col,

-> 1382                     check_filterable=check_filterable,

   1383                 )

   1384                 joinpromoter.add_votes(needed_inner)

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in build_filter(self, filter_expr, branch_negated, current_negated, can_reuse, allow_joins, split_subq, reuse_with_filtered_relation, simple_col, check_filterable)

   1249         if not arg:

   1250             raise FieldError("Cannot parse keyword query %r" % arg)

-> 1251         lookups, parts, reffed_expression = self.solve_lookup_type(arg)

   1252

   1253         if check_filterable:

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in solve_lookup_type(self, lookup)

   1086             if expression:

   1087                 return expression_lookups, (), expression

-> 1088         _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())

   1089         field_parts = lookup_splitted[0:len(lookup_splitted) - len(lookup_parts)]

   1090         if len(lookup_parts) > 1 and not field_parts:

 

~\anaconda3\lib\site-packages\django\db\models\sql\query.py in names_to_path(self, names, opts, allow_many, fail_on_missing)

   1482                     ])

   1483                     raise FieldError("Cannot resolve keyword '%s' into field. "

-> 1484                                      "Choices are: %s" % (name, ", ".join(available)))

   1485                 break

   1486             # Check if we need any joins for concrete inheritance cases (the

 

FieldError: Cannot resolve keyword 'question_text_startswith' into field. Choices are: choice, id, pub_date, question_text

In [9]: Question.objects.filter(

   ...: question_text__startswith='What'

   ...: ).exclue(

   ...: pub_date__gte = datetime.date.today()

   ...: ).filter(

   ...: pub_date__gte = datetime(2005,1,30)

   ...: )

---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-9-bf746d06f3dc> in <module>

      1 Question.objects.filter(

----> 2 question_text__startswith='What'

      3 ).exclue(

      4 pub_date__gte = datetime.date.today()

      5 ).filter(

 

AttributeError: 'QuerySet' object has no attribute 'exclue'

 

In [9]: Question.objects.filter(

   ...: question_text__startswith='What'

   ...: ).exclude(

   ...: pub_date__gte = datetime.date.today()

   ...: ).filter(

   ...: pub_date__gte = datetime(2005,1,30)

   ...: )

In [10]: Question.objects.filter(

    ...: question_text__startswith='What'

    ...: ).exclude(

    ...: pub_date__gte = datetime.date.today()

    ...: ).filter(

    ...: pub_date__gte = datetime(2005,1,30)

    ...: )

---------------------------------------------------------------------------

NameError                                 Traceback (most recent call last)

<ipython-input-10-b00731584e5c> in <module>

      2 question_text__startswith='What'

      3 ).exclude(

----> 4 pub_date__gte = datetime.date.today()

      5 ).filter(

      6 pub_date__gte = datetime(2005,1,30)

 

NameError: name 'datetime' is not defined

 

 

In [16]: one_entry = Question.objects.get(pk=1)

 

In [17]: one_entry

Out[17]: <Question: What's new?>

 

In [18]: Question.objects.all()[:5]

Out[18]: <QuerySet [<Question: What's new?>]>

 

In [19]:

 

4.2.3 Update 데이터 수정

q.question_text ='What is your favorite hobby?'

q.save()

 

4.2.4 delete데이터 삭제

Question.objects.filter(pub_date__year=2005).delete()

Question.objects.all().delete()

Question.objects.delete()

 

4.2.5 polls 애플리케이션의 데이터 실습

In [4]: from django.utils import timezone

 

In [5]: q = Question(question_text="What'up?

Object `up` not found.

 

In [6]: q = Question(question_text="What'up?

Object `up` not found.

 

In [7]: q = Question(question_text="What'up?", pub_date = timezone.now())

 

In [8]: q.save()

 

In [9]: q.id

Out[9]: 5

 

In [10]: q.question_text

Out[10]: "What'up?"

 

In [11]: q.pub_date

Out[11]: datetime.datetime(2020, 6, 22, 7, 7, 16, 177977, tzinfo=<UTC>)

 

In [12]: q.question_text = "What's new ? "

 

In [13]: q.save()

 

In [14]: Question.objects.all()

Out[14]: <QuerySet [<Question: What's new?>, <Question: What is you hobby ?>, <Question: What do you like best ?>, <Question: Where do you live ?>, <Question: What's new ? >]>

 

In [15]: exit()

 

C:\project\webprogram\ch4>python manage.py shell

Python 3.7.6 (default, Jan  8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)]

Type 'copyright', 'credits' or 'license' for more information

IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.

 

In [1]: from polls.models import Question, Choice

 

In [2]: Question.objects.filter(pk=1)

Out[2]: <QuerySet [<Question: What's new?>]>

 

In [3]: Question.objects.filter(id=1)

Out[3]: <QuerySet [<Question: What's new?>]>

 

In [4]: Question.objects.filter(question_text__startswith='What')

Out[4]: <QuerySet [<Question: What's new?>, <Question: What is you hobby ?>, <Question: What do you like best ?>, <Question: What's new ? >]>

 

In [5]: from ajango.utils import timezone

---------------------------------------------------------------------------

ModuleNotFoundError                       Traceback (most recent call last)

<ipython-input-5-3d9b29a9cc81> in <module>

----> 1 from ajango.utils import timezone

 

ModuleNotFoundError: No module named 'ajango'

 

In [6]: from django.utils import timezone

 

In [7]: current_year = timezone.now().year

 

In [8]: Question.objects.filter(pub_date__year= current_year)

Out[8]: <QuerySet [<Question: What's new?>, <Question: What is you hobby ?>, <Question: What do you like best ?>, <Question: Where do you live ?>, <Question: What's new ? >]>

 

In [9]: Question.objects.get(id=5)

Out[9]: <Question: What's new ? >

 

In [10]: Question.objects.get(id=6)

---------------------------------------------------------------------------

DoesNotExist                              Traceback (most recent call last)

<ipython-input-10-24ef5a462b1a> in <module>

----> 1 Question.objects.get(id=6)

 

~\anaconda3\lib\site-packages\django\db\models\manager.py in manager_method(self, *args, **kwargs)

     80         def create_method(name, method):

     81             def manager_method(self, *args, **kwargs):

---> 82                 return getattr(self.get_queryset(), name)(*args, **kwargs)

     83             manager_method.__name__ = method.__name__

     84             manager_method.__doc__ = method.__doc__

 

~\anaconda3\lib\site-packages\django\db\models\query.py in get(self, *args, **kwargs)

    415             raise self.model.DoesNotExist(

    416                 "%s matching query does not exist." %

--> 417                 self.model._meta.object_name

    418             )

    419         raise self.model.MultipleObjectsReturned(

 

DoesNotExist: Question matching query does not exist.

 

 

In [11]: Question.objects.get(pk=1)

Out[11]: <Question: What's new?>

 

In [12]: q = Question.objects.get(pk=2)

 

In [13]: q.choice_set.all()

Out[13]: <QuerySet [<Choice: Reading>, <Choice: Climbing>, <Choice: Soccer>]>

 

In [14]: q = Question.objects.get(pk=3)

 

In [15]: q.choice_set.all()

Out[15]: <QuerySet []>

 

In [16]: q.choice_set.create(choice_text ='Sleeping',votes=0)

Out[16]: <Choice: Sleeping>

 

In [17]: q.choice_set.create(choice_text='Eating',votes=0)

Out[17]: <Choice: Eating>

 

In [18]: c = q.choice_set.create(choice_text='Playing',votes=0)

 

In [19]: c.question

Out[19]: <Question: What do you like best ?>

 

In [20]: q.choice_set.all()

Out[20]: <QuerySet [<Choice: Sleeping>, <Choice: Eating>, <Choice: Playing>]>

 

In [21]: q.choice_set.count()

Out[21]: 3

 

In [22]: Choice.objects.filter(question__pub_date__year=current_year)

Out[22]: <QuerySet [<Choice: Reading>, <Choice: Climbing>, <Choice: Soccer>, <Choice: Seoul>, <Choice: Daejeon>, <Choice: Jeju>, <Choice: Sleeping>, <Choice: Eating>, <Choice: Playing>]>

 

In [23]: c = q.choice_set.filter(choice_text__startswith='Sleeping')

 

In [24]: c.delete()

Out[24]: (1, {'polls.Choice': 1})

 

장고 파이썬 쉘에서 중요한 점은 SQL쿼리 문장을 사용하지 않고도 데이터베이스에 대한 처리를 할 수 있다는 점이다.

 

4.3 템플릿 시스템

4.3.1 템플릿 변수

4.3.2 템플릿 필터

필터란 일반적인 용어로 어떤 객체나 결과에 추가적으로 명령을 적용하여 해당 명령에 맞게 최종 결과를 변경하는 것

{{ name|lower }}  소문자로 바꾸기

{{ text|escatpe|linebreaks }} text변수 값 중에서 특수 문자를 이스케이프해주고 (escape), 그 결과 스트링에 html<p>태그를 붙여줍니다 (linebreaks)

{{ bio|truncatewords:30 }} 앞에 30개우ㅏ 단어만 보여주고 , 줄 바꿈 문자는 모두 없애줍니다.

{{ list|join:” //” }} 만약 list[‘a’,’b’,’c’]라면 결과는 “a//b//c”

{{ value|default:”nothing” }} false이거나 없는 경우, “nothing”으로 보여줍니다.

{{ value|length }} 변수값의 길이 반환

{{ value|striptags }} html태그를 모두 없애줍니다. 100%보장한느 것은 아니다.

{{ value|pluralize }} Results.html에서 사용했던 복수 접미사 필터입니다.

{{ value|pluralize:”es” }} 또는 {{ value|pluralize:”ies” }} 변수값이 1이 아니면 접미사 s를 붙여줍니다.

{{ first|add:second }} 더하기

First=”python”,second=”django” =>”pythondjango”

First=[1,2,3],second=[4,5,6] =>[1,2,3,4,5,6]

First=”5”,second=”10” => 15

 

 

4.3.3 템플릿 태그

{% tag %}

{% if %}

 

{% for %}

 

{% if 태그 %}

 

{%  if athlete_list|length > 1 %}

 

And, or, not , and , not , == , !=, < , >, <= , >= , in , not in

 

{% csrf_token %}태그

post방식의 <form>을 사용하는 템플릿 코드에서는 CSRF Cross Site Request Forgery공격

{% csrf_token %} =>악의적인 스크립트 문장이 들어있을 수도 있기 때문입니다.

<form action =”.” Method=”post” >{% csrf_token %}

 위치는 forn엘리먼트의 첫줄 다음에 넣어주면 됩니다.

Csrf 토큰값의 유효성을 검증합니다. 만일 csrf토큰값 검증에 실패하면 사용자에게 403에러를 보여줍니다.

한가지 주의 할 점은 CSRF토큰값이 유출될 수 도 있으므로 , 외부 URL로 보내는 <form>에는 사용하지 않도록 합니다.

 

{% url %}

<form action = “{% url ‘polls:vote’ question.id %} method=”post”>

<form action=”/polls/3/vote/” method=”post”>

{% url ‘namespace;view-name’ arg1 arg2 %}

Namespace: urls.py파일의 include()함수 또는 app_name변수에 정의한 이름공간(namespace)이름

View-name:urls.py파일에서 정의한 url패턴이름

argN: 뷰 함수에서 사용하는 인자로 ,없을 수도 있고 여러 개인 경우 빈칸으로 구분함

 

{% with %}태그

{% load %}

{%load somelibrary package.otherlibrary %}

 

 

4.3.4 템플릿 주석

{# greeting #}hello

{# {% if foo %} bar{% else %} #}

 

{% comment “Optional note” %}

<p>Commented out text here</p>

{% endcomment %}

 

4.3.5 HTML 이스케이프

Name = “<b>username”

Hello, {{ name }}

Hello, <b>username =>약점 xss Cross Site Scripting 공격이 이루어집니다.

XSS공격이란 Cross-Site Scripting는 사이트 간 스크립팅 공격이라고도 합니다. 웹 사이트의 취약점을 공격하는 방식 중의 하나로 , 웹 사이트 관리자가 아닌 일반 사용자라도 시도할 수 있는 공격 방법입니다. 주로 여러 사용자가 보게 되는 전자 게시판에 악성 스크립트가 담긴 글을 올리는 형태로 이루어집니다. 이 취약점은 웹 애플리케이션이 사용자로부터 입력 받은 값을 제대로 검사하지 않고 사용할 경우 나타냅니다.

 

<         &lt

>         &gt

           &#39

          &quot

&         &amp

 

4.3.6 템플릿 상속

Title 블록, sidebar블록, content블록 3개입니다.

{% block %}

 

4.4 폼 처리하기

4.4.1 html에서의 폼

get  post 방식

 

4.4.2 장고의 폼 기능

데이터가 없는 폼을 언바운드 unbound폼이라고 하며 , 언바운드 폼은 렌더링 되어 사용자에게 보옂루 때 비어있거나 디폴트 값으로 채워집니다.

바운드 bound폼은 제출된 데이터를 갖고 있어서 데이터의 유효성 검사를 하는데 사용됩니다.

 

4.4.3 폼 클래스로 폼 생성

 

참고로 장고의 폼 클래스는 모든 필드에 대해 유효성 검사 루틴을 실행시키는 is_valide()메소드 를 갖고 있습니다. 이 메소드가 호출되어 유효성 검사를 하고 , 그 결과 만일 모든 필드가 유효하다면 is_valid()메소드는 다음과 같은 2가지 일을 합니다.

True를 반환합니다.

폼 데이터를 cleaned_data속성에 넣습니다.

 

4.4.4 뷰에서 폼 클래스 처리

뷰 함수

Form.is_valie():

           Get_name()

 

4.4.5 폼 클래슬르 템플릿으로 변환

{{ from.as_table }}

{{ from.as_p }}

{{ from.as_ul }}

 

4.5 클래스형 뷰

callable

 

4.5.1 클래스형 뷰의 시작점

As_view()진입 메소드의 역할은 크ㄹ래스의 인스턴스를 생성하고 , 그 인스턴스의 dispatch()메소드를 호출합니다.

Dispatch()메소드는 요청을 검사해서 GET, POST등의 어떤 HTTP메소드로 요청되었는지를 알아낸 다음 ,인스턴스 내에서 해당 이름을 갖는 메소드로 요청을 중계해줍니다.

HttpResponseNotAllowed 익셉션을 발생시킵니다.

 

4.5.2 클래스형 뷰의 장점 효율적인 메소드 구분

4.5.3 클래스형 뷰의 정점 상속 기능 가능

4.5.4 클래스형 제네릭 뷰

제네릭 뷰 generic view

4.5.5 클래스형 뷰에서 폼 처리

4.6 로그 남기기

4.6.1 로거

4.6.2 핸들러

4.6.3 필터

4.6.4 포맷터

4.6.5 로거 사용 및 로거 이름 계층화

 

mysite/settings.py

# logging
LOGGING = {
   
'version' :1,
   
# 기존의 로깅 설정을 비활성화 할 것인가?
   
'disable_existing_loggers' : False,
   
# 핸들러
   
# 로그 레코드로 무슨 작업을 할 것인지 정의
   
# 여러 핸들러 정의 가능
   
'handlers':{
       
'console':{
           
'class': 'loggingStreamHandler'
       
},
   
},
   
# 로거
   
# 로그 레코드 저장소
   
# 로거를 이름별로 정의
   
'loggers': {
       
'mylogger' :{
           
'handlers' : ['console'],
           
'level' :'INFO'
       
}
    }
}

 

 

사용법

Import logging

#settngs.py파일에서 설정된 로거를 취득함

Logger = logging.getLogger(‘mylogger’)

 

 

4.6.6장고의 default 로깅 설정

 

 

4.6.7 장고의 로깅 추가 사항 정리

 

로깅 설정 디폴트 설정 유지

 

 

# logging
LOGGING = {
   
'version' :1,
   
# 기존의 로깅 설정을 비활성화 할 것인가?
   
'disable_existing_loggers' : False,
   
# 포맷터
   
# 로그 레코드는 최종적으로 텍스트로 표현됨
   
# 이 텍스트의 포맷 형식 정의
   
# 여러 포맷 정의 가능
   
'formatters': {
       
'verbose': {
           
'format': '[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s',
           
'datefmt': '%d/%b/%Y %H:%M:%S'
       
},
       
'format2': {
           
'format': '%(levelname)s %(message)s'
       
},
   
},
   
# 핸들러
   
# 로그 레코드로 무슨 작업을 할 것인지 정의
   
# 여러 핸들러 정의 가능
   
'handlers':{
       
#'console':{
        #    'class': 'loggingStreamHandler'
        #},
        #
로그 파일을 만들어 텍스트로 로그레코드 저장
       
'file': {
           
'level': 'DEBUG',
           
'class': 'logging.FileHandler',
           
'filename': os.path.join(BASE_DIR, 'logs','mysite.log'),
           
'formatter': 'verbose',
       
},
       
# 콘솔(터미널)에 출력
       
'console': {
           
'level': 'DEBUG',
           
'class': 'logging.StreamHandler',
           
'formatter': 'format2',
       
}
    }
,
   
# 로거
   
# 로그 레코드 저장소
   
# 로거를 이름별로 정의
   
'loggers': {
       
'django' :{
           
'handlers' : ['file'],
           
'level' :'DEBUG'
       
},
       
'mysite':{
           
'handlers' : ['file'],
           
'level' : 'DEBUG',
       
}
    }
}

 

 

4.6.9 로깅 설정 디폴트 설정 무시

LOGGING_CONFIG= None

LOGGING = {

}

 

Import logging.config

Logging.config.dictConfig(LOGGING)

 

 

 

 

출처 : Django로 배우는 쉽고 빠른 웹 개발 파이썬 웹 프로그래밍

반응형
반응형

3.1 일반적인 특징

파이썬 웹프로그래미이다.

MVC

하지만 장고에서는 ViewTemplate, ControllerView라고 부릅니다.

MVT

3.2 장고 프로그램 설치

C:\Users\NB-0308>python -V

Python 3.7.6

 

3.2.1 윈도우에서 장고 설치

pip install Django

설치 확인

python -m django –-version

 

pip install django-oauth-toolkit djangorestframework

pip install pymysql

pip install mysqlclient

pip install djangorestframework-jwt

pip install pyjwt

pip install djangorestframework_simplejwt

3.3 장고에서의 애플리케이션 개발 방식

3.3.1 MVT 패턴

모델은 데이터베이스에 저장되는 데이터를 의미하는 것이고

템플릿은 사용자에게 보여주는 uii부분

뷰는 실질적으로 프로그램 로직이 동작하여 데이터를 가져오고 적절하게 처리한 결과를 전달하는 역할 을 수행합니다.

3.3.2 Model – 데이터베이스 정의

3,3,3 URLconf-URL정의

3.3.4 View-로직 정의

3.3.5 Template -화면 UI정의

3.3.6 MVT 코딩 순서

프로젝트 뼈대 만들기

모델 코딩하기

URLconf 코딩하기

템플릿 코딩하기

뷰 코딩하기

3.4 애플리케이션 설계하기

프로젝트란 개발 대상이 되는 전체 프로그램을 의미하며 , 프로젝트를 몇 개의 기능 그룹으로 나누었을 때 , 프로젝트 하위의 서브 프로그램을 애플리케이션이라고 합니다.

즉 서버 프로그램인 애플리케이션을 개발하고 , 이들을 모아서 프로젝트 개발을 완성하게 되는 것입니다.

3.5.1 프로젝트 생성

C:\Users\NB-0308>cd c:\project

 

c:\project>mkdir webprogram

 

c:\project>cd webprogram

 

c:\project\webprogram>

 

c:\project\webprogram>django-admin startproject mysite

 

c:\project\webprogram>dir

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 c:\project\webprogram 디렉터리

 

2020-06-18  오후 04:11    <DIR>          .

2020-06-18  오후 04:11    <DIR>          ..

2020-06-18  오후 04:11    <DIR>          mysite

               0개 파일                   0 바이트

               3개 디렉터리  135,499,644,928 바이트 남음

 

c:\project\webprogram>dir mysite

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 c:\project\webprogram\mysite 디렉터리

 

2020-06-18  오후 04:11    <DIR>          .

2020-06-18  오후 04:11    <DIR>          ..

2020-06-18  오후 04:11               647 manage.py

2020-06-18  오후 04:11    <DIR>          mysite

               1개 파일                 647 바이트

               3개 디렉터리  135,499,579,392 바이트 남음

 

c:\project\webprogram>dir mysite\mysite

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 c:\project\webprogram\mysite\mysite 디렉터리

 

2020-06-18  오후 04:11    <DIR>          .

2020-06-18  오후 04:11    <DIR>          ..

2020-06-18  오후 04:11               405 asgi.py

2020-06-18  오후 04:11             3,208 settings.py

2020-06-18  오후 04:11               769 urls.py

2020-06-18  오후 04:11               405 wsgi.py

2020-06-18  오후 04:11                 0 __init__.py

               5개 파일               4,787 바이트

               2개 디렉터리  135,499,579,392 바이트 남음

 

이름 바꾸기

c:\project\webprogram>move mysite ch3

        1개의 디렉터리를 이동했습니다.

 

c:\project\webprogram>

 

3.5.2 애플리케이션 생성

Polls는 원하는 애플리케이션 명칭을 입력하면 됩니다.

c:\project\webprogram>cd ch3

 

c:\project\webprogram\ch3>python manage.py startapp polls

 

c:\project\webprogram\ch3>dir

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 c:\project\webprogram\ch3 디렉터리

 

2020-06-18  오후 04:18    <DIR>          .

2020-06-18  오후 04:18    <DIR>          ..

2020-06-18  오후 04:11               647 manage.py

2020-06-18  오후 04:18    <DIR>          mysite

2020-06-18  오후 04:18    <DIR>          polls

               1개 파일                 647 바이트

               4개 디렉터리  135,498,149,888 바이트 남음

 

c:\project\webprogram\ch3>dir polls

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 c:\project\webprogram\ch3\polls 디렉터리

 

2020-06-18  오후 04:18    <DIR>          .

2020-06-18  오후 04:18    <DIR>          ..

2020-06-18  오후 04:18                66 admin.py

2020-06-18  오후 04:18                90 apps.py

2020-06-18  오후 04:18    <DIR>          migrations

2020-06-18  오후 04:18                60 models.py

2020-06-18  오후 04:18                63 tests.py

2020-06-18  오후 04:18                66 views.py

2020-06-18  오후 04:18                 0 __init__.py

               6개 파일                 345 바이트

               3개 디렉터리  135,498,149,888 바이트 남음

 

 

3.5.3 프로젝트 설정 파일 변경

프로젝트에 필요한 설정값들은 settings.py파일에 지정합니다.

Settings.py파일은 프로젝트의 전반적인 사항들을 설정해주는 곳으로 , 루트 디렉토리를 포함한 각종 디레토리의 위치 , 로그의 형식, 프로젝트에 포함된 애플리케이션의 이름 등이 지정되어 있습니다.

 

1.     ALLOWED_HOSTS 적절하게 지정해야 합니다.

DEBUG = True 개발모드로 , False이면 운영 모드로 인식합니다.

운영 모드인 경우는 ALLOWED_HOSTS에 반드시 서버의 Ip나 도메인을 지정해야 하고 , 개발 모드인 경우에는 값을 지정하지 않아도 locaolhost, 127.0.0.1로 간주

2.     프로젝트에 포함되는 애플리케이션들은 모든 설정 파일에 등록되어야 합니다. 따라서 우리가 개발하고 있는 polls 애플리케이션도 등록해야 합니다. 애플리케이션을 등록할 때는 간단하게 애플리케이션의 모듈명인 ‘polls’만 등록해도 되자만, 애플리케이션의 설정 클래스로 등록하는 것이 더 정확한 방법입니다.

poll앱의 설정 클래스는 startapp polls 명령 시에 자동 생성된 apps.py파일에 PollsConfig라고 정의 되어 있습니다. 그래서 장고가 설정 클래스를 찾을 수 있도록 모듈 결올까지 포함하여 ‘polls.apps.PollsConfig’ 라고 등록합니다.

 

INSTALLED_APPS = [

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

    'polls.apps.PollsConfig' #추가

]

3.     프로젝트에 사용할 데이터베이스 엔진입니다.

장고는 기본적으로 디폴트로 sqlite3데이터베이스 엔진을 사용하도록 설정되어 있습니다.

 

  • ENGINE -- 'django.db.backends.sqlite3''django.db.backends.postgresql''django.db.backends.mysql', 또는 'django.db.backends.oracle'. 그외에 서드파티 백엔드 참조.
  • NAME -- 데이터베이스의 이름. 만약 SQLite 사용 중이라면, 데이터베이스는 당신의 컴퓨터의 파일로서 저장됩니다. 경우NAME  파일명을 포함한 절대경로로 지정해야 합니다. 기본값은 os.path.join(BASE_DIR, 'db.sqlite3') 정의되어 있으며, 프로젝트 디렉토리 내에 db.sqlite3 파일로 저장됩니다.

SQLite 데이터베이스로 사용하지 않는 경우USERPASSWORDHOST 같은 추가 설정이 반드시 필요합니다. 자세한 내용은 DATABASES 문서를 참조해 주세요.

 

https://docs.djangoproject.com/ko/3.0/intro/tutorial02/

 

 

 

4.     타임존 지저ㅇ

TIME_ZONE = 'UTC'

 

#TIME_ZONE = 'UTC'

TIME_ZONE = 'Asia/Seoul'

 

3.5.5 기본 테이블 생성

c:\project\webprogram\ch3>python manage.py migrate

Operations to perform:

  Apply all migrations: admin, auth, contenttypes, sessions

Running migrations:

  Applying contenttypes.0001_initial... OK

  Applying auth.0001_initial... OK

  Applying admin.0001_initial... OK

  Applying admin.0002_logentry_remove_auto_add... OK

  Applying admin.0003_logentry_add_action_flag_choices... 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 auth.0007_alter_validators_add_error_messages... OK

  Applying auth.0008_alter_user_username_max_length... OK

  Applying auth.0009_alter_user_last_name_max_length... OK

  Applying auth.0010_alter_group_name_max_length... OK

  Applying auth.0011_update_proxy_permissions... OK

Applying sessions.0001_initial... OK

 

c:\project\webprogram\ch3>dir

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 c:\project\webprogram\ch3 디렉터리

 

2020-06-18  오후 04:46    <DIR>          .

2020-06-18  오후 04:46    <DIR>          ..

2020-06-18  오후 04:46           131,072 db.sqlite3

2020-06-18  오후 04:11               647 manage.py

2020-06-18  오후 04:18    <DIR>          mysite

2020-06-18  오후 04:46    <DIR>          polls

               2개 파일             131,719 바이트

               4개 디렉터리  134,454,546,432 바이트 남음

 

Migrate 명령은 데이터베이스에 변경사항이 있을 때 이를 반영해주는 명령입니다ㅣ.

이 명령이 필요한 이유 :

장고는 모든 웹 프로젝트 개발 시 반드시 사용자와 그룹 테이블 등이 필요하다는 가정하에 설계되었습니다. 그래서 우리가 테이블을 전혀 만들지 않았더라도 , 사용자 및 그룹 테이블 등을 만들어주기 위해서 프로젝트 개발 시작 시점에 이 명령을 실행하는 것입니다. 명령을 실행하면 migrate 명령에 대한 로그가 보이고 , 실행 결과로 sqlite3데이터베이스 파일인

db.sqlite3 파일이 생성된 것을 확인 할 수 있습니다.

 

3.5.5 지금 까지 작업 확인하기

runserver라고 하는 간단한 테스트용 웹서버를 제공해줍니다.

 

c:\project\webprogram\ch3>python manage.py runserver 0.0.0.0:8000

Watching for file changes with StatReloader

Performing system checks...

 

System check identified no issues (0 silenced).

June 18, 2020 - 17:00:56

Django version 3.0.7, using settings 'mysite.settings'

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

Quit the server with CTRL-BREAK.

[18/Jun/2020 17:00:56] "GET / HTTP/1.1" 200 16351

url에서 : http://localhost:8000/admin

정상

 

로그인 하려면 username, password를 넣어야 되는제 아직 생성하지 않았습니다.

c:\project\webprogram\ch3>python manage.py createsuperuser

Username (leave blank to use 'nb-0308'): user

Email address: haidanliu@dkitec.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.

 

user 0000

여기에서 usersgroups테이블이 보이는 것은 이미 settings.py파일에 Django.contrib.authGroups테이블이 미리 정의 되어 잇는 것입니다.

 

3.6 애플리케이션 개발하기 -Model 코딩

3.6.1 테이블 정의

c:\project\webprogram\ch3>cd polls

 

c:\project\webprogram\ch3\polls>notepad models.py

 

c:\project\webprogram\ch3\polls>

 

from django.db import models

 

# Create your models here.

class Question(models.Model):

           question_text = models.CharField(max_length=200)

           pub_date = models.DateTimeFiled('data published')

 

           def __str__(self):

                      return self.question_text

 

class Choice(models.Model):

           question= models.ForeignKey(Question, on_delete=models.CASCADE)

           choice_text = models.CharField(max_length=200)

           votes = models.IntegerField(default=0)

 

           def __str(self):

            return self.choice_text

테이블을 하나의 class로 정의하고 , 테이블의 컬럼은 클래스의 변수(속성)로 매핑함

django..models.Model클래스를 상속받아 정의하고 , 각 클래스 변수의 타입도 장고에서 미리 정의된 필드 클래스를 사용합니다.

Id는 자동생성해준다.

Pk ;클래스에 정의해주지 않아도 장고는 항상 PK에 대한 속성을 Not NullAutoincrement로 이름은 id로 해서 자동으로 만들어줍니다.

DateTimeFiled()필드 클래스에 정의한 date published pub_Date컬럼에 대한 레이블 문구입니다. 나중에 설명하느 Admin사이트에서 이 문구를 보게 될 것입니다.

FK: 항상 다른 테이블의 pk에 연결된다.

__str__()메소드는 객체를 문자열로 표현할 때 사용하는 함수입니다. 나중에 보게 될 Admin사이트나 장고 쉘 등에서 테이블명을 보여줘야 하는뎅, 이때 __Str__()메소드를 정의하지 않으면 테이블명이 제대로 표시되지 않습니다. 파이썬 2에서는 __unicode__()메소드를 사용합니다.

 

3.6.2 Admin사이트에 테이블 변경

 

c:\project\webprogram\ch3\polls>notepad admin.py

from django.contrib import admin

from polls.models import Question, Choice

# Register your models here.

 

admin.site.register(Question)

admin.site.register(Choice)

 

오류 해결

pub_date = models.DateTimeFiled('data published')  =>

pub_date = models.DateTimeFiled('date published')

 

수정후 ㅊㅇ

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')

 

           def __str__(self):

                      return self.question_text

 

class Choice(models.Model):

           question= models.ForeignKey(Question, on_delete=models.CASCADE)

           choice_text = models.CharField(max_length=200)

           votes = models.IntegerField(default=0)

 

           def __str(self):

            return self.choice_text

import하고 한다.

 

3.6.3 데이터베이스 변경사항 반영

c:\project\webprogram\ch3>python manage.py makemigrations

Migrations for 'polls':

  polls\migrations\0001_initial.py

    - Create model Question

    - Create model Choice

 

c:\project\webprogram\ch3>dir polls\migrations

 C 드라이브의 볼륨에는 이름이 없습니다.

 볼륨 일련 번호: FCA3-2376

 

 c:\project\webprogram\ch3\polls\migrations 디렉터리

 

2020-06-19  오전 10:51    <DIR>          .

2020-06-19  오전 10:51    <DIR>          ..

2020-06-19  오전 10:51             1,107 0001_initial.py

2020-06-18  오후 04:18                 0 __init__.py

2020-06-19  오전 10:51    <DIR>          __pycache__

               2개 파일               1,107 바이트

               3개 디렉터리  132,641,574,912 바이트 남음

 

c:\project\webprogram\ch3>python manage.py migrate

Operations to perform:

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

Running migrations:

  Applying polls.0001_initial... OK

 

c:\project\webprogram\ch3>

 

           python manage.py runserver 0.0.0.0:8000

 

3.7 애플리케이션 개발하기 -View Template 코딩

3.7.1 URLconf코딩

c:\project\webprogram\ch3>cd mysite

 

c:\project\webprogram\ch3\mysite>notepad urls.py

from django.contrib import admin

from django.urls import path

from polls import views

 

urlpatterns = [

    path('admin/', admin.site.urls),

    path('polls/', views.index, name='index'),

    path('polls/<int:question_id>/',views.detail,name ='detail'),

    path('polls/<int:question_id>/results/',views.results,name ='results'),

    path('polls/<int:question_id>/vote/',views.vote,name ='vote'),

]

필요한 모듈과 함수를 임포트합니다. Admin 모듈과 path()함순느 장고에서 제공하는 것이고 , Views모듈은 다음 절에서 코딩을 예정입니다.

URL/뷰 매핑을 정의하는 방식은 항상 동일하므로 , 그대로 따라서 코딩합니다. URL패턴 매칭은 위에서 아래로 진행하므로 ,정의하는 순서에 유의해야 합니다.

장고의 Admin사이트에 대한 URLconf는 이미 정의 되어 있는데 , 이를 활용하고 있습니다. Admin사이틀 사용하기 위해서는 항상 이렇게 정의한다고 알아두세요.

polls애플리케이션에 대한 URL/뷰 매핑을 정의하고 있습니다. PATH()함수를 중요하므로 따로 설명 합니다.

route: url패턴 ,url 스트링

view: url스트링이 매칭되면 호출되는 뷰 함수

kwargs: urlspring에서 추출된 항목 외에 추가적인 인자를 뷰 함수에 전달할 때  ,파이썬 사전 차입으로 인자를 정의합니다.

name: url패턴별로 이름을 붙여줍니다.

 

Admin : path('admin/', admin.site.urls),

요청이 polls 라면

path('polls/', views.index, name='index')

 

/polls/3

path('polls/<int:question_id>/', views.detail, name='detail')

 

 

polls/7/results/

path('polls/<int:question_id>/results/', views.results, name='results'),

 

polls/9/vote/

path('polls/<int:question_id>/vote', views.vote, name='vote'),

 

 

 

mysite/urls.py

from django.contrib import admin
from django.urls import path,include

'''
urlpatterns = [
    path('admin/', admin.site.urls),
    path('polls/',  views.index, name='index'),
    path('polls/<int:question_id>/', views.detail, name='detail'),
    path('polls/<int:question_id>/results/', views.results, name='results'),
    path('polls/<int:question_id>/vote', views.vote, name='vote'),
]
'''
urlpatterns = [
    path(
'admin/', admin.site.urls),
   
path('polls/',include('polls.urls')),
]

 

polls/urls.py

from django.urls import path
from . import views

app_name =
'polls'
urlpatterns = [
    path(
'', views.index , name = 'index'),
   
path('<int:question_id>/', views.detail, name='detail'),
   
path('<int:question_id>/results/', views.results, name='results'),
   
path('<int:question_id>/vote', views.vote, name='vote'),
]

 

 

3.7.2 뷰 함수 index()템플릿 작성

c:\project\webprogram\ch3>cd polls

 

c:\project\webprogram\ch3\polls>notepad urls.py

 

c:\project\webprogram\ch3\polls>mkdir templates

 

c:\project\webprogram\ch3\polls>mkdir templates\polls

 

c:\project\webprogram\ch3\polls>cd templates\polls

 

c:\project\webprogram\ch3\polls\templates\polls>notepad index.html

{% if latest_question_list %{
   
<ul>
   
# latest_question_list index()
    {% for question in latest_question_list %}
       
<li><a href="/polls/{{question.id}}/">{{question.question_Text}}</a></li>
   
{% endfor %}
   
</ul>
{% else %}
   
<p>No polls are available.</p>
{% endif %}

 

c:\project\webprogram\ch3\polls>notepad views.py

 

c:\project\webprogram\ch3\polls>

 

from django.shortcuts import render

# Create your views here.
from django.shortcuts import  render
from polls.models import Question

def index(request):
    latest_question_list = Question.objects().all().order_by(
'-pub_date')[:5]
    context = {
'latest_question_list' : latest_question_list}
   
return render(request, 'polls/index.html', context)

 

 

3.7.3 뷰 함수 detail()및 폼 템플릿 작성

c:\project\webprogram\ch3\polls>cd templates

 

c:\project\webprogram\ch3\polls\templates>cd polls

 

c:\project\webprogram\ch3\polls\templates\polls>notepad detail.html

 

<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{error_message}}</strong></p>{% endif %}

<from action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
   
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{choice.id}}">
    <label
for="choice{{ forloop.counter}}">{{choice.choice.text}}</label>
<% endfor %}
<input type = "submit" value="Vote" />
</from>

 

c:\project\webprogram\ch3\polls\templates\polls>notepad views.py

from django.shortcuts import  render, get_object_or_404
from polls.models import Question

def index(request):
    latest_question_list = Question.objects().all().order_by(
'-pub_date')[:5]
    context = {
'latest_question_list' : latest_question_list}
   
return render(request, 'polls/index.html', context)

def detail(request , question_id):
    question = get_object_or_404(Question
, pk = question_id)
   
return render(request,'polls/detail.html',{'question':question})

 

get_object_or_404()함수를 임포트핟로ㅗㄱ 함수명만 추가하였습니다.

Request는 필수 인자이고 , 추갖거으로 question_id인자를 더 받습니다.

Get_object_or_404()단축함수를 사용하고 있습니다. 이 함수의 첫번쨰 인자는 모델 클래스이고, 두번째 인자부터는 검색 조건을 여러 개 사용할 수 있습니다. 이 예제에서는 Question모델 클래스로 부터 pk = question_id검색 조건에 맞는 객체를 조회합니다. 조건에 맞는 객체가 없으면 Http404익셉션을 발생시킵니다.

Render()

Detail()

 

3.7.4 뷰 함수 vote() 및 리다이렉션 작성

Detail.html  -> vote버튼 클릭 ->

c:\project\webprogram\ch3\polls >notepad views.py

from django.shortcuts import render

# Create your views here.
from django.shortcuts import  render,get_object_or_404
from polls.models import Question
from django.http import HttpResponseRedirect
from polls.models import Choice,Question
from django.urls import reverse

def index(request):
    latest_question_list = Question.objects().all().order_by(
'-pub_date')[:5]
    context = {
'latest_question_list' : latest_question_list}
   
return render(request, 'polls/index.html', context)

def detail(request , question_id):
    question = get_object_or_404(Question
, pk = question_id)
   
return render(request,'polls/detail.html',{'question':question})

def vote(request, question_id):
    question = get_object_or_404(Question
, pk = question_id)
   
try:
        selected_choice = question.choice_set.get(
pk= request.POST['choice'])
   
except(KeyError, Choice.DoesNotExist):
       
#설문 투표 폼을 다시 보여준다.
       
return render(request,'polls/detail.html',{
           
'question':question,
           
'error_message':"You didn't select a choice."
       
})
   
else:
        selected_choice.votes +=
1
       
selected_choice.save()
       
#POST데이터를 정상적으로 처리하였으면 ,
        #
항상 httpResponseRedirectㄹ르 반환하여 리다이렉션 처리함
       
#reverse url처리
       
return HttpResponseRedirect(reverse('polls:results',args=(question.id,)))

 

 

3.7.3 뷰 함수 results()및 템플릿 작성

def results(request, question_id):
    question = get_object_or_404(Question
, pk = question_id)
   
return render(request,'polls/results.html',{'question' : question})

 

 

c:\project\webprogram\ch3\polls\templates\polls>notepad results.html

<h1>{{ question.question_text }}</h1>

<ul>
{% for chioce in question.choice_set.all %}
   
<li>{{ choice.choice_text }} - {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a
href ="{% url 'polls:detail' question.id %}">Vote again?</a>

 

 

 

 

 

 

python manage.py runserver 0.0.0.0:8000

 

http://127.0.0.1:8000/polls/

 

def index(request):
    latest_question_list = Question.objects().all().order_by(
'-pub_date')[:5]
    context = {
'latest_question_list': latest_question_list}
   
return render(request, 'polls/index.html', context)

 

def index(request):
    latest_question_list = Question.objects.all().order_by(
'-pub_date')[:5]
    context = {
'latest_question_list': latest_question_list}
   
return render(request, 'polls/index.html', context)

 

 

{% if latest_question_list %}
   
<ul>
   
# latest_question_list index()
    {% for question in latest_question_list %}
       
<li><a href="/polls/{{ question.id }}/">{{ question.question_Text }}</a></li>
   
{% endfor %}
   
</ul>
{% else %}
   
<p>No polls are available.</p>
{% endif %}

 

 

 

http://127.0.0.1:8000/admin/

Index,html

{% if latest_question_list %}
   
<ul>
   
{% for question in latest_question_list %}
       
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
   
{% endfor %}
   
</ul>
{% else %}
   
<p>No polls are available.</p>
{% endif %}

 

 

Detail.html

<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<from action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
   
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
    <label
for="choice{{ forloop.counter }}">{{choice.choice_text}}</label><br />
<% endfor %}
<input type = "submit" value="Vote" />
</from>

 

 

 

Detail.html

<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
   
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
    <label
for="choice{{ forloop.counter }}">{{choice.choice_text}}</label><br />
{% endfor %}
<input type = "submit" value="Vote" />
</form>

 

Results.html

<h1>{{ question.question_text }}</h1>

<ul>
{% for choice in question.choice_set.all %}
   
<li>{{ choice.choice_text }} - {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>

<a
href ="{% url 'polls:detail' question.id %}">Vote again?</a>

http://127.0.0.1:8000/polls/

python manage.py runserver 0.0.0.0:8000

 

 

 

 

 

 

출처 : Django로 배우는 쉽고 빠른 웹 개발 파이썬 웹 프로그래밍

반응형
반응형

2.1 웹 라이브러리 구성

urllib패키지 : 웹 클라이언트를 작성하는 데 사용되는 모듈들이 있으며 가장 빈번하게 사용하는 모듈들입니다.

http 패키지: 크게 서버용과 클라이언트 용 라이버러리로 나누어 모듈을 담고 있으며 , 쿠키 관련 라이브러리도 http패키지 내에서 서버용과 클라이언트용으로 모듈이 구분되어 있다.

2.2 웹 클라이언트 라이브러리

2.2.1 urllib.parse모듈

이 모듈은 url의 분해 , 조립 ,변경 및 url문자 인코딩 , 리코딩 등을 처리하는 함수를 제공합니다.

Sheme: urlㅇ 사용된 프로토콜을 의미한다.

2.2.2 urllib.request모듈

Urlopen()함수

2.2.3 urllib.request 모듈 예제

2.2.4 http.client모듈

2.3 웹 서버 라이브러리

2.4 CGI/WSGI라이브러리

 

 

출처 : Django로 배우는 쉽고 빠른 웹 개발 파이썬 웹 프로그래밍

 

반응형
반응형

1.1  웹 프로그래밍이란?

서버클라이언트

HTTP(s) 프로토콜로 통신하는 , 클라이언트와 서버를 개발하는 것입니다. 웹 클라이언트와 웹 서버를 같이 개발할 수도 있고 , 웹 클라이언트 또는 웹 서버 하나만 개발할 수도 있습니다.

웹 프로그래밍 장고 Django

1.2  다양한 웹 클라이언트

Request response

1.2.1       웹 브라우저를 사용하여 요청

1.2.2       리눅스 curl명령을 사용하여 요청

1.2.3       Telnet을 사용하여 요청

1.2.4       직접 만든 클라이언트로 요청

1.3  HTTP 프로토콜 Hypertext Transfer Protocol

1.3.1       HTTP 메시지 구조

1.3.2       HTTP 처리 방식

GET방식은 지정한 url의 정보를 가져오는 메소드로 , 가장 많이 사용됩니다.

Post는 대표적인 기능은 리소스를 생성하는 것으로 , 블로그에 글을 등록하는 경우가 이에 해당됩니다. ->리소스 생성

Put은 리소스를 변경하는데 사용됩니다. ->리소스 변경

새롭게 생성한 리소스에 대한 URL결정권이 서버 측에 있을 때 POST를 사용하고 , url결정권이 클라이언트에 있을 때 put을 사용하는 것이 적합합니다.

1.3.3       get post메소드

get url부분의 ? 뒤에 이름 = 값 쌍으로 이어붙여 보냅니다. ->많은 양의 데이터를 보내기 어렵습니다. 제한이 잇기 때문입니다.

1.3.4 상태 코드

1.4  URL 설계

1.5  웹 애플리케이션 서버

정적 페이지: 누가 , 언제 요구하더라도 항상 같은 내용을 표시하는 웹 페이지를 말합니다.

동적 페이지 : 동일한 리소스의 요청이라도 누가 ,언제 , 어떻게 요구했는지에 따라 각각 다른 내용이 변환되는 페이지를 말합니다.

CGI:자체는 정식 프로그래밍 언어나 스크립트가 아니라, 웹 서버와 독립적인 프로그램 사이에 정볼르 주고 닫는 규격을 의미하며 , 이 규격을 준수하면 어떤 언어를 사용해도 CGI프로그램을 개발할 수 있습니다.

 

 

 

 

 

 

 

출처 : Django로 배우는 쉽고 빠른 웹 개발 파이썬 웹 프로그래밍

반응형

+ Recent posts