4월-5월 TIL

Soo Im·2022년 4월 2일
0

일별 TIL 기록

목록 보기
9/19
post-custom-banner

2022-04-04


MA(q) 모델에서 ACF(t>q)가 0이 되는 이유

왜 ACF가 MA를 설명하는지 아무리 찾아도 모르겠다... ACF(k)가 lag=k에서 yty_{t}ytky_{t-k}의 직간접 상관을 의미하는 거랑 MA가 cc에서 이전 오차를 반영하는 거랑 무슨 상관인건데... ACF가 차분한 다음에 계산한 것도 아니잖아? SARIMAX까지 갈 길이 멀다

2022-04-06

Django 플젝에서 secret code 파일을 따로 만들어 gitignore에 넣으려다가 여러 문제가 생겨서... 처음부터 플젝 다시 만들었다 😂 나중에 문제 생기느니 지금 해야지

pipenv --three 에러 해결

pipenv --three로 다시 버블 만드려는데 아래 에러가 나오면 다음 스텝으로 해결한다.

pipenv system is intended to be used for pre-existing Pipfile installation, not installation of specific packages.
  1. pipenv --uninstall all pipenv 관련 패키지 모두 삭제
  2. 다시 pipenv --three 시도
  3. 된다면 축하하기
  4. 그래도 안된다면 pipenv --unsinstall all을 다시 실행하고
  5. pip uninstall virtualenv, pip uninstall virtualenv-clone 가상환경 세팅 지우고
  6. pip uninstall pipenv pipenv 제거하고
  7. pip install pipenv pipenv 다시 설치

pipenv 작업을 했던 폴더를 그냥 삭제한 후 똑같은 이름의 폴더를 다시 만들어서 pipenv --three를 하니까 저런 에러가 있었다. 실험을 해보지 못해서 같은 이름의 폴더가 문제였던 건지는 확인하지 못했지만(그냥 pipenv로 이것저것 하다 생긴 오류였을지도) 우선 저렇게 해결했다!

2022-04-07

Pipfile이 실행 플젝에 생성되게 하는 법

어제 에러를 다 고친 줄 알고 기뻐했는데... pipenv를 다시 설치하고 pipenv --three로 Python 버전을 세팅하자 Pipfile이 다른 폴더에 생겼다😱

Virtualenv location: C:\Users\username\.virtualenvs\username-hFtWgrld

플젝 폴더가 아니라 저 폴더 안에 .virtualenvs, Pipfile, Pipfile.lock이 생겼다. 그래서 pipenv shell을 실행하면 자동으로 저 폴더로 이동해버렸다.
찾아보니 Pipfile이 다른 폴더에 생기는 게 오류는 아니라고 한다(.virtualenvs 안에 내 프로젝트명이 생기는 걸로 봐서 플젝에서 작동 안 하는 건 아닌 것 같다).

그래도 나는 플젝 폴더 안에 생기는 게 마음이 편할 것 같아서 해결책을 찾았다. 방법은 간단하다.

set PIPENV_VENV_IN_PROJECT="enabled" # window 기준
export PIPENV_VENV_IN_PROJECT="enabled" # mac 기준

이렇게 설정해주고 다시 pipenv --three를 하면 Pipfile이 플젝 폴더 안에 들어가있다!

2022-04-12

Django migration

데이터 유형이 바뀌면 migration을 생성하고 그에 맞추어 DB를 업데이트하는 과정을 말한다. (데이터 유형 ≃ 데이터 제약 조건으로 봐도 되는 듯)
models.py 안에 데이터 유형을 입력한 후 python manage.py makemigrations을 실행하면 migration이 생성된다. 그리고 python manage.py migrate를 실행하면 migration에 맞추어 데이터 유형이 DB에 적용된다.

2022-04-15

framework vs. library

framework가 library보다 훨씬 강한 규칙을 가진다. Django(framework)에서는 모든 파일/폴더/데이터 명칭 등등의 규칙을 원래 상태 그대로 따라야 한다. 대신 새로운 것을 만드는 것은 괜찮다.

앱 DB 필드(models.py) 수정하기

  1. users 앱을 생성한다.
    django-admin startapp users
  2. 해당 앱 디렉토리의 models.py에서 원하는 형식으로 DB 필드를 편집한다. 필드 유형은 Django 문서에서 선택한다. (modles.py에 입력한 코드를 ORM(Object Relational Mapper)가 SQL문으로 바꿔서 데이터베이스를 생성한다.)
    그리고 새 필드를 추가할 경우 기존 레코드의 값을 처리하려면 default=채우려는 기본값 혹은 null=True 등의 옵션을 준다. 후자는 기존 레코드의 새 필드 값을 null로 두는 것이다.
from ast import Pass
from django.db import models
from django.contrib.auth.models import AbstractUser

# AbstractUser 클래스를 상속하여 User 클래스를 만든다.
class User(AbstractUser):
	# 원하는 필드를 적절히 수정한다.
    bio = models.TextField(default="")
  1. 최상위 디렉토리의 settings.py에서 앱을 추가한다. 기본 세팅은 INSTALLED_APPS = [...] 형식으로 되어있는데, 기본 세팅과 내가 만든 앱을 구분하고 싶으면 이런 식으로 써도 된다.
DJANGO_APSS = [
    # 기존 INSTALLED_APPS에 들어있던 APP 리스트 넣기
]

PROJECT_APPS = [
	# 내가 만든 APP 리스트 넣기
    'users.apps.UsersConfig',
]

INSTALLED_APPS = DJANGO_APSS + PROJECT_APPS
  1. 최상위 디렉토리의 settings.py에서 USER을 덮어씌운다. Django 문서는 유저를 커스터마이징할 때 위 파일에서 AUTH_USER_MODEL=을 이용해 덮어씌우라고 설명한다.
    우리의 경우에는 users 앱의 models.py에서 User라는 새로운 클래스를 만들었으니까 아래와 같이 설정한다.
AUTH_USER_MODEL = 'users.User'
  1. 데이터 유형을 바꾸었으니 기존의 DB 설정을 지우고, migrate도 다시 해줘야 한다. 먼저 최상위 디렉토리의 db.sqlite3를 지운다.
  2. 그 다음 다시 migrate을 한다.
    python manage.py makemigrations를 실행해서 migration 파일(users\migrations\0001_initial.py)을 만들고,
    python manage.py migrate을 실행해서 migrate을 한다. 그러면 다시 db.sqlite3가 생성된다.
  3. 이제 python manage.py runserver하면 내가 만든 앱 DB에 맞게 서버가 작동한다!

2022-04-17

docstring

가끔 파이썬에서 함수나 클래스를 새로 선언하면 자동으로 """ """가 나오는 경우가 있다. 이걸 docstring이라고 하는데 그 안에 들어있는 문자열(보통은 설명문)을 별개의 객체로 처리해준다. 모듈 import 등을 할 때 설명을 편리하게 확인할 수 있다. 자세한 내용은 이 글 참고.

null & blank

위에서 특정 필드의 값에 null을 허용하려면 null=True로 두면 된다고 했다. 하지만 admin 패널에서 입력폼(form)에 아무것도 넣지 않은 채 저장하려면 해당 필드를 입력하라는 경고가 나온다. 이는 DB 유효성 검사와 폼의 유효성 검사가 별개이기 때문이다. null=True는 입력폼 내 필수 입력필드가 빈 칸으로 제출하는 걸 허용하지 않는다. 이 경우에는 따로 blank=True를 주어야 한다.

CharField, TextField는 null=True를 쓰지 말자!
장고는 두 문자 필드에 대해서 빈 값(null)을 ""로 두기 때문에 null=True 옵션을 줄 필요가 없다. 만약 위 옵션을 주면 빈 값을 처리하는 방법이 ""와 null 두 가지가 되기 때문에 에러가 날 수 있다. 출처: 스택오퍼플로우 답변

2022-04-23

Register model into admin.py

모델을 admin에서 관리하게 만들 수 있다. 위에서 만든 users의 모델을 admin에 등록하는 과정은 다음과 같다.

  1. users 앱 내의 admin.py 파일을 편집한다.
  2. 아래와 같이 우리가 만든 모델 클래스를 등록한다.
from . import models

@admin.register(models.User) # <- decorator
class CustomUserAdmin(admin.ModelAdmin):
    pass

한 번에 여러 모델을 등록할 수도 있다.

@admin.register(models.RoomType, models.Facility, models.Amenity, models.HouseRule)
class ItemAdmin(admin.ModelAdmin):
    pass
  1. 첫 줄을 decorator라고 부르는데, "admin 패널에 models.User 클래스를 등록하라"는 뜻이다.
  2. 아랫줄은 우리가 admin 패널에서 사용할 클래스를 선언하는 것이다. 이 때 상속받는 admin.ModelAdminadmin.py에 들어있는 클래스로, 원래의 admin 패널 설정이 들어가있다.
  3. decorator는 무조건 클래스는 한 줄 위에 있어야 한다.
  4. 클래스에서 우리가 useres 모델 중 어느 필드를 노출할지/필터를 걸지/수정 가능하게 할 지... 등등을 설정할 수 있다. 가능한 옵션은 공식 문서에서 확인 가능.
  5. 예를 들어 아래와 같이 보여줄(list_display) 필드 혹은 필터를 걸(list_filter) 필드를 설정할 수 있다.
@admin.register(models.User)
class CustomUserAdmin(admin.ModelAdmin):
    """
    Custom User Admin
    """

    list_display = ("username", "gender", "language", "currency", "superhost")
    list_filter = ("superhost", "language", "currency")

2022-05-16

반복되는 필드 선언

상속을 이용해서 여러 앱에서 공통으로 사용하는 필드를 한 번에 선언할 수 있다. created 필드가 '게시글', '댓글' 앱 모두에 사용하는 경우를 예시로 들어보자.

  1. created 필드를 선언하기 위한 임의의 앱 core을 생성한다. (django-admin startapp core)
  2. core 앱의 models.py에 아래와 같이 필드를 선언한다.
class TimeStampedModel(models.Model):
    """Time Stamped Model"""

    created = models.DateTimeField()
  1. 하지만 우리는 core 앱의 models.py를 따로 데이터베이스로 만들고 싶지 않다. 위에서 만든 필드에 아래와 같이 선언하면 된다.
class TimeStampedModel(models.Model):
    """Time Stamped Model"""

    created = models.DateTimeField()

    class Meta:
        abstarct = True	# 데이터베이스를 만들지 않는 옵션
  1. 이제 생성한 모델을 config>settings.py에 등록한다.
PROJECT_APPS = [
    "core.apps.CoreConfig",
    ...]
  1. 이제 core 앱에서 선언한 필드를 다른 앱의 models.py에서 상속해서 사용할 수 있다.
from django.db import models
from core import models as core_models	# core 앱 내 모델 상속

# Create your models here.
class Room(core_models.TimeStampedModel):
    """Room Model Definition"""

    pass

2022-05-19

__str__

객체의 내용을 문자열로 가공해서 보여줄 때 사용하는 함수. 이 글에 설명이 잘 나와있다.
예를 들어 Human 클래스와 Soo 인스턴스를 아래처럼 만들었다고 가정해보자.

>>> class Human():
		def __init__(self, name):
    		self.name = name

>>> Soo = Human('Soo')

여기서 print(Soo)를 하면 <__main__.Human object at 0x00000...> 이런 식으로 메모리 주소가 나온다. 메모리 주소 대신 다른 정보를 문자열 형태로 전달하려면 Human 클래스 내부에서 __str__ 함수를 사용하면 된다.

class Human():
	def __init__(self, name):
    	self.name = name
	def __str__(self):
    	return self.name

이제 print(Soo)를 하면 Soo가 출력된다!

def __str__(self): return 'something'을 하면 어떤 인스턴스가 생성되더라도 무조건 something 문자열만 반환한다. 이럴 일은 없겠지만 반드시 인스턴스의 정보를 사용할 필요는 없다는 걸 보여주기 위해 든 예시!

Relation with Other Models

장고 내 테이블(DB)는 다른 테이블과 relation을 가질 수 있다. 일대다는 ForeignKey, 다대다는 ManyToManyField로 설정한다. 예를 들어 User 테이블(1)-Room 테이블(N), Room type 테이블(N)-Room 테이블(M)의 관계가 있다고 가정하자.
이 때 Room의 models.py에서 아래와 같이 관계를 설정할 수 있다.

from users import models as user_models	# 연결하려는 테이블 가져오기
from roomtype import models as roomtype_models

class Room(core_models.TimeStampedModel):
    host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)
    room_type = models.ManyToManyField(roomtype_models, blank=True)

이렇게 하면 Room 테이블의 host 필드는 User 테이블 내의 모델(레코드)을 FK로 가진다.
ForeignKey에서 사용하는 파라미터는... 이어서 알아보자

2022-05-21

ForeignKey 파라미터

한 테이블에서 모델이 사라졌을 때, 그 테이블의 모델을 ForeignKey(일대다 관계)로 가지는 다른 테이블에서 어떻게 처리할지 설정하는 파라미터이다.

  1. CASCADE
    위의 예시인models.CASCADE는 폭포수가 떨어지듯이(cascade) 모델이 사라지는 효과가 다른 곳에도 적용된다는 의미이다. 즉 User 테이블의 특정 모델을 삭제하면, 그 모델에 연결된 Room 테이블의 모델도 함께 삭제된다.
  2. PROTECT
    models.PROTECT는 User의 모델이 다른 테이블의 FK로 들어가있다면 그 User 모델을 곧바로 삭제할 수 없게 제한한다. 다른 테이블의 FK를 삭제한 후에야 User 모델을 지울 수 있다.
  3. SET_NULL', 'SET_DEFAULT
    models.SET_NULL은 User 모델을 지우면 다른 테이블의 FK를 NULL 처리 한다. models.SET_DEFAULT는 NULL 대신 FK를 따로 설정한 default 값으로 처리한다.

2022-05-30

admin 패널에서 모델의 값을 수정하려면(Users 모델에 user을 추가했듯이) 다음과 같이 admin.py에 모델을 추가해야 한다.

@admin.register(models.Model1, models.Model2)	# , 를 이용해서 한 번에 여러 모델을 등록할 수도 있다.
class RoomAdmin(admin.ModelAdmin):

이렇게 등록하면 admin 패널에서 모델 명칭은 '모델명'+'s'와 같이 나온다. 예를 들어 위의 경우에는 'Model1s', 'Model2s'로 나온다.
만약 다른 명칭을 원한다면 class Meta에서 verbose_name_plural을 설정해야 한다(앞에서 abstract = True을 썼던 그 Meta이다).

class Model1():
	 class Meta:
     	verbose_name_plural = "First Models"

's'를 붙이는 것은 유지하되 다른 명칭으로 쓰고 싶으면 verbose_name을 설정한다. 예를 들어 RoomType 모델은 'Room types'로 나오는데, 이걸 'Room Types'으로 바꾸고 싶으면 아래와 같이 쓴다.

class RoomType():
	class Meta:
    	verbose_name = "Room Type"
post-custom-banner

0개의 댓글