반응형

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로 배우는 쉽고 빠른 웹 개발 파이썬 웹 프로그래밍

반응형

+ Recent posts