- values_list() 2023.08.09
- 삽입 정렬 알고리즘 2023.07.29
- 선택 정렬 알고리즘 2023.07.29
- annotate() 메서드와 가변 키워드 인자 2023.07.25
- django에서 *args, **kwargs 2023.07.25
- Python) 위치 인자, 키워드 인자 2023.07.25
- get_user_model() 2023.07.22
- @classmethod 와 @staticmethod 2023.07.20
- django 템플릿 <script>태그 2023.07.08
- Django ORM에서 던더(__) 2023.07.07
values_list()
는 Django 쿼리셋(QuerySet) 메서드 중 하나로, 데이터베이스에서 특정 필드들만 가져올 때 사용됩니다. 이 메서드는 특정 필드들에 대한 튜플들의 리스트를 반환합니다.
예시
# 예시 모델
class MyModel(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
gender = models.CharField(max_length=100)
height = models.IntegerField()
# values_list() 사용
queryset = MyModel.objects.values_list('name', 'age')
위의 예시에서 values_list('name', 'age')
는 MyModel
모델의 name
필드와 age
필드에 대한 데이터를 가져옵니다.
[('John', 25), ('Alice', 30), ('Bob', 22)]
즉, name
필드와 age
필드에 대한 튜플들의 리스트가 반환됩니다.
values_list()
를 사용하면 쿼리셋에서 가져와야 할 필드들을 선택적으로 지정하여 데이터베이스에서 필요한 정보만 효율적으로 가져올 수 있습니다.
'Python > Django' 카테고리의 다른 글
Serializer에서 method 사용하기 (0) | 2023.08.27 |
---|---|
Django에서의 Transactions (0) | 2023.08.26 |
annotate() 메서드와 가변 키워드 인자 (0) | 2023.07.25 |
django에서 *args, **kwargs (0) | 2023.07.25 |
get_user_model() (0) | 2023.07.22 |
삽입 정렬 알고리즘(insertion sort algorithm)
삽입 정렬(insertion sort)은 리스트를 반복하면서 각 항목을 이미 정렬된 부분 리스트의 올바른 위치에 "삽입"함으로써 동작합니다.
- 리스트의 두 번째 항목에서 시작하여 왼쪽의 항목과 비교합니다.
- 현재 항목이 왼쪽 항목보다 작으면 왼쪽 항목을 오른쪽으로 이동시킵니다.
- 이를 현재 항목이 왼쪽 항목보다 크거나 왼쪽에 더 이상 항목이 없을 때까지 반복합니다.
- 그런 다음 현재 항목을 마지막으로 비어 있는 위치에 삽입합니다.
- 이 과정을 리스트의 모든 항목에 대해 반복합니다.
이를 파이썬 코드로 구현하면 다음과 같습니다:
def insertion_sort(arr: list[int]) -> list[int]:
# 배열 전체를 반복하면서
for i in range(1, len(arr)):
key: int = arr[i]
# 이미 정렬된 배열 부분에서 올바른 위치를 찾아가는 과정
j: int = i - 1
while j >=0 and key < arr[j] :
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
return arr
if __name__ == "__main__":
arr: list[int] = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
print(insertion_sort(arr))
# [1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9]
예를 들어, 이 함수에 [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
배열을 전달하면,3
과 1
을 비교하고, 1
이 더 작으므로 순서를 바꿉니다. [1, 3, 4, 1, 5, 9, 2, 6, 5, 3, 5]
이렇게 바뀐 이후 3번째 인덱스인 4
를 비교하기 시작합니다. 4
는 1
보다 크므로 지나가고, 3
보다 크므로 지나갑니다. 이런 식으로 배열의 마지막 인덱스까지 정렬을 진행합니다.
삽입 정렬의 시간 복잡도는 최악의 경우 O(n^2)입니다. 그러나 리스트가 이미 거의 정렬되어 있는 경우 삽입 정렬은 매우 효율적일 수 있으며, 이 경우 시간 복잡도는 O(n)이 됩니다.
'Algorithms and Data Structures > Algorithms' 카테고리의 다른 글
Divide and Conquer(분할 정복) (0) | 2023.08.29 |
---|---|
Brute Force (0) | 2023.08.15 |
재귀 함수(Recursive Function) (0) | 2023.08.13 |
선택 정렬 알고리즘 (1) | 2023.07.29 |
선택 정렬 알고리즘(selection sort)
- 리스트 중에서 최소값을 찾습니다.
- 그 값을 리스트의 맨 앞에 위치한 값과 바꿉니다.
- 맨 처음 위치를 제외한 나머지 리스트를 대상으로 위의 과정을 반복합니다.
Python 코드
def selection_sort(arr: list[int]) -> list[int]:
length: int = len(arr)
# 배열 전체를 반복하면서
for index_1 in range(length):
min_index: int = index_1
# 현재 위치에서 가장 작은 원소를 찾습니다.
for index_2 in range(index_1 + 1, length):
if arr[min_index] > arr[index_2]:
min_index = index_2
# 가장 작은 원소와 현재 원소를 교환합니다.
arr[index_1], arr[min_index] = arr[min_index], arr[index_1]
return arr
if __name__ == "__main__":
arr: list[int] = [3, 1, 4, 9, 5, 7, 5]
print(selection_sort(arr))
# [1, 3, 4, 5, 5, 7, 9]
예를 들어, 이 함수에 [3, 1, 4, 9, 5, 7, 5]
배열을 전달하면,3
과 1
을 비교해 1
이 더 작으므로 min_index은 0에서 1
의 위치정보인 1로 바뀝니다. 그리고 나머지 숫자들과 차례대로 비교합니다.
그러면 배열이 [1, 3, 4, 9, 5, 7, 5]
로 바뀝니다.
이러한 과정을 반복하면 배열 [1, 3, 4, 5, 5, 7, 9]
이라는 결과가 나옵니다.
선택 정렬의 시간 복잡도는 O(n^2)입니다. 이는 리스트의 모든 요소를 한 번씩 검사해야 하기 때문이며, 따라서 큰 리스트에서는 매우 느릴 수 있습니다.
'Algorithms and Data Structures > Algorithms' 카테고리의 다른 글
Divide and Conquer(분할 정복) (0) | 2023.08.29 |
---|---|
Brute Force (0) | 2023.08.15 |
재귀 함수(Recursive Function) (0) | 2023.08.13 |
삽입 정렬 알고리즘 (0) | 2023.07.29 |
annotate()
메서드는 Django 쿼리셋에서 사용되는 함수 중 하나로, 데이터베이스에서 집계된 값을 추가하는 데 사용됩니다. annotate()
메서드를 사용하면 원하는 필드 값을 가져오고 그 값을 기반으로 새로운 필드를 생성할 수 있습니다.
annotate(aggregate_expression, ...)
aggregate_expression
: 필드 값을 계산하기 위한 집계 식을 지정합니다. 일반적으로 Django의django.db.models
모듈에 있는 집계 함수들을 사용합니다. 예를 들어,Count()
,Sum()
,Avg()
,Min()
,Max()
등이 있습니다.
annotate()
메서드는 쿼리셋의 결과에 대해 각 필드 값에 대한 집계를 수행하고, 결과에 추가된 필드를 포함한 새로운 쿼리셋을 반환합니다. 이를 통해 집계된 값을 활용할 수 있습니다.
예
Book 모델이 있다고 가정하고, 이 모델은 다음과 같은 필드가 있다고 가정하겠습니다.(title, author, pages)
이때 각 저자가 쓴 책들의 총 페이지 수를 계산한다면 아래처럼 사용할 수 있습니다.
from django.db.models import Sum # 집계 함수
total_pages_by_author = Book.objects.values("author").annotate(Sum("pages"))
이러면 각 저자별로 책들의 총 페이지 수를 계산하고 그 결과를 pages__sum
이라는 이름의 필드로 추가합니다. 그러면 각 저자의 이름과 그 저자의 책들의 총 페이지 수를 담은 딕셔너리의 쿼리셋을 리턴합니다.
리턴되는 쿼리셋의 예시는 아래와 같습니다.
total_pages_by_author = [
{
'author': 1, # 작가1의 id
'pages__sum': 250, # 작가1이 쓴 책들의 페이지 수 합산
},
{
'author': 2, # 작가2의 id
'pages__sum': 400, # 작가2가 쓴 책들의 페이지 수 합산
}
]
만약 pages__sum
이라는 필드명이 아닌 사용자가 정의한 필드명으로 구현하고 싶다면 아래 방식대로 구현하면 됩니다.
annotate(field_name=aggregate_expression)
field_name
: 생성된 필드의 이름을 지정합니다.
예
from django.db.models import Sum
total_pages_by_author = Book.objects.values("author").annotate(total_pages=Sum("pages"))
이러면 리턴값에 추가되는 필드명이 total_pages
가 됩니다.
리턴되는 쿼리셋의 예시는 아래와 같습니다.
total_pages_by_author = [
{
'author': 1, # 작가1의 id
'total_pages': 250, # 작가1이 쓴 책들의 페이지 수 합산
},
{
'author': 2, # 작가2의 id
'total_pages': 400, # 작가2가 쓴 책들의 페이지 수 합산
}
]
가변 키워드 인자
이 annotate() 함수를 공부하면서 의아한 점이 생겼습니다. anootate() 함수의 field_name
은 어떤 인자인지가 궁금해졌습니다. 키워드 인자도 아니고 위치 인자도 아니고 지정한 이름에 따라 바뀌는 인자가 무엇이지 찾아보며 알게 된 결론은 "가변 키워드 인자"였습니다.
참고로 아래 두 링크를 읽고 오시면 다음 내용이 더 이해가 잘 되실겁니다.
위치 인자와 키워드 인자 : https://yesaroun.tistory.com/entry/Python-%EC%9C%84%EC%B9%98-%EC%9D%B8%EC%9E%90-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%9D%B8%EC%9E%90
django에서 *args, **kwargs : https://yesaroun.tistory.com/entry/django%EC%97%90%EC%84%9C-args-kwargs
annotate()
는 키워드 인자를 받아서 새로운 필드 이름으로 사용하는 "키워드 인자 패킹"이라는 Python의 기능을 사용합니다.
아래의 예시가 가변 키워드 인자를 사용하는 예시입니다.
def func(**kwargs):
for key, value in kwargs.items():
print(f"{key} = {value}")
func(a=1, b=2)
# a = 1
# b = 2
이 예시는 단순하게 **kwargs
인자를 설명하는 예시일 수 있습니다. 하지만 이 예시 대로 annotate() 메서드의 가변 키워드 인자도 동일하게 동작합니다.
아래는 annotate()
에서 사용되는 가변 키워드 인자 개념을 보기 쉽게 표현한 annotate_func()
코드입니다.
def annotate_func(**kwargs):
# 이 경우 kwargs = {"total_pages": Sum("pages")}
aggregates = kwargs # 집계 표현식을 저장하는 딕셔너리
for field, aggregate_expr in aggregates.items():
# 각 키와 값을 출력합니다.
print(f"필드명: {field}, 집계 표현식: {aggregate_expr}")
annotate_func(total_pages="Sum('pages')")
# 필드명: total_pages, 집계 표현식: Sum('pages')
만약 더 django의 annotate() 메소드 코드를 보고 싶으면 아래 코드를 확인해 주세요.
django 코드 링크 : https://github.com/django/django/blob/3.2/django/db/models/query.py
'Python > Django' 카테고리의 다른 글
Django에서의 Transactions (0) | 2023.08.26 |
---|---|
values_list() (0) | 2023.08.09 |
django에서 *args, **kwargs (0) | 2023.07.25 |
get_user_model() (0) | 2023.07.22 |
django 템플릿 <script>태그 (0) | 2023.07.08 |
Django와 같은 Python 기반 프레임워크에서 *args
와 **kwargs
는 함수나 메소드에 임의의 개수의 인자를 전달하는데 사용되는 문법입니다.
*args
:*args
는 임의의 개수의 위치 인자를 함수나 메소드로 전달하는데 사용됩니다. 이를 통해 함수나 메소드는 미리 정해지지 않은 개수의 인자를 받을 수 있습니다.*args
는 튜플 형태로 인자를 전달받습니다.**kwargs
:**kwargs
는 임의의 개수의 키워드 인자를 함수나 메소드로 전달하는데 사용됩니다. 이를 통해 함수나 메소드는 미리 정해지지 않은 개수의 키워드 인자를 받을 수 있습니다.**kwargs\
는 딕셔너리 형태로 인자를 전달받습니다.
참고 위치인자, 키워드 인자란 : https://yesaroun.tistory.com/entry/Python-%EC%9C%84%EC%B9%98-%EC%9D%B8%EC%9E%90-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%9D%B8%EC%9E%90
일반적인 사용 예시
1. *args
의 사용 예시
def print_all_args(*args):
for count, thing in enumerate(args):
print('{}. {}'.format(count, thing))
print_all_args('apple', 'banana', 'cabbage')
# 0. apple
# 1. banana
# 2. cabbage
위의 코드는 print_all_args
라는 함수를 정의하고 있습니다. 이 함수는 *args
를 인자로 받아서, 넘겨받은 모든 인자를 출력합니다. 따라서 'apple', 'banana', 'cabbage' 세 가지 인자를 넘겨주면, 이 세 가지 모두를 출력합니다.
2. `kwargs`의 사용 예시**
def print_keyword_args(**kwargs):
for key in kwargs:
print('{}: {}'.format(key, kwargs[key]))
print_keyword_args(apple='fruit', cabbage='vegetable')
# apple: fruit
# cabbage: vegetable
위의 코드는 print_keyword_args
라는 함수를 정의하고 있습니다. 이 함수는 **kwargs
를 인자로 받아서, 넘겨받은 키워드 인자의 키와 값을 출력합니다. 따라서 'apple'과 'cabbage'라는 키와 각각의 값을 넘겨주면, 이 키와 값들을 출력합니다.
django에서 사용 예시
1. *args
의 사용 예시
장고에서 *args
와 **kwargs
는 주로 URLconf에서 보낸 위치 인자와 키워드 인자를 뷰 메소드로 전달하는데 사용됩니다.
먼저, URLconf를 정의합니다
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path("articles/<int:year>/", views.YearArchiveView.as_view())
]
위의 URL 패턴에서 <int:year>
부분은 year
라는 이름의 정수 변수를 캡처합니다.
이제 뷰에서 이 year
변수를 받아서 처리하는 코드를 작성합니다
# views.py
from django.http import HttpResponse
from django.views import View
class YearArchiveView(View):
def get(self, request, *args, **kwargs):
year = kwargs.get("year")
return HttpResponse("Year archive: {}".format(year))
위의 코드에서 *args
와 **kwargs
는 URLconf에서 캡처한 변수를 받는 역할을 합니다. 여기서 kwargs.get("year")
를 통해 year
변수를 가져오고 있습니다.
2. `kwargs`의 사용 예시**
장고(Django)에서 *args
를 사용하는 상황은 비교적 드뭅니다. 왜냐하면 대부분의 경우에서 키워드 인자(**kwargs
)가 더 명확하고 관리하기 쉽기 때문입니다. 키워드 인자를 사용하면 각 인자가 무엇을 의미하는지 명확히 알 수 있습니다.
그러나 *args
는 어떤 함수나 메소드를 오버라이드(override)하거나 래핑(wrapper)하는 경우에 유용하게 사용할 수 있습니다. 예를 들어, Django에서 모델의 save
메소드를 오버라이드하는 경우에 *args
를 사용할 수 있습니다
from django.db import models
class MyModel(models.Model):
my_field = models.CharField(max_length=100)
def save(self, *args, **kwargs):
self.my_field = self.my_field.upper() # 대문자로 변환
super().save(*args, **kwargs) # save() 메서드 오버라이드
여기서 *args
와 **kwargs
를 사용하면, 원래 save
메소드가 받아들일 수 있는 모든 인자를 그대로 전달할 수 있습니다. 따라서 *args
와 **kwargs
를 사용하면 원래의 save
메소드와 같은 인터페이스를 유지하면서 새로운 동작을 추가할 수 있습니다.
'Python > Django' 카테고리의 다른 글
values_list() (0) | 2023.08.09 |
---|---|
annotate() 메서드와 가변 키워드 인자 (0) | 2023.07.25 |
get_user_model() (0) | 2023.07.22 |
django 템플릿 <script>태그 (0) | 2023.07.08 |
Django ORM에서 던더(__) (0) | 2023.07.07 |
파이썬에서 함수를 호출할 때, 인자(argument)를 전달하는 방법에는 두 가지가 있습니다. 위치인자(Positional Arguments)와 키워드 인자(Keyword Arguments)로 나뉩니다.
1. 위치 인자 (Positional Arguments)
위치 인자는 함수 호출 시 전달하는 인자가 함수 정의에서 매개변수(parameter)의 위치에 따라 매핑되는 방식입니다. 즉, 인자의 순서가 함수 정의에서 매개변수의 순서와 일치해야 합니다. 위치인자를 사용할 때는 인자의 값을 순서대로 전달합니다.
일반적으로 인자를 정의하는 방식입니다.
예
def greet(name, age):
print(f"Hello, {name}. You are {age} years old.")
이 함수는 name
과 age
라는 두 개의 매개변수를 받아서 인사말과 나이를 출력합니다. 이제 이 함수를 호출할 때 위치인자를 사용하면 다음과 같습니다.
greet("Alice", 30)
위의 호출은 name
에 "Alice"라는 값이, 그리고 age
에 30이라는 값이 매핑되어 함수가 실행됩니다.
2. 키워드 인자 (Keyword Arguments)
키워드 인자는 함수 호출 시 인자의 이름을 지정하여 함수 정의에서 해당 이름과 매핑되도록 전달하는 방식입니다. 이를 통해 인자의 순서를 신경 쓰지 않고 명확하게 어떤 값이 어떤 매개변수에 해당하는지 지정할 수 있습니다.
예
greet(age=30, name="Alice")
이렇게 키워드 인자를 사용하면 인자의 순서와 상관없이 name
과 age
에 대해 명확하게 지정할 수 있습니다. 파이썬에서는 위치인자와 키워드 인자를 혼합하여 사용할 수도 있습니다. 하지만 키워드 인자를 사용하려면 위치인자가 먼저 나와야 합니다.
greet("Bob", age=25)
위의 호출은 name
에 "Bob"이라는 위치 인자가 먼저 왔고, age
에는 키워드 인자로 25가 전달되었습니다.
하지만, 이렇게 위치 인자와 키워드 인자를 혼합해서 사용하는 방식은 지양하는 것이 좋습니다.
'Python > Python' 카테고리의 다른 글
deque 모듈 (0) | 2023.08.30 |
---|---|
Python - isinstance() (0) | 2023.08.12 |
@classmethod 와 @staticmethod (0) | 2023.07.20 |
@property 데코레이터 (0) | 2023.07.01 |
glob.glob() 함수 (0) | 2023.06.11 |
Django에서 get_user_model()
함수는 현재 사용 중인 User 모델 클래스를 가져오는 데 사용되는 메서드입니다.
내장 User 모델
장고에 내장되어있는 User 모델을 사용하는 경우 get_user_model()
은 django.contrib.auth.get_user_model()
함수를 호출하여 django.contrib.auth.models.User
클래스를 반환합니다.
예를 들어, User 모델에 대한 참조를 가져오기 위해 다음과 같이 get_user_model()
함수를 사용할 수 있습니다
from django.contrib.auth import get_user_model
User = get_user_model()
이렇게 하면 User
변수는 현재 활성화된 User 모델을 나타내게 됩니다.
사용자 정의 User 모델
get_user_model()
함수는 사용자 정의 모델을 사용하는 경우에도 사용 가능합니다. 사용자 정의 User 모델을 구현하면, settings.py 파일에 AUTH_USER_MODEL
설정을 하는데 이렇게 하면 get_user_model()
함수는 자동으로 사용자 정의 모델을 반환합니다.
# settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'
이렇게 하면 get_user_model()
은 myapp.CustomUser
클래스를 반환합니다.
'Python > Django' 카테고리의 다른 글
annotate() 메서드와 가변 키워드 인자 (0) | 2023.07.25 |
---|---|
django에서 *args, **kwargs (0) | 2023.07.25 |
django 템플릿 <script>태그 (0) | 2023.07.08 |
Django ORM에서 던더(__) (0) | 2023.07.07 |
Type hint 적용후 circular dependency 문제 해결법 (0) | 2023.06.30 |
인스턴스 메서드, 클래스 메서드, 정적 메서드 차이점
- 인스턴스 메서드(Instance Methods): 이 메서드들은 클래스의 객체 인스턴스에서 호출되며, 첫 번째 인자로 인스턴스 자체(
self
)를 받습니다. 인스턴스 변수에 접근하여 값을 읽거나 수정할 수 있습니다.
클래스 메서드(Class Methods): 클래스 메서드는 클래스에서 호출되며, 첫 번째 인자로 클래스(
cls
)를 받습니다. 이 메서드들은 클래스 변수를 수정하는 데 사용될 수 있습니다. 인스턴스에 대한 정보는 사용할 수 없습니다.정적 메서드(Static Methods):
@staticmethod
데코레이터로 표시된 메서드는 인스턴스나 클래스에 대한 참조 없이 동작합니다. 이 메서드들은 클래스나 인스턴스 상태를 수정할 필요가 없는 경우에 사용됩니다.
@classmethod
@classmethod
데코레이터는 메서드를 클래스 메서드로 표시하는 데 사용됩니다. 일반적인 인스턴스 메서드와 달리 클래스 메서드는 클래스 자체를 첫 번째 인자로 받습니다(일반적으로 cls
로 표시됩니다), 그리고 객체 인스턴스가 아닌 클래스를 조작합니다.
예시
class MyClass:
class_variable = "I am a class variable"
def __init__(self, instance_variable):
self.instance_variable = instance_variable
def instance_method(self):
print(f"Instance method, instance variable: {self.instance_variable}")
@classmethod
def class_method(cls):
print(f"Class method, class variable: {cls.class_variable}")
@staticmethod
def static_method():
print("Static method, no access to class or instance variables")
# 인스턴스 생성
my_instance = MyClass("I am an instance variable")
# 인스턴스 메서드 호출
my_instance.instance_method()
# Instance method, instance variable: I am an instance variable
# 클래스 메서드 호출
MyClass.class_method()
# Class method, class variable: I am a class variable
# 정적 메서드 호출
MyClass.static_method()
# Static method, no access to class or instance variables
@classmethod
는 주로 클래스 변수를 조작하거나, 클래스에 대한 상태를 변경할 때 사용됩니다. 또한, 인스턴스를 생성하지 않고도 클래스의 기능을 사용할 수 있게 해줍니다.
@staticmethod
@staticmethod
데코레이터는 메서드를 정적(static) 메서드로 지정합니다. 정적 메서드는 클래스와 관련이 있지만 클래스나 인스턴스의 상태에 영향을 받지 않으며, 인스턴스 메서드와 달리 self
나 cls
와 같은 첫 번째 매개변수를 갖지 않습니다.
따라서 @staticmethod
를 사용하여 정의된 메서드는 클래스의 인스턴스 없이도 호출할 수 있으며, 클래스 내부의 다른 메서드나 속성에 접근할 수 있습니다.
아래 예시 코드에서 @staticmethod
를 사용한 이유는 Serializer 클래스의 serialize()
메서드를 클래스 메서드로 정의하고자 했기 때문입니다. @staticmethod
를 사용하면 serialize()
메서드를 인스턴스화하지 않고도 직접 호출할 수 있으며, 클래스 내부의 다른 메서드나 속성에 접근할 수 있습니다.
class UserSerializer:
@staticmethod
def serialize(user):
# 직렬화 로직
return serialized_data
이렇게 하면 UserSerializer.serialize(user)
와 같은 형태로 메서드를 호출할 수 있습니다.
정적 메서드는 클래스의 상태와 관련이 없는 유틸리티 메서드를 정의하거나, 클래스와 밀접한 연관이 있는 로직을 모듈화하고 싶을 때 유용하게 사용될 수 있습니다.
'Python > Python' 카테고리의 다른 글
Python - isinstance() (0) | 2023.08.12 |
---|---|
Python) 위치 인자, 키워드 인자 (0) | 2023.07.25 |
@property 데코레이터 (0) | 2023.07.01 |
glob.glob() 함수 (0) | 2023.06.11 |
Python 라이브러리 - functools (0) | 2023.05.24 |
장고 템플릿을 이용하는 프로젝트 진행 중에 대시보드를 구현해야 했습니다.
대시보드 한 페이지에 다양한 정보가 들어오고 컴포넌트 별로 실시간 업데이트가 필요하지 않을까라는 생각에 ajax로 통신을 하려고 했습니다.
ajax로 통신할 때 url 정보를 보내줘야 하는데 장고 url 태그가 편리하기에 이 장고 코드를 <script> 태그
내에 작성해도 되는지 알아보았습니다.
<script>
태그 내부의 장고 코드
<script>
태그 내부에도 Django 템플릿 태그를 사용할 수 있습니다. 하지만 여기서 주의할 점은 Django 템플릿 태그가 서버 측에서 처리되고, JavaScript 코드는 클라이언트 측에서 실행된다는 것입니다.
예를 들어, Django의 URL을 JavaScript 코드에서 사용하고 싶을 때, 이렇게 할 수 있습니다
<script>
let listDataUrl = "{% url 'list_data_url' %}";
let graphDataUrl = "{% url 'graph_data_url' %}";
// 이후에 이 URL들을 AJAX 요청에서 사용
// ...
</script>
위의 예제에서, Django 템플릿 태그는 서버 측에서 URL을 생성하고, 이 URL은 JavaScript 변수에 할당됩니다. 이후에 이 변수들을 사용하여 AJAX 요청을 수행할 수 있습니다.
주의할 점
여기서 주의할 점은 Django 템플릿 태그가 서버 측에서 처리되고, JavaScript 코드는 클라이언트 측에서 실행된다는 것입니다.
웹 애플리케이션에서 서버 측과 클라이언트 측은 다른 환경에서 실행되며, 서로 다른 역할을 수행합니다.
서버 측(Server-Side)
- 서버 측은 웹 서버와 백엔드 애플리케이션 로직이 실행되는 곳입니다.
- 데이터베이스 쿼리, 인증, 데이터 처리 등과 같은 작업을 처리합니다.
- Django는 서버 측 웹 프레임워크로, 요청이 들어오면 이에 대한 응답을 생성하는 데 사용됩니다.
- Django 템플릿 태그는 서버에서 해석되고 처리됩니다. 템플릿 태그는 서버 측에서 HTML 문서를 렌더링 하는데 도움이 됩니다.
클라이언트 측(Client-Side)
- 클라이언트 측은 사용자의 브라우저에서 실행되는 환경입니다.
- HTML, CSS, JavaScript로 구성된 웹 페이지를 렌더링 하고, 사용자와 상호작용합니다.
- JavaScript는 클라이언트 측에서 실행되며, 동적인 기능을 제공합니다 (예: 버튼 클릭, AJAX 요청, 애니메이션 등).
서버 측과 클라이언트 측의 관계
- 사용자가 웹 페이지를 요청하면, 서버 측(Django)은 HTML 문서를 생성하여 브라우저로 보냅니다.
- 이 HTML 문서는 Django 템플릿 태그로 작성되었을 수 있으며, 이 태그들은 서버에서 처리되고 최종 HTML로 변환됩니다.
- 브라우저(클라이언트 측)는 이 HTML 문서를 받아 사용자에게 표시하며, JavaScript는 브라우저에서 실행됩니다.
이렇게 서버 측에서 렌더링 된 결과를 클라이언트 측에서 사용할 수 있습니다. 하지만 JavaScript 코드 자체는 클라이언트에서 실행되기 때문에, 실행 시점에 서버 측에 영향을 미치지는 않습니다.
그래서 script 함수 내부에서는 장고 템플릿 코드를 사용할 수 없습니다.
<script>
$(document).ready(function(){
function renderList() {
$.ajax({
url: "{% url 'list_data_url' %}"; // 이렇게 사용 할 수 없습니다.
// 생략...
});
}
});
</script>
'Python > Django' 카테고리의 다른 글
django에서 *args, **kwargs (0) | 2023.07.25 |
---|---|
get_user_model() (0) | 2023.07.22 |
Django ORM에서 던더(__) (0) | 2023.07.07 |
Type hint 적용후 circular dependency 문제 해결법 (0) | 2023.06.30 |
FK 관계를 설정하는 방법 (0) | 2023.06.30 |
언더스코어 두 개 (__
)는 Django ORM에서 사용되는 문법입니다. 이를 "던더" 또는 "더블 언더스코어"라고도 합니다.
__
를 사용하여 필드 이름과 조건을 연결하여 데이터베이스 쿼리를 구성할 수 있습니다. 이를 통해 관련된 모델들 간의 관계를 표현하고, 필터링 또는 관련된 데이터를 가져올 수 있습니다.
예를 들어,
모델의 구조는 아래와 같습니다.
class Department(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
is_it = models.BooleanField(default=False)
explain = models.CharField(max_length=255, blank=True, default="")
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True)
# ... 생략 ...
이 경우 it 부서의 유저 프로필만 가져온다면 아래와 같이 작성할 수 있습니다.
user_profiles = UserProfile.objects.filter(
department__is_it=True
)
department__is_it=True
는 UserProfile
의 department
필드의 is_it
속성을 필터링하는 부분입니다. __
을 사용하여 관련된 모델인 Department
의 is_it
필드에 접근하고 비교 조건을 설정합니다.
즉, __
를 사용하면 관련된 모델 간의 필드를 참조하고, 관련된 데이터를 가져오는 데 사용할 수 있습니다.
'Python > Django' 카테고리의 다른 글
get_user_model() (0) | 2023.07.22 |
---|---|
django 템플릿 <script>태그 (0) | 2023.07.08 |
Type hint 적용후 circular dependency 문제 해결법 (0) | 2023.06.30 |
FK 관계를 설정하는 방법 (0) | 2023.06.30 |
(Django) reverse와 reverse_lazy 차이 (0) | 2023.06.23 |