0303 TIL

looggi·2023년 3월 3일
2

TILs

목록 보기
24/114
post-thumbnail

django

ORM

  1. ORM에 대해서 설명하시오

ORM은 객체간의 관계를 바탕으로 자동으로 테이블을 생성해주고 SQL문을 사용하지 않고 사용하는 언어 그대로 클래스의 메서드를 통해 데이터베이스 조작(CRUD)을 할 수 있게 해주는 기능입니다.

ORM(Object-Relational Mapping)
장고에서
models.py에 정의한 모델을 바탕으로 객체간의 관계를 통해 데이터베이스의 테이블을 자동으로 생성해줍니다. 이때 하나의 class는 하나의 테이블을 생성하고 관계에 따라 스루테이블이 생기기도 합니다. CRUD를 할 때 SQL 쿼리를 사용하지 않고 데이터를 다룰 수 있습니다. ORM을 통해 CRUD기능을 구현할 때 SQL 쿼리를 사용하지 않고 데이터를 다룰 수 있습니다.

객체를 통해 간접적으로 데이터베이스 데이터를 다룹니다.

  1. Django ORM의 장단점은 무엇입니까?
    SQL문이 아닌 클래스의 메서드를 통해 데이터베이스를 조작할 수 있어 직관적이고 객체 재사용이 가능하여 유지보수에 용이합니다. 하지만 간접적으로 데이터를 다루게 되기때문에 ORM만으로 완벽한 서비스를 구현할 수는 없고 프로젝트가 복잡해질수록 구현하기가 어렵다는 단점이 있습니다.

장점:
현재 쓰는 언어만 사용해도 됨
해당 언어에서 지원하는 라이브러리 사용 가능
DBMS 종속성이 왜 줄어들지??

  • 데이터베이스 시스템으로부터 분리가 됨. -> MYSQL, PostgreSQL 등 원하는 시스템 사용 가능.

단점:
N+1 쿼리 이슈
django ORM은 Lazy-Loading 방식
모든 명령 처리가 끝나고 실제로 데이터를 불러와야 할 시점이 왔을 때 데이터베이스에 쿼리를 실행하는 방식

  • 데이터베이스에 직접 쿼리문을 보내는 것이 아니기 때문에 성능 저하가 발생함.
  • lazy loading이라서 n+1 쿼리 이슈가 발생하는거야?

데이터베이스 복잡도를 데이터베이스 시스템에서 어플리케이션 코드로 옮기게 됨.

https://landwhale2.github.io/python/10/
https://gggggeun.tistory.com/75

결국 SQL문을 써야할 수도 있다

장고에서 퀴리문 확인하는 법

>>> queryset = Book.objects.all()
>>> str(queryset.query)
    SELECT "appname_book"."id", "appname_book"."title","appname_book"."author"
    FROM "appname_book"

장고 ORM으로 연산하는 법

Q모듈

from django.db.models import Q

queryset = Book.objects.filter(Q(title="A") | Q(title="B"))
queryset = Book.objects.filter(Q(title="A") & Q(title="B"))
queryset = Book.objects.filter(~Q(title="A"))

논리 연산자 사용

queryset = Book.objects.filter(title="A")| Book.objects.filter(title="B")
queryset = Book.objects.filter(title="A", title="B")
queryset = Book.objects.filter(title="A") & Book.objects.filter(title="B")

# 내장함수 사용
queryset = Book.objects.exclude(title="A")
  1. Django Admin은 무엇이고 어떤 기능을 제공합니까?
    관리자가 웹서버의 컨텐츠를 관리할 수 있도록 관리자페이지를 통해 데이터베이스에 접근할 수 있는 기능을 제공합니다. 프로젝트의 admin.py에 모델을 등록하면 해당 모델에 대한 데이터에 대해서 CRUD가 가능합니다.

메타 데이터를 읽어서 사이트 컨텐츠를 관리할 수 있도록하는 모델 중심의 인터페이스

  1. Django Template Engine은 무엇이고 어떤 기능을 제공합니까?
    장고에서 템플릿은 유저가 보는 화면으로 이 화면에 view로부터 전달된 데이터를 적용하여 웹페이지를 구성합니다. 이 템플릿에서 데이터를 전달하기 위해 사용하는 언어가 장고 템플릿 언어이고 장고 템플릿 엔진에 의해 해석됩니다. 템플릿 엔진으로 DTL의 변수, 필터, 태그, 커멘트와 같은 기능들을 읽고 실행할 수 있습니다.

https://django-doc-test-kor.readthedocs.io/en/old_master/topics/templates.html#template-inheritance
https://docs.djangoproject.com/en/4.1/topics/templates/

DTL

{% extends "base.html" %}

태그가 하는 일은 템플릿 엔진에게 태그의 내용을 할 것이라고 알려주는 것

Django template engine is used to separate the design from the python code and allows us to build dynamic web pages.

A Django template is a text document or a Python string marked-up using the Django template language. Some constructs are recognized and interpreted by the template engine.

Django 개발 가이드라인은 "App폴더/templates/App명/템플릿파일" 처럼, 각 App 폴더 밑에 templates 서브폴더를 만들고 다시 그 안에 App명을 사용하여 서브폴더를 만든 후 템플릿 파일을 그 안에 넣기를 권장한다

프로그래머스 문제풀기

➡️로또의 최고 순위와 최저 순위

def solution(lottos, win_nums):
    pos_nums=set(win_nums)-set(lottos) # 당첨 가능한 숫자
    inter_nums=set(win_nums)&set(lottos) # 당첨된 숫자
    zero_cnt=lottos.count(0) # 0의 갯수
    if zero_cnt>=len(pos_nums):
        highest=len(inter_nums)+len(pos_nums)
        lowest=len(inter_nums)
    else:
        highest=len(inter_nums)+zero_cnt
        lowest=len(inter_nums)
    if highest==0:
        lowest,highest=1,1
    elif lowest==0:
        lowest=1
    return [6-highest+1,6-lowest+1]

당첨 가능한 숫자, 당첨된 숫자, 순위를 결정하는 0의 갯수를 변수로 만들어놓고
0의 갯수와 거기에 들어갈 수 있는 당첨 가능한 숫자의 갯수를 비교해서

  • 0의 갯수가 같거나 더 많으면 받을 수 있는 최고점은 이미 당첨된 숫자의 갯수 + 가능한 당첨 번호의 갯수가 되고
  • 0의 갯수가 더 적으면 이미 당첨된 숫자의 갯수 + 0의 갯수가 된다

최고점이 0이면 최저점도 당연히 0이 되기때문에 최고점이 0인경우 점수가 1인 것과 같은 결과가 나와야하므로 점수 변수에 1을 넣어준다

최저점은 언제나 0이 하나도 맞지 않고 이미 당첨된 숫자만 맞는 경우이므로 두번 계산해줄 필요도 없고, len(inter_nums)와 같은 값이라서 레퍼런스를 여러개 만들 필요가 없을 것 같아서 수정했다
그리고 0의 갯수가 당첨 가능한 숫자 리스트의 길이보다 항상 작거나 같기때문에 비교하는 게 아무 의미가 없었다...............갹

def solution(lottos, win_nums):
    inter_nums=set(win_nums)&set(lottos)
    zero_cnt=lottos.count(0)
    lowest=len(inter_nums)
    highest=lowest+zero_cnt
    if highest==0:
        lowest,highest=1,1
    elif lowest==0:
        lowest=1
    return [6-highest+1,6-lowest+1]

➡️로또의 최고 순위와 최저 순위 딴 거

def solution(lottos, win_nums):
    rank=[6,6,5,4,3,2,1]
    cnt_0 = lottos.count(0)
    ans = 0
    for x in win_nums:
        if x in lottos:
            ans += 1
    return rank[cnt_0 + ans],rank[ans]

단순히 맞으면 된다고 생각하고 짜야되는데 너무 복잡하게 생각한 것 같당.. 랭크도 어차피 6개 밖에 안되고 로또나 당첨번호나 다 6자리라서 for문 돌려도 상관없고 해서 진짜 잘푼 것 같다ㅜㅜ

def solution(lottos, win_nums):
    rank = {
        0: 6,
        1: 6,
        2: 5,
        3: 4,
        4: 3,
        5: 2,
        6: 1
    }
    return [rank[len(set(lottos) & set(win_nums)) + lottos.count(0)], rank[len(set(lottos) & set(win_nums))]]

같은 set을 써도.. 나도 이렇게 써야지ㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣㅣ

➡️기사단원의 무기

def solution(number, limit, power):
    answer=[] 
    for i in range(1,number+1):
        cnt=0
        for j in range(1,int(i**0.5)+1):
            if i%j==0:
                cnt+=1
        if i**0.5==int(i**0.5):
            cnt=(cnt-1)*2+1
        else:
            cnt=cnt*2
        if cnt>limit:
            cnt=power
        answer.append(cnt)
    return sum(answer)

챠챠챠
if i**0.5==int(i**0.5): 이 부분 if (j == i**2):이렇게 해도 됨 더 간단함
그리고 answer에 append하지 않고 첨부터 answer=0으로 선언해서 해서 아예 처음부터 계속 더하는 것도.. 어차피 더할거니까.. 근데 계속 값 바뀌면 안좋다해서 킁..

def cf(n): # 공약수 출력
    a = []
    for i in range(1,int(n**0.5)+1):
        if n%i == 0:
            a.append(n//i)
            a.append(i)
    return len(set(a))
def solution(number, limit, power):
    return sum([cf(i) if cf(i)<=limit else power for i in range(1,number+1)])

공약수 갯수 구하는 부분을 공약수 전체 리스트를 구해서 그걸 set으로 중복을 없애고 길이를 구함

profile
looooggi

0개의 댓글