UDR 멘토링 4주차-2

오종찬·2022년 11월 12일
0

UDR 멘토링

목록 보기
8/10

장고 웹 프로그래밍 강좌

8강 Test

https://www.youtube.com/watch?v=4mm0mGMBQc8&list=PLi4xPOplIq7d1vDdLBAvS5PmQR-p6KwUz&index=8

1. Test

테스트란 코드 작동을 확인하는 루틴

만들어야하는 이유

  1. 앞으로 작성할 코드는 끊임없이 수정 및 개발이 필요하고 버그들이 발생한다
  2. 많은 사람들과 협업하기 때문

2. 첫 번째 테스트 작성

버그식별하기

shell을 사용해 미래의 날짜로 메소드 실행

py manage.py shell
>>> import datetime
>>> from django.utils import timezone
>>> from polls.models import Question
>>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30))
>>> future_question.was_published_recently()   
True  #미래생성 날짜인데 true가 나옴-> 버그발생

태스트 만들기

test.py파일을 만들기

import datetime

from django.test import TestCase
from django.utils import timezone

from .models import Question


class QuestionModelTests(TestCase):

    def test_was_published_recently_with_future_question(self):  #앞머리도 test로 시작해야함
        """
        was_published_recently() returns False for questions whose pub_date
        is in the future.
        """
        time = timezone.now() + datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)
터미널에서 테스트 실행

py manage.py test polls

테스트 실패했다고 출력, 테스트를 통과해야 코드가 올바른 것이다

버그 수정

models.py에서 날짜가 과거에 있을 때에만 True 이도록 코드 수정

def was_published_recently(self):
    now = timezone.now()
    return now - datetime.timedelta(days=1) <= self.pub_date <= now

이후 테스트 다시 실행

3.보다 포괄적인 테스트

test.py에 두가지 테스트 메소드 추가, 과거, 현재, 미래의 질문에 대해 올바른 값을 반환한다는걸 확인시켜줌


def test_was_published_recently_with_old_question(self):

    time = timezone.now() - datetime.timedelta(days=1, seconds=1)
    old_question = Question(pub_date=time)
    self.assertIs(old_question.was_published_recently(), False)

def test_was_published_recently_with_recent_question(self):

    time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
    recent_question = Question(pub_date=time)
    self.assertIs(recent_question.was_published_recently(), True)
 

4.뷰 테스트

뷰의 핵심: request를 받고 response를 해주는 것
뷰 테스트 코드는 사용자가 된 것처럼 request을 하고 response를 받아서 결과값 확인

shell에서 테스트 환경 구성

py manage.py shell

>>> from django.test.utils import setup_test_environment
>>> setup_test_environment()

테스트 클라이언트 클래스 사용

>>> from django.test import Client
>>> client = Client()
>>> response = client.get('/')
Not Found: /
>>> response.status_code
404   #상태코드
>>> from django.urls import reverse
>>> response = client.get(reverse('polls:index'))
>>> response.status_code
200  #상태코드
>>> response.content
b'\n    <ul>\n    \n        <li><a href="/polls/1/">What&#x27;s up?</a></li>\n    \n    </ul>\n\n'
>>> response.context['latest_question_list']
<QuerySet [<Question: What's up?>]>

뷰 개선하기

tests.py에 코드 추가

from django.urls import reverse

def create_question(question_text, days):
    time = timezone.now() + datetime.timedelta(days=days)
    return Question.objects.create(question_text=question_text, pub_date=time)


class QuestionIndexViewTests(TestCase):
    def test_no_questions(self):
        response = self.client.get(reverse('polls:index'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_past_question(self):
        question = create_question(question_text="Past question.", days=-30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question],
        )

    def test_future_question(self):
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertContains(response, "No polls are available.")
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_future_question_and_past_question(self):
        question = create_question(question_text="Past question.", days=-30)
        create_question(question_text="Future question.", days=30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question],
        )

    def test_two_past_questions(self):
        question1 = create_question(question_text="Past question 1.", days=-30)
        question2 = create_question(question_text="Past question 2.", days=-5)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            [question2, question1],
        )

9강 css, static file

https://www.youtube.com/watch?v=S-vgWZnPI_I&list=PLi4xPOplIq7d1vDdLBAvS5PmQR-p6KwUz&index=9

1. css

스태틱 파일 = 정적 파일
웹 어플리케이션은 일반적으로 전체 웹 페이지를 렌더링 하는데 필요한 추가파일을 제공
장고에서는 이러한 파일을 정적 파일이라고 부름
각 응용 프로그램의 정적 파일들을 프로덕션 환경에서 쉽게 제공 할 수있는단일위치로 수집

polls 디렉토리의 static 디렉토리를 만들고, 앱 이름(polls)으로 디렉토리를 하나더 만든 뒤, style.css 파일 생성

li a {
    color: green;
}

index.html 맨 위에 아래코드 추가

{% load static %}   # 템플릿 태그는 정적 파일의 절대 URL을 생성

<link rel="stylesheet" href="{% static 'polls/style.css' %}">

배경 이미지 추가하기

polls/static/polls/에 images 서브 디렉토리 생성, background.gif 이미지 넣기,스타일 시트(style.css)에 코드 추가 => 사이트 왼쪽 상단에 사진 생성

body {
    background: white url("images/background.png") no-repeat;
}

10강 customize admin

https://www.youtube.com/watch?v=nYY1xBNSvgA&list=PLi4xPOplIq7d1vDdLBAvS5PmQR-p6KwUz&index=10

1. 관리자 폼 커스터마이징

admin.py에 admin.site.register(question)부분 코드 수정

from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

admin.site.register(Question, QuestionAdmin)

관련된 객체 추가

admim.py에서 Choice를 관리자의 등록

from django.contrib import admin

from .models import Choice, Question

admin.site.register(Choice)

현재 Choice객체를 시스템에 추가하는 비효율적인 방법임므로 Question 객체를 생성 할 때 여러 개의 Choices를 직접 추가할 수 있게 admin.py 코드 수정

from django.contrib import admin

from .models import Choice, Question


class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]

admin.site.register(Question, QuestionAdmin)

StackedInline 대신 TabularInline을 사용하면 좀 더 깔끔하게 테이블 기반 형식으로 표시

2.관리자 변경 목록 커스터마이징

admin.py 클래스 추가

class QuestionAdmin(admin.ModelAdmin):

	list_display = ('question_text', 'pub_date', 'was_published_recently')
	# 질문, 날짜, 최근에 등록됐는지

커스터마이징한 필드에 대해서 속성을 몇개 부여하여 편리성 상승을 위해 models.py 코드 수정

from django.contrib import admin

class Question(models.Model):
    @admin.display(
        boolean=True,
        ordering='pub_date',
        description='Published recently?',
    )
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

3.어드민 템플릿 수정

mysite 디렉토리에 templates 디렉토리 생성, templates에서 admin 디렉토리 생성 -> 장고에서 커스터마이징 템플릿 위치 알려주기

mysite/settings.py의 DIRS옵션을 tempates 설정에 추가

'DIRS': [BASE_DIR / 'templates'],

장고 소스코드에서 커스터마이징할 파일(base_site.html)을 templates/admin에 복사이후 원하는 대로 변경

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}


이번 강의들을 통해 프로젝트를 만드는 방법에 대해 많이 공부했다.
그중에서 상태코드가 가장 흥미롭게 다가왔다. 가끔 인터넷을 하다가 404같은 숫자를 몇번 봐서 그런지 상태코드에 대해 더 찾아보기로 했다.

과정
구글에 'HTTP 상태 코드' 검색, 이후 아래 사이트를 통해 코드를 통해서 어디에 문제가 생겼는지에 대해 알 수 있다는 것을 숙지
https://velog.io/@sangyeon217/http-status-code

profile
평범한 대학생의 공부내용

0개의 댓글