WTMO-dev
AI
CV
basic
DL
basic
ML
basic
NLP
basic
dspy
hugging face
llama index
ollama
C++
basic
COMPUTER SCIENCE
basic
ETC
GIT
Blog
basic
IDE
VSC
python
setting
JAVA
basic
MATH
Basic
Statistic
NETWORK
basic
OS
Window
WSL
basic
basic
PROJECT
PYTHON
Advance
Basic
Framework
Django
FastAPI
Library
Module
Home
PROJECT PRACTICE
Crawling
EDA
Kaggle
Python
CV
Contact
Copyright © 2024
WTMO-dev
Home
>
PYTHON
>
Framework
> Django
Now Loading ...
Django
Django relations
How to use relations in Django relation은 모델을 더욱 유연하고 연결성이 좋게 만들 수 있습니다. 잘못 설정할 경우 오히려 복잡해지기도 하며, 아래의 방식을 참조하여 정확하게 설정해야 합니다. Django에서는 다음 방식의 relation key가 있습니다. Foriegn Key(many to one) 일반적으로 가장 흔하게 사용되는 관계입니다. 다중값을 가져와야하여 query로 값이 나오게 됩니다. one to one 1대1로 매칭이 되는 상황에서 사용이 가능하며 object를 바로 가져오는 방식이 가능합니다. many to many 관계가 종속적이라기 보다 상호관계를 가지게 되는 형태로 가장 일반적이지 못한 형태입니다. Field of model model의 column들을 정의 하는 field는 다음과 같이 사용할 수 있습니다. Field Option Field의 옵션은 다음과 같으며 모든 Field가 모든 옵션을 사용할 수는 없습니다. Field 옵션 설명 to 필드의 기본값을 설정합니다. related_name 추상 모델에서 관계를 정의할 때 사용될 이름을 의미합니다. on_delete 개체가 제거될 때의 동작을 설정합니다. db_column 데이터베이스의 컬럼의 이름을 설정합니다. limite_choices_to json형식으로 데이터베이스의 컬럼의 옵션을 추가해 filter를 적용합니다. 다음은 on_delete일때 외래키의 작동요건을 나타냅니다. on_delete 의미 models.CASCADE 외래키를 포함하는 행도 함께 삭제 models.PROTECT 해당 요소가 함께 삭제되지 않도록 오류 발생 (ProtectedError) models.SET_NULL 외래키 값을 NULL 값으로 변경 (null=True일 때 사용 가능) models.SET(func) 외래키 값을 func 행동 수행 (func는 함수나 메서드 등을 의미) models.DO_NOTHING 아무 행동을 하지 않음 외래키는 정규참조와 역참조로 이루어지는데 일반적인 방식의 반대가 역참조입니다. 역참조는 일반참조와 달리 사용방법이 달라집니다. related_name이 선언되어 있지 않으면 (1)와 같이 역참조가 가능하며 선언되어 있으면 (2)와 같이 참조가 가능합니다. (2)번 방식이 일반적으로 선호됩니다. 혹시나 2개이상의 참조를 하는 경우 (1)번 방식은 동작을 하지 않기 때문입니다. (1) {% highlight shell %} job1 = .objects.get(id = 1) people = job1._set.all() {% endhighlight %} (2) {% highlight shell %} job1 = .objects.get(id = 1) people = job1..all() {% endhighlight %}
PYTHON
/
Framework
/
Django
· 2024-03-28
Django advance
Advance HttpRequest HttpRequest.headers # request의 headers 객체 HttpRequest.body # request의 body 객체 HttpRequest.COOKIES # 모든 쿠키를 담고 있는 딕셔너리 객체 HttpRequest.method # reqeust의 메소드 타입 HttpRequest.FILES # 로 보낸 UploadFile! HttpRequest.META # HTTP 헤더가 포함하는 모든 접근 가능한 정보를 담고 있는 dict, 메타 정보는 (당연히) web-server에 영향을 받는다. HttpRequest.GET # GET 파라미터를 담고 있는 QueryDict instance HTTpRequest.POST # POST 파라미터를 담고 있는 QueryDict instance queryDict instance Query Expression F function python에서 핸들링 하는것이 아닌 Query로 만들어서 database에서 핸들링을 할 수 있는 방법입니다. {% highlight python %} User.objects.all().update(user_id=F(‘user_id’) + 1) # Base company = Company.objects.annotate(chairs_needed=F(‘num_employees’) - F(‘num_chairs’)) # annotate same field from django.db.models import DateTimeField, ExpressionWrapper, F Ticket.objects.annotate( expires=ExpressionWrapper( F(‘active_at’) + F(‘duration’), output_field=DateTimeField() ) ) # annotate different field {% endhighlight %} Docs Func function Func 방식은 Django에서 구현되지 않은 query의 구문을 사용하고자 할때 활용 가능합니다. {% highlight python %} class UNNEST(Func): function = ‘UNNEST’ temp = Test.objects.annotate(user=UNNEST(‘user’)) {% endhighlight %} Func Q function Q 방식은 Django에서 구현되어 있는 구현체로 조건들을 활용할때 사용하기 좋습니다. {% highlight python %} Product.objects.filter(Q(category=’A’) & Q(sub_category=’AB’)) {% endhighlight %} Value function Value는 기본적인 형태로 단순한 값을 의미합니다. {% highlight python %} User.objects.filter(“user”, Value(“_”), “id”) {% endhighlight %} annotate function annotate는 별칭을 주는것과 같으며 nested와 같은 구조에서 명칭이 복잡할때 사용 가능합니다. {% highlight python %} logs = OrderLog.objects.annotate( name=F(“product__name”), price=F(“product__price”) ).values( ‘created’, ‘name’, ‘price’ ) {% endhighlight %} subquery function subquery는 query를 사용하여 query를 만드는 복잡한 형태의 query를 구성할때 사용합니다. {% highlight python %} from django.db.models import OuterRef, Subquery newest = Comment.objects.filter(post=OuterRef(‘pk’)).order_by(‘-created_at’) Post.objects.annotate(newest_commenter_email=Subquery(newest.values(‘email’)[:1])) {% endhighlight %} Transaction database에서 일관적으로 한번에 작업이 되어야하는 단위를 transaction 이라합니다. 이를 통하여 안정된 서비스를 구현할 수 있으나 과도한 transaction은 오히려 서비스를 느리게 만들 수 있습니다. {% highlight python %} from django.db import transaction @transaction.atomic() def update_user(user_id: int, updated_company_name: str): Profile.objects.filter(user__id=user_id).update(company_name=updated_company_name) User.objects.filter(id=user_id).update(company_name=updated_company_name) {% endhighlight %} commit() transaction을 종료하며 저장합니다. rollback() transaction을 종료하며 처음으로 돌아갑니다. on_commit() transaction commit 종료 이후에 동작이 되야할 경우 사용 savepoint() transaction 도중에 savepoint를 지정하여 commit 또는 rollback같은 작업을 할 수 있습니다. Signal signal은 main logic과 별개로 실행해야하는 작업이 있을때 사용할 수 있습니다. 하지만 비동기적으로 작동되는 로직이 아니라서 celery와 같은것을 활용하는것을 추천합니다. {% highlight python %} 우선 signals.py 를 특정 앱(여기선 user) 안에 만든다. from django.db.models.signals import post_save from django.contrib.auth.models import User def create_profile(sender, instance, created, **kwargs): if created == True: user = instance profile = Profile.objects.create( owner = user, user_name = user.username, email = user.email, name = user.first_name, ) post_save.connect(create_profile, sender=User) 아래에서 더 자세히 보겠지만, connect를 쓰기 싫으면, 아래 app config를 진행하면 된다. signal의 코드 분리를 위해 app config에서, app이 load 될 때 signal을 import하게 한다. (user) apps.py class UserConfig(AppConfig): name = ‘user’ def ready(self) -> None: # DB signal import app.user.signals return super().ready() {% endhighlight %}
PYTHON
/
Framework
/
Django
· 2024-03-27
Django view
What is View How to use View view를 사용하는 방식은 Fuction, Class 두가지 방식이 있습니다. 원래의 Django는 Fuction으로 구성되어 있었으나 OOP의 장점을 이용하는 Class 형식이 추후에 추가 되었습니다. FBV 다음은 Fuction을 사용한 View의 기본 예제입니다. {% highlight python %} @api_view([‘GET’, ‘POST’]) def index(request): if request.method == ‘POST’: return HttpResponse(“Post method”) else: return HttpResponse(“Get method”) {% endhighlight %} CBV 다음은 class를 사용한 View의 기본 예제입니다. 이러한 방식은 상속과 같이 확장성을 가지지만 모든 상황에서 최선은 아닙니다. {% highlight python %} from django.views import View class ContactView(View): def post(self, request): return HttpResponse(“Post method”) def get(self, request): return HttpResponse(“Get method”) {% endhighlight %} {% highlight python %} quickstart/views.py from django.http import HttpResponse, JsonResponse from django.views.decorators.csrf import csrf_exempt from rest_framework.parsers import JSONParser # 그냥 json 파싱만 위해,, @csrf_exempt def snippet_list(request): “”” List all code snippets, or create a new snippet. “”” if request.method == ‘GET’: snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return JsonResponse(serializer.data, safe=False) elif request.method == 'POST': data = JSONParser().parse(request) serializer = SnippetSerializer(data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data, status=201) return JsonResponse(serializer.errors, status=400) {% endhighlight %} Prev(how to start) Prev
PYTHON
/
Framework
/
Django
· 2024-03-26
Django serializer
What is serializer Django의 serializer는 많은 역활을 담당합니다. 그중 대표적인 사용처는 json <-> dict 형태로의 치환을 주로 해주게 됩니다. 이러한 이유는 rest api에서 사용하는 형식과 python에서 사용하는 형식이 다르기 때문입니다. normal serializer 일반적인 seriallizer는 serializers.Serializer의 상속을 받아 아래와 같이 작성하게 됩니다. {% highlight python %} class UserSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) name = serializers.CharField(required=False, allow_blank=True, max_length=10) def create(self, validated_data): return models.User.objects.create(**validated_data) {% endhighlight %} 위와 같은 방식은 model과 상관없이 serializer를 설정하고 싶을때 사용할 수 있으며, model을 활용하여 사용하는 방법도 있습니다. model serializer model seriallizer는 serializers.ModelSerializer의 상속을 받아 아래와 같이 작성하게 됩니다. 아래의 방식은 model이 선언되어 있을때 사용하기 용이하며 코드를 간편하게 해줍니다. {% highlight python %} class UserSerializer(serializers.ModelSerializer): class Meta: model = models.User fields = [‘id’, ‘name’] {% endhighlight %} method field method field는 다른 field를 활용하여 재가공하여 사용하는 방식입니다. 대표적으로 id값이 있고 id의 길이를 확인하는 방법입니다. {% highlight python %} class UserSerializer(serializers.ModelSerializer): is_long = serializers.SerializerMethodField() class Meta: model = models.User fields = ['id', 'name'] def get_is_long(self, instance: CheckedCrn): if len(instance.id) > 2: return "long" else: return "short" {% endhighlight %} dict -> json -> dict 때에 따라서는 데이터의 형태가 계속 변경이 되어야 할 수 있습니다. 그에따라 형변환을 하는 법을 나타냅니다. {% highlight python %} import io from rest_framework.renderers import JSONRenderer content = JSONRenderer().render(serializer.data) # json stream = io.BytesIO(content) data = JSONParser().parse(stream) serializer = UserSerializer(data=data) serializer.is_valid() serializer.validated_data # check data serializer.save() serializer.data # dict {% endhighlight %} nested serializer N in (1:N) 1:N 의 형식에서 N의 입장은 다음과 같이 바로 활용이 가능합니다. seriallizer {% highlight python %} class GroupOnlySerializer(serializers.ModelSerializer): class Meta: model = Group fields = “all” class UserWithGroupSerializer(serializers.ModelSerializer): product = GroupOnlySerializer(read_only=True) class Meta: model = User fields = "__all__" {% endhighlight %} view {% highlight python %} class UserListAPIView(generics.ListAPIView): “”” User GET ALL API “”” queryset = User.objects.all().order_by(“-id”) serializer_class = UserWithGroupSerializer {% endhighlight %} 1 in (1:N) 1:N 의 형식에서 1의 입장은 역참조를 해야 하기 때문에 조금은 복잡합니다. Read case seriallizer {% highlight python %} class GroupSerializer(serializers.ModelSerializer): class Meta: model = Group fields = “all” class UserSerializer(serializers.ModelSerializer): product = GroupSerializer(read_only=True, many=True) class Meta: model = User fields = "__all__" {% endhighlight %} view {% highlight python %} class UserListAPIView(generics.ListAPIView): “”” User GET ALL API “”” queryset = User.objects.all().order_by(“-id”) serializer_class = UserSerializer {% endhighlight %} Write case write case에서는 원래 read만 가능하기 때문에 create를 override하여 새로이 구성해줘야 합니다. seriallizer {% highlight python %} class GroupSerializer(serializers.ModelSerializer): class Meta: model = Group fields = “all” class UserSerializer(serializers.ModelSerializer): product = GroupSerializer(read_only=True, many=True) class Meta: model = User fields = "__all__" {% endhighlight %} view {% highlight python %} class UserListAPIView(generics.ListAPIView): “”” User GET ALL API “”” queryset = User.objects.all().order_by(“-id”) serializer_class = UserSerializer def create(self, validated_data): groups = validated_data.pop(‘group’) user = User.objects.create(**validated_data) for group in groups: Group.objects.create(user=user, **group) return user {% endhighlight %} Prev(how to start) Prev
PYTHON
/
Framework
/
Django
· 2024-03-25
Django models
What is model Django에서 model은 DB의 구조를 나타내어집니다. How to use model model의 사용법은 다음과 같습니다. <app-name>.models.py 생성 {% highlight shell %} from django.contrib.auth.models import User from django.db import models class UserDetail(models.Model): user = models.ForeignKey( User, verbose_name=”user 정보”, on_delete=models.DO_NOTHING ) user_email = models.IntegerField(verbose_name=”user email”, null=False, primary_key=True) class Meta: db_table = "userdetail" managed = True verbose_name = "user 상세 정보" verbose_name_plural = "user 상세 정보 목록" {% endhighlight %} <app-name>.admin.py 추가(case 1) {% highlight shell %} from django.contrib import admin from .models import Cart class CartAdmin(admin.ModelAdmin): # admin 페이지에 표기할 column 지정 list_display = (‘', '') admin.site.register(Cart, CartAdmin) # admin page에 등록 {% endhighlight %} <app-name>.admin.py 추가(case 2) {% highlight shell %} from django.contrib import admin from .models import Cart @admin.register(Cart) # admin page에 등록 class CartAdmin(admin.ModelAdmin): # admin 페이지에 표기할 column 지정 list_display = (‘', '') {% endhighlight %} Field of model model의 column들을 정의 하는 field는 다음과 같이 사용할 수 있습니다. ID Field Field 타입 설명 AutoField 1에서 부터 자동적으로 증가합니다. BigAutoField 1 ~ 9223372036854775807까지 1씩 자동으로 증가하는 필드입니다. UUIDField UUID 전용 필드입니다. String Field Field 타입 설명 CharField 적은 문자열을 저장하는 필드입니다. TextField 많은 문자열을 저장하는 필드입니다. URLField URL을 저장하는 필드입니다. EmailField E-mail을 저장하는 필드입니다. String Field Field 타입 설명 CharField 적은 문자열을 저장하는 필드입니다. Data Field Field 타입 설명 BinaryField Binary 데이터를 저장하는 필드입니다. DecimalField Decimal 데이터를 저장하는 필드입니다. IntegerField Interger 데이터를 저장하는 필드입니다. PositiveIntegerField 양수만 취급하는 Interger 데이터를 저장하는 필드입니다. FloatField Float 데이터를 저장하는 필드입니다. BooleanField 참/거짓 데이터를 저장하는 필드입니다. NullBooleanField Null값이 가능한 참/거짓을 저장하는 필드입니다. Time Field Field 타입 설명 DateField 날짜 데이터를 저장하는 필드입니다. TimeField 시간 데이터를 저장하는 필드입니다. DateTimeField 날짜와 시간 데이터 모두 저장할 수 있는 필드입니다. File Field Field 타입 설명 ImageField 이미지 데이터를 저장하는 필드입니다. FileField 파일 업로드 데이터를 저장하는 필드입니다. FilePathField 파일 경로 데이터를 저장하는 필드입니다. Relation Field Field 타입 설명 OneToOneField 일대일 관계를 저장하는 필드입니다. ForeignKey 일대다 관계를 저장하는 필드입니다. ManyToManyField 다대다 관계를 저장하는 필드입니다. 더 많은 정보는 다음에 포함되어 있습니다. relations Field Option Field의 옵션은 다음과 같으며 모든 Field가 모든 옵션을 사용할 수는 없습니다. Field 옵션 설명 기본값 default 필드의 기본값을 설정합니다. - help_text 도움말 텍스트를 설정합니다. - null Null 값 허용 유/무를 설정합니다. False blank 비어있는 값 허용 유/무를 설정합니다. False unique 고유 키 유/무를 설정합니다. False primary_key 기본 키 유/무를 설정합니다. (null=False, unique=True와 동일) False editable 필드 수정 유/무를 설정합니다. False max_length 필드의 최대 길이를 설정합니다. - auto_now 개체가 저장될 때마다 값을 설정합니다. False auto_now_add 개체가 처음 저장될 때 값을 설정합니다. False on_delete 개체가 제거될 때의 동작을 설정합니다. - db_column 데이터베이스의 컬럼의 이름을 설정합니다. - Meta Option Meta 옵션은 다음과 같습니다. Meta 옵션 설명 기본값 abstract 추상 클래스 유/무를 설정합니다. False db_table 모델에 사용할 데이터베이스 테이블의 이름을 설정합니다. - managed 데이터베이스의 생성, 수정, 삭제 등의 권한을 설정합니다. True ordering 객체를 가져올 때의 정렬 순서를 설정합니다. - verbose_name 사람이 읽기 쉬운 객체의 이름을 설정합니다. (단수형으로 작성) - verbose_name_plural 사람이 읽기 쉬운 객체의 이름을 설정합니다. (복수형으로 작성) - model manager model은 기본적으로 objects를 manager로 가지게 되어있습니다. 하지만 아래와 같이 override할 수 있습니다. {% highlight shell %} class DeletedManager(models.Manager): use_for_related_fields = True # default manager로 사용시 관계에서 모두 활용 가능 def deleted(self, **kwargs): return self.filter(is_deleted=False, **kwargs) def get_queryset(self): return super().get_queryset().filter(is_deleted=False) {% endhighlight %} {% highlight shell %} class Post(models.Model): objects = DeletedManager() {% endhighlight %} structure of model 구조는 위에 나열한 Field를 추가하여 주면 되며, Meta를 사용한 abstract기능을 True로 해주면 상속을 할 수 있는 상태가 됩니다. 아래는 default로 있는 User정보의 abstract를 활용한 예시입니다. Mixedin은 2개이상의 상속을 받을때 사용하며, abstract와 같으나 명칭만 다릅니다. {% highlight python %} class User(AbstractBaseUser, PermissionsMixin): objects = UserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['nickname', ] class Meta: ordering = ('-date_joined',) def __str__(self): # object 호출시 지정할 명칭 return self.nickname {% endhighlight %} migration migration은 DB와 코드간의 상태를 확인하는 작업입니다. 아래의 코드는 migration을 하는데 있어 주로 사용되는 코드입니다. {% highlight shell %} python manage.py showmigrations # migration의 상태확인 python manage.py makemigrations # migration 생성 python manage.py migrate # migration 적용 python manage.py –fake zero # 의 migration 초기화 python manage.py --fake-initial # fake migration 생성 {% endhighlight %}
PYTHON
/
Framework
/
Django
· 2024-03-22
Django rest api
How to start Django restfulAPI Django를 활용하여 REST API를 만드는데 최적화 되어 있는 모듈입니다. 다음의 방식으로 다운받을 수 있습니다. {% highlight shell %} pip install djangorestframework pip install markdown # Markdown support for the browsable API. pip install django-filter # Filtering support {% endhighlight %} setting.py {% highlight python %} INSTALLED_APPS = [ # default setting …, ‘rest_framework’, ] REST_FRAMEWORK = [ # additional pagination setting ‘DEFAULT_PAGINATIOM_CLASS’: ‘rest_framework.pagination.pageNumberPagination’, ‘PAGE_SIZE’: 50 ] {% endhighlight %} Next step models serializers views Prev(how to start) Prev
PYTHON
/
Framework
/
Django
· 2024-03-21
Django additional module
What is Django debug toolbar Django의 webpage들에서 debug 정보를 바로 확인하기 위한 middleware입니다. How to setting 다음은 Django debug toolbar를 설치하는 방법입니다. django-debug-toolbar 설치 {% highlight shell %} pip install django-debug-toolbar {% endhighlight %} <proj-name>.settings.py에서 확인, 추가 {% highlight python %} INSTALLED_APPS = [ # … “django.contrib.staticfiles”, # … ] STATIC_URL = “static/” {% endhighlight %} <proj-name>.settings.py에서 확인, 추가 {% highlight python %} TEMPLATES = [ { “BACKEND”: “django.template.backends.django.DjangoTemplates”, “APP_DIRS”: True, # … } ] {% endhighlight %} <proj-name>.settings.py에 추가 {% highlight python %} INSTALLED_APPS = [ # … “debug_toolbar”, # … ] {% endhighlight %} <proj-name>.urls.py에 추가 {% highlight python %} from django.conf import settings if settings.DEBUG: import mimetypes mimetypes.add_type(“application/javascript”, “.js”, True) import debug_toolbar urlpatterns += [ path(r’^debug/’, include(debug_toolbar.urls)), ] {% endhighlight %} <proj-name>.settings.py에 추가 {% highlight python %} MIDDLEWARE = [ # … “debug_toolbar.middleware.DebugToolbarMiddleware”, # … ] {% endhighlight %} <proj-name>.settings.py에 추가 {% highlight python %} INTERNAL_IPS = [ # … “127.0.0.1”, # ... ] {% endhighlight %} 위의 방식을 전부 완료하고 나서 Django proj를 실행하면 오른쪽에 debug toolbar가 보여집니다. 혹시나 보여지지 않으시다면 아래의 코드를 추가해주세요. <proj-name>.urls.py에 추가 {% highlight python %} import mimetypes mimetypes.add_type(“application/javascript”, “.js”, True) {% endhighlight %} What is Django celery Django에서 celery를 활용하여 worker와 broker를 사용하는 기능입니다. How to setting 다음은 Django celery(W.redis)를 설치하는 방법입니다. <proj-name>.celery.py 생성 {% highlight python %} import os from celery import Celery Set the default Django settings module for the ‘celery’ program. os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’, ‘mysite.settings’) app = Celery(‘projs’) Using a string here means the worker doesn’t have to serialize the configuration object to child processes. - namespace=’CELERY’ means all celery-related configuration keys should have a CELERY_ prefix. app.config_from_object(‘django.conf:settings’, namespace=’CELERY’) Load task modules from all registered Django apps. app.autodiscover_tasks() @app.task(bind=True, ignore_result=True) def debug_task(self): print(f’Request: {self.request!r}’) {% endhighlight %} <proj-name>.settings.py에 추가 {% highlight python %} CELERY_BROKER_URL = ‘redis://127.0.0.1:6379/0’ CELERY_RESULT_BACKEND = ‘redis://127.0.0.1:6379/0’ CELERY_ACCEPT_CONTENT = [‘application/json’] CELERY_RESULT_SERIALIZER = ‘json’ CELERY_TASK_SERIALIZER = ‘json’ CELERY_TIMEZONE = ‘Asia/Seoul’ CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True {% endhighlight %} <proj-name>.__init__.py에 추가 {% highlight python %} from .celery import app as celery_app all = (‘celery_app’,) {% endhighlight %} shared_task 데코레이터를 사용한 함수 delay로 실행 {% highlight python %} from celery import shared_task {% endhighlight %} 위와 같이 코드를 완성하고 나서 다음의 코드로 celery를 구동시키면 사용이 가능합니다. {% highlight shell %} celery -A worker -l INFO {% endhighlight %}
PYTHON
/
Framework
/
Django
· 2024-03-21
Django intro
What is Django Django python으로 구현된 web framework입니다. Getting start 다음은 아주 기본적인 django 의 실행방식입니다. {% highlight shell %} pip install Django # Django 설치 python -m django –version # Django 설치 확인 django-admin startproject # 프로젝트 생성 cd python manage.py runserver # 프로젝트 실행 {% endhighlight %} 다음은 startproject로 생성되는 파일의 구조입니다. <proj-name>/ manage.py <proj-name>/ __init__.py settings.py urls.py asgi.py wsgi.py Creating App 다음은 django에서 App을 만들고 연결하는 방법입니다. {% highlight shell %} python manage.py startapp # create App {% endhighlight %} 다음은 startapp으로 생성되는 dir의 구조 입니다. <app-name>/ __init__.py admin.py apps.py migrations/ __init__.py models.py tests.py urls.py views.py <app-name>/views.py {% highlight python %} from django.http import HttpResponse def index(request): return HttpResponse(“Hello, world. You’re at the polls index.”) {% endhighlight %} <app-name>/urls.py {% highlight python %} from django.urls import path from . import views urlpatterns = [ path(“”, views.index, name=”index”), ] {% endhighlight %} <proj-name>/urls.py {% highlight python %} from django.contrib import admin from django.urls import include, path urlpatterns = [ path(“/", include(".urls")), path("admin/", admin.site.urls), ] {% endhighlight %} Setting database 다음은 django에서 database를 세팅하는 방법입니다. Django는 기본으로 SQLite를 활용하지만 설정을 변경하여 수정이 가능합니다. mysql 다음은 mysql 예시입니다. 필수 모듈 설치 {% highlight shell %} pip install mysqlclient {% endhighlight %} <proj-name>.settings.py에 DB 옵션변경 {% highlight python %} DATABASES = { ‘default’: { ‘ENGINE’: ‘django.db.backends.mysql’, ‘NAME’: ‘', 'USER': '', 'PASSWORD': '', 'HOST': 'localhost', 'PORT': '3306', } } {% endhighlight %} postgre 다음은 postgre 예시입니다. 필수 모듈 설치 {% highlight shell %} pip install psycopg2 {% endhighlight %} postgre setting {% highlight shell %} sudo su - postgres # postgre 실행 psql CREATE DATABASE django_test; # postgre 유저 및 DB 생성 CREATE USER django_user WITH PASSWORD ‘django_pass’; ALTER ROLE django_user SET client_encoding TO ‘utf8’; ALTER ROLE django_user SET default_transaction_isolation TO ‘read committed’; ALTER ROLE django_user SET timezone TO ‘UTC’; GRANT ALL PRIVILEGES ON DATABASE django_test TO django_user; \q {% endhighlight %} <proj-name>.settings.py에 DB 옵션변경 {% highlight python %} DATABASES = { ‘default’: { ‘ENGINE’: ‘django.db.backends.mysql’, ‘NAME’: ‘', 'USER': '', 'PASSWORD': '', 'HOST': 'localhost', 'PORT': '3306', } } {% endhighlight %} Next(Web page) Next Next(Rest API) Next
PYTHON
/
Framework
/
Django
· 2024-03-20
Django init summary
Django django-debug-toolbar -> 디버그 내용 확인 용이 INSTALLED_APPS “debug_toolbar” MIDDLEWARE “debug_toolbar.middleware.DebugToolbarMiddleware” INTERNAL_IPS “IP” djangorestframework -> restAPI 제작에 용이 django-ninja -> djangorestframework의 느린 serializer 대신 pydantic 사용 swagger 지원 POSTMAN 같은것 Async 지원 api version 지원 django-seed -> db에 임시 데이터 뿌려줌 INSTALLED_APPS “django_seed” cmd: python manage.py seed <app_name> --number=<num> 서버 기본 세팅 {% highlight shell %} 프로젝트 생성 구문 django-admin startproject 프로젝프 앱 생성 구문 cd python /manage.py startapp 프로젝프 슈퍼 유저 생성 python /manage.py createsuperuser 프로젝프 기본 마이그레이션 python /manage.py migrate 프로젝프 추가 제작한 마이그레이션 (오류발생시 setting.py -> INSTALLED_APPS에 추가) python /manage.py makemigrations 서버 구동 구문 python \manage.py runserver {% endhighlight %} 유저 테이블 제작(models) 커스텀 유저 테이블을 제작하는데 있어서 직접 제작이 가능하며 아래의 방법들이 있다. 추상화 유저 제작 {% highlight python %} from django.contrib.auth.models import AbstractUser class Users(AbstractUser): pay_plan = models.ForeignKey(PayPlan, on_delete=models.DO_NOTHING) {% endhighlight %} setting.py에 AUTH_USER_MODEL = ‘<app_name>.Users’ 추가해야함 장고 모듈 활용 유저 제작 {% highlight python %} from django.contrib.auth.models import User as U class UserDetail(models.Model): user = models.OneToOneField(U, on_delete=models.CASCADE) pay_plan = models.ForeignKey(PayPlan, on_delete=models.DO_NOTHING) {% endhighlight %} 두개를 모두 사용할 경우 oneToOneField의 입력이 추상화의 Users를 가르켜야한다. view_html urls.py url 패턴을 이용하여 입력받는 주소로 부터 사용할 view단과 연결을 해준다. {% highlight python %} from app_test.views import index, redirect_test urlpatterns = [ path(‘’, index , name=’index’), path(‘redirect’, redirect_test), ] {% endhighlight %} view.py urls.py에 연결된 view단을 세팅하는 부분 base.html과 같은경우는 <app_name>/templates 폴더에 둔다. {% highlight python %} 모델(DB)에서 참조할시 해당 모델 추가사항 from .models import Users 모델에서 유저정보를 받아서 보여지는 결과를 다르게 한 예시 def index(request): user = Users.objects.filter(username=”admin”).first() email = user.email if user else “Nooooo” print(email) print(request.user.is_authenticated) if not request.user.is_authenticated: email = “NOoooooooooooooo” print(email) return render(request, “base.html”, {“welcome_msg”: f”Hello {email}”}) 재참조 형식의 view단 예시 def redirect_test(request): return redirect(“index”) {% endhighlight %} view_restAPI urls.py url 패턴을 이용하여 입력받는 주소로 부터 사용할 view단과 연결을 해준다. <int:user_id>는 query string 사용법 {% highlight python %} urlpatterns = [ path(‘get_user/', get_user), ] {% endhighlight %} view.py urls.py에 연결된 view단을 세팅하는 부분 csrf_exempt는 token 인증을 임시로 풀기위한것 body가 아닌 JsonResponse는 보통 개발자들끼리 내용을 주고 받을때 사용하기도 한다. {% highlight python %} from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt @csrf_exempt def get_user(request, user_id): print(user_id) if request.method == “GET”: abc = request.GET.get(“abc”) xyz = request.GET.get(“xyz”) user = Users.objects.filter(pk=user_id).first() return render (request, “base.html”, {“user”: user, “params”: [abc, xyz]}) elif request.method == “POST”: username = request.GET.get(“username”) if username: user = Users.objects.filter(pk=user_id).update(username=username) return JsonResponse(status=201, data=dict(msg=”POST is”)) {% endhighlight %} admin_handling1 admin.py admin page에서 model을 핸들링 가능하게 해준다. {% highlight python %} from .models import PayPlan Register your models here. admin.site.register(PayPlan) {% endhighlight %} django original login setting urls.py 세팅 views.py {% highlight python %} from django.contrib.auth import authenticate, login from .forms import RegisterForm def register(request): if request.method == “POST”: form = RegisterForm(request.POST) msg = “not valid data” if form.is_valid(): form.save() # db에 저장(commit=False로 임시저장가능) username = form.cleaned_data.get(“username”) raw_password = form.cleaned_data.get(“password1”) user = authenticate(username= username, password= raw_password) # 인증 login(request, user) # 로그인 msg = “login” return render(request, “register.html”, {“form”: form, “msg”: msg}) else: form = RegisterForm() return render(request, “register.html”, {“form”: form}) {% endhighlight %} forms.py {% highlight python %} from django import forms from django.contrib.auth.forms import UserCreationForm from .models import Users class RegisterForm(UserCreationForm): username = forms.CharField(max_length=20, required=True, help_text=”name”, label=”이름”) email = forms.EmailField(max_length=20, required=False, help_text=”email”, label=”이메일”) class Meta: model = Users fields = ( "username", "email", "password1", "password2", ) {% endhighlight %} paginator views.py 페이지 분할 제작법 {% highlight python %} from django.core.paginator import Paginator def a(request): page = int(request.GET.get(“page”, 1)) = <>.objects.all().order_by("-id") # 정렬해야 "-"내림차순 paginator = Paginator(, 5) = paginator.get_page(page) return render(request, ".html", {"args": <datas>}) {% endhighlight %} login_required setting.py LOGIN_URL =”/<>” views.py 로그인 필수 페이지 세팅 {% highlight python %} from django.contrib.auth.decorators import login_required @login_required def a(request): {% endhighlight %} template tags 탬플렛을 제작하는데 있어서 조건이나 데이터 활용등을 위한 태그 {\% csrf_token \%} csrf token을 필요로 하다는것을 나타낼때 사용 {\% cycle “a” “b” \%} iter적인 상황에서 각 순서마다 서로 다른 영향을 주려고 할때 사용 {\% extends “.html" \%} 한 html에서 다른 html을 확장하여 사용할때 사용 자식페이지에 최상단에 필요하며 은 부모파일이다. {\% block \%} {\% endblock \%} 한 html에서 다른 html을 확장하여 사용할때 사용 부모페이지에서 자식을 넣을공간에, 자식페이지에서 넣을 내용을 감싼다. {\% if \%}{\% elsif \%}{\% else \%}{\% endif \%} 조건문을 사용할때 사용 {\% for i in items \%}{\% endfor \%} for문을 사용할때 사용 forloop.counter 루프의 인덱스(1시작) forloop.counter0 루프의 인덱스(0시작) forloop.first 루프의 첫번째 True forloop.last 루프의 마지막 True {\% includes “<filename>.html” \%} html에서 html 파일을 사용할때 사용할 <filename>을 작성 extends보다 느리다.(랜더링이 느리다.) {\% url “<namespace>” \%} <namespace>로 이동하게 할때 사용 {\% static “<filepath>” \%} <filepath>에 있는 static 파일 사용 <app_name>/static/<filepath>으로 구성 {\% load static \%}을 최상단에 작성해야함 custom tags 탬플렛을 제작하는데 있어서 <app_name>/templatetags/custom_tags.py {% highlight python %} from django import template from django.utils.html import mark_safe register = template.Library() @register.simple_tag(name=, takes_context=True) def tags_test(context): # context에는 해당 페이지 정보가 있으며 상세히 다룰 수 있다. tag_html = "태그" # mark_safe는 html로 사용해도 안전함을 알려줌 사용안하면 string으로 사용 return mark_safe(tag_html) {% endhighlight %} {\% load custom_tags \%} 태그 사용할 html 최상단에 적용 {{data|<tag_name>}} 태그 사용할 html 코드에 사용 custom filter 탬플렛을 제작하는데 있어서 원하는 내용만 보여주기 위하여 사용 <app_name>/templatetags/custom_filters.py {% highlight python %} from django import template register = template.Library() @register.filter(name=) def email_masker(value): email_split = value.split("@") return f"{email_split[0]}@******.***" {% endhighlight %} {\% load custom_filters \%} 필터 사용할 html 최상단에 적용 {{data|<filter_name>}} 필터 사용할 html 코드에 사용
PYTHON
/
Framework
/
Django
· 2023-08-25
Django unit test
What is serializer test test_base normal serializer 일반적인 seriallizer는 serializers.Serializer의 상속을 받아 아래와 같이 작성하게 됩니다. {% highlight python %} class UserSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True) name = serializers.CharField(required=False, allow_blank=True, max_length=10) def create(self, validated_data): return models.User.objects.create(**validated_data) {% endhighlight %} 위와 같은 방식은 model과 상관없이 serializer를 설정하고 싶을때 사용할 수 있으며, model을 활용하여 사용하는 방법도 있습니다. model serializer model seriallizer는 serializers.ModelSerializer의 상속을 받아 아래와 같이 작성하게 됩니다. 아래의 방식은 model이 선언되어 있을때 사용하기 용이하며 코드를 간편하게 해줍니다. {% highlight python %} class UserSerializer(serializers.ModelSerializer): class Meta: model = models.User fields = [‘id’, ‘name’] {% endhighlight %} method field method field는 다른 field를 활용하여 재가공하여 사용하는 방식입니다. 대표적으로 id값이 있고 id의 길이를 확인하는 방법입니다. {% highlight python %} class UserSerializer(serializers.ModelSerializer): is_long = serializers.SerializerMethodField() class Meta: model = models.User fields = ['id', 'name'] def get_is_long(self, instance: CheckedCrn): if len(instance.id) > 2: return "long" else: return "short" {% endhighlight %} dict -> json -> dict 때에 따라서는 데이터의 형태가 계속 변경이 되어야 할 수 있습니다. 그에따라 형변환을 하는 법을 나타냅니다. {% highlight python %} import io from rest_framework.renderers import JSONRenderer content = JSONRenderer().render(serializer.data) # json stream = io.BytesIO(content) data = JSONParser().parse(stream) serializer = UserSerializer(data=data) serializer.is_valid() serializer.validated_data # check data serializer.save() serializer.data # dict {% endhighlight %} nested serializer N in (1:N) 1:N 의 형식에서 N의 입장은 다음과 같이 바로 활용이 가능합니다. seriallizer {% highlight python %} class GroupOnlySerializer(serializers.ModelSerializer): class Meta: model = Group fields = “all” class UserWithGroupSerializer(serializers.ModelSerializer): product = GroupOnlySerializer(read_only=True) class Meta: model = User fields = "__all__" {% endhighlight %} view {% highlight python %} class UserListAPIView(generics.ListAPIView): “”” User GET ALL API “”” queryset = User.objects.all().order_by(“-id”) serializer_class = UserWithGroupSerializer {% endhighlight %} 1 in (1:N) 1:N 의 형식에서 1의 입장은 역참조를 해야 하기 때문에 조금은 복잡합니다. Read case seriallizer {% highlight python %} class GroupSerializer(serializers.ModelSerializer): class Meta: model = Group fields = “all” class UserSerializer(serializers.ModelSerializer): product = GroupSerializer(read_only=True, many=True) class Meta: model = User fields = "__all__" {% endhighlight %} view {% highlight python %} class UserListAPIView(generics.ListAPIView): “”” User GET ALL API “”” queryset = User.objects.all().order_by(“-id”) serializer_class = UserSerializer {% endhighlight %} Write case write case에서는 원래 read만 가능하기 때문에 create를 override하여 새로이 구성해줘야 합니다. seriallizer {% highlight python %} class GroupSerializer(serializers.ModelSerializer): class Meta: model = Group fields = “all” class UserSerializer(serializers.ModelSerializer): product = GroupSerializer(read_only=True, many=True) class Meta: model = User fields = "__all__" {% endhighlight %} view {% highlight python %} class UserListAPIView(generics.ListAPIView): “”” User GET ALL API “”” queryset = User.objects.all().order_by(“-id”) serializer_class = UserSerializer def create(self, validated_data): groups = validated_data.pop(‘group’) user = User.objects.create(**validated_data) for group in groups: Group.objects.create(user=user, **group) return user {% endhighlight %} Next step models serializers views Prev(how to start) Prev
PYTHON
/
Framework
/
Django
· 2023-01-01
Django web
W G {% highlight python %} {% endhighlight %} Next step models forms views Prev(how to start) Prev
PYTHON
/
Framework
/
Django
· 2023-01-01
<
>
Touch background to close