소스 : https://github.com/braverokmc79/djangocrm
산출물
1)회원가입
2)로그인
3)메인화면
4)영업사원 목록화면
5)영업사원 등록화면
6)상세화면
7)수정화면
1.Python Django 프로젝트 설치 과정 정리
1. 가상환경(Virtual Environment) 설정
Python의 가상환경을 설정하기 위해 virtualenv를 설치합니다.
- pip install virtualenv 명령어를 사용하여 설치합니다.
가상환경을 생성합니다.
- virtualenv <가상환경 이름> 명령어를 사용합니다.
- 예: virtualenv env
(이름은 원하는 대로 설정 가능)
생성된 가상환경을 활성화합니다.
- Windows: Scripts\activate
- Linux/Mac: source bin/activate
2. Django 설치
- 가상환경이 활성화된 상태에서 Django를 설치합니다.
- 특정 버전 설치: pip install django==3.1.4
- 최신 버전 설치: pip install django
3. Django 프로젝트 생성
- Django 프로젝트를 생성합니다.
- 명령어: django-admin startproject <프로젝트 이름>
예: django-admin startproject django_crm
- 명령어: django-admin startproject <프로젝트 이름>
- 생성된 프로젝트 폴더 구조를 확인합니다.
4. 개발 서버 실행
- 개발 서버를 실행하여 프로젝트가 제대로 생성되었는지 확인합니다.
- 명령어: python manage.py runserver
- 실행 후 브라우저에서 http://127.0.0.1:8000으로 접속하여 Django 기본 화면 확인.
5. 마이그레이션 적용
- Django의 데이터베이스 초기 설정을 적용합니다.
- 명령어: python manage.py migrate
- 실행 결과로 데이터베이스 파일(db.sqlite3)이 생성됩니다.
- 기본 데이터베이스는 SQLite이며, 필요에 따라 다른 DB로 변경 가능합니다.
6. 주요 명령어 요약
7. 추가 팁
- 프로젝트 개발 중 SQLite를 사용하지만, 실제 서비스에서는 더 강력한 데이터베이스(MySQL, PostgreSQL 등)를 사용하는 것을 권장합니다.
- 데이터베이스 변경 후 항상 migrate 명령을 실행해야 변경 사항이 반영됩니다.
- 필요 시 서버를 종료하려면 Ctrl + C를 누릅니다.
2.파이썬 장고 프로젝트 - 앱(App) 만들기
1. 앱(App)의 개념
- Django에서 앱(App)은 특정한 기능 또는 논리적인 단위를 처리하는 모듈.
- 예시:
- CRM 프로젝트에서 회원 관리를 처리하는 앱.
- 결제를 처리하는 앱.
- 인증과 관련된 앱.
- 논리적인 단위로 나눠 개발하며, 프로젝트 안에 여러 앱을 생성하여 기능을 분리.
2. 앱 생성하기
- 앱을 생성할 때는 manage.py 파일을 이용하여 명령어를 실행.
python manage.py startapp 앱이름 python manage.py startapp sales
3. 생성된 앱의 폴더 구조
- 생성된 앱 폴더는 아래와 같은 구조
sales/ ├── migrations/ # 데이터베이스 마이그레이션 관련 정보 ├── admin.py # 관리자 페이지 설정 ├── apps.py # 앱 설정 정보 ├── models.py # 데이터베이스 모델 정의 ├── tests.py # 테스트 코드 작성 ├── views.py # 브라우저에 렌더링할 작업 정의
4. 앱 등록하기
- 앱을 생성한 후 프로젝트에 등록해야 사용 가능.
- 등록 방법:
- settings.py 파일 열기
- INSTALLED_APPS 리스트에 앱 이름 추가.
INSTALLED_APPS = [ ..., 'sales', # 새로 생성한 앱 이름 ]
주의: 앱 이름은 정확히 입력해야 오류가 발생하지 않음.
요약:
- Django에서 앱은 논리적인 기능 단위로 나뉘며, 각 앱은 특정 역할을 수행.
- python manage.py startapp 앱이름 명령어로 앱을 생성.
- 생성된 앱은 settings.py의 INSTALLED_APPS에 등록해야 사용 가능.
- 각 앱은 데이터베이스, 관리자 설정, 뷰(View) 등을 포함한 구조로 생성됨.
3.장고(Django) 모델 생성 및 데이터베이스 만들기
1.모델 파일 설정
- models.py 파일을 열어 모델을 정의합니다.
- django.db.models에서 models를 import합니다.
- 데이터베이스 설계를 클래스 형태로 작성합니다.
from django.db import models class Sales(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) age = models.IntegerField(default=0)
클래스는 models.Model을 상속받으며, 각 필드에 적합한 데이터 타입(예: CharField, IntegerField)과 속성을 설정합니다.
2. 마이그레이션 생성
- 작성한 모델을 데이터베이스 설계도로 변환하는 단계입니다.
python manage.py makemigrations
이 과정에서 migrations 폴더에 설계도가 생성됩니다.
3.마이그레이션 적용
- 설계도를 실제 데이터베이스에 반영하는 단계입니다.
python manage.py migrate
데이터베이스에 테이블이 생성되고, 각 필드에 대응되는 컬럼이 만들어집니다.
4.데이터베이스 확인
SQLite를 사용하는 경우, 확장 프로그램을 설치하여 데이터베이스 구조를 확인할 수 있습니다.
- 추천 확장 프로그램: SQLite Viewer 또는 SQLTools.
- Visual Studio Code 사용 시:
- Command Palette에서 SQLite: Open Database를 선택하여 데이터베이스 확인 가능.
5.주요 사항
- 장고는 기본적으로 각 모델 클래스에 대해 id 필드를 자동 생성합니다.
- 모델 정의 후 반드시 makemigrations와 migrate를 순차적으로 실행해야 데이터베이스에 반영됩니다.
- 데이터베이스 구조를 변경할 경우, 변경 후 다시 위 과정을 반복해야 합니다.
요약 흐름
- models.py에서 데이터베이스 클래스 정의.
- makemigrations로 설계도 생성.
- migrate로 데이터베이스에 반영.
- SQLite Viewer 등을 통해 결과 확인.
4. 모델 (Model) 데이터 베이스 필드 추가 하기
from django.db import models class Sales(models.Model): 경로_선택 = ( ('nr', '네이버'), ('shop2', '샵투월드'), ('news', '이메일뉴스레터'), ) first_name = models.CharField(max_length=30) # 이름 필드 last_name = models.CharField(max_length=30) # 성 필드 age = models.IntegerField(default=0) # 나이 필드 (기본값 0) 기존고객 = models.BooleanField(default=False) # 기존 고객 여부 (True/False) 유입경로 = models.CharField(choices=경로_선택, max_length=200) # 유입 경로 인물사진 = models.ImageField(blank=True, null=True) # 인물 사진 필드 (비워둘 수 있음) 파일 = models.FileField(blank=True, null=True) # 파일 업로드 필드 (비워둘 수 있음)
정리 내용
기본 필드
- first_name, last_name: 고객의 이름과 성을 저장하는 문자열 필드입니다.
- max_length=30으로 최대 30자의 길이를 제한합니다.
- age: 고객의 나이를 저장하는 정수 필드입니다.
- default=0을 설정하여 기본값을 0으로 지정했습니다.
- first_name, last_name: 고객의 이름과 성을 저장하는 문자열 필드입니다.
추가 필드
- 기존고객: 기존 고객 여부를 나타내는 Boolean 필드입니다.
- default=False로 기본값이 False(기존 고객 아님)으로 설정됩니다.
- 유입경로: 고객의 유입 경로를 선택할 수 있는 필드입니다.
- 선택 가능한 값은 경로_선택 튜플에 정의되어 있습니다.
- choices 옵션을 통해 유입 경로 값을 제한하고, max_length=200으로 최대 길이를 제한합니다.
- 기존고객: 기존 고객 여부를 나타내는 Boolean 필드입니다.
이미지와 파일 업로드 필드
- 인물사진: 고객의 사진을 저장하는 이미지 필드입니다.
- blank=True, null=True 옵션으로 필수 입력이 아님을 설정했습니다.
- 파일: 업로드 파일을 저장하는 파일 필드입니다.
- 위와 동일하게 blank=True, null=True 옵션이 적용되었습니다.
- 인물사진: 고객의 사진을 저장하는 이미지 필드입니다.
choices 옵션 사용
- 경로_선택 튜플에 유입 경로의 선택지를 정의합니다.
- 'nr': 네이버
- 'shop2': 샵투월드
- 'news': 이메일 뉴스레터
- 이 값들은 관리 화면에서도 드롭다운 메뉴로 제공됩니다.
- 경로_선택 튜플에 유입 경로의 선택지를 정의합니다.
참고 내용
데이터베이스 필드에 대한 변경 사항을 반영하려면 다음 명령을 실행해야 합니다.
- 마이그레이션 생성
python manage.py makemigrations
2.마이그레이션 적용
python manage.py migrate
이미지와 파일 필드를 사용하려면 프로젝트에 Pillow 라이브러리를 설치해야 합니다.
pip install pillow
5.외래 키(Foreign Key) 정리
외래 키(Foreign Key)란?
- 외래 키는 데이터베이스 테이블 간의 관계를 정의하는 키입니다.
- 한 테이블에서 다른 테이블의 특정 행(row)을 참조하는 데 사용됩니다.
- 예: 판매 데이터(Sale)와 관련된 직원(Person)을 연결.
from django.db import models class Sale(models.Model): first_name = models.CharField(max_length=30) # 판매자의 이름 last_name = models.CharField(max_length=30) # 판매자의 성 age = models.IntegerField(default=0) # 판매자의 나이 person = models.ForeignKey( "Person", # 참조할 테이블 (Person) on_delete=models.CASCADE # 연관된 데이터 삭제 시 동작 설정 ) class Person(models.Model): first_name = models.CharField(max_length=30) # 직원 이름 last_name = models.CharField(max_length=30) # 직원 성 age = models.IntegerField(default=0) # 직원 나이
외래 키의 필요성
데이터 중복 방지
- 예를 들어, Sale(판매) 데이터와 Person(직원) 데이터를 하나의 테이블에 저장하면, 동일한 직원 정보가 반복적으로 저장되어 비효율적입니다.
- 대신 ForeignKey를 사용해 직원 정보를 별도의 테이블(Person)에 저장하고, Sale 테이블에서 참조하도록 하면 데이터가 깔끔하게 관리됩니다.
효율적인 관계 관리
- 한 직원이 여러 개의 판매 데이터를 가질 수 있는 다대일(Many-to-One) 관계를 효율적으로 표현할 수 있습니다.
외래 키 삭제 시 동작 설정 (on_delete)
- 외래 키는 관계된 데이터 삭제 시 동작을 반드시 지정해야 합니다. 그렇지 않으면 오류가 발생합니다.
- 주요 옵션:
models.CASCADE
- 참조된 객체가 삭제되면, 연관된 객체도 함께 삭제됩니다.
- 예: 직원(Person)이 삭제되면, 해당 직원과 관련된 모든 판매(Sale) 데이터도 삭제됨.
models.SET_NULL
- 참조된 객체가 삭제되면, 외래 키 필드를 NULL로 설정합니다.
- 사용 시, null=True 옵션 필요.
models.SET_DEFAULT
- 참조된 객체가 삭제되면, 외래 키 필드를 기본값(default)으로 설정합니다.
models.PROTECT
- 참조된 객체가 삭제되지 않도록 보호합니다. 삭제 시 오류 발생.
models.DO_NOTHING
- 아무 동작도 하지 않음. 데이터 일관성이 깨질 가능성이 있어 주의 필요.
관계 설정 시 고려사항
연결 방향
- Sale(판매) 데이터는 많지만, 직원(Person) 데이터는 적습니다.
- 따라서 직원(Person)이 Sale을 참조하기보다는 Sale이 Person을 참조하는 것이 효율적입니다.
- 다대일(Many-to-One) 관계를 설정.
외래 키로 관계 정의
- 관계된 테이블(Sale, Person) 간의 데이터를 참조하여 필요한 정보를 효율적으로 가져올 수 있음.
- 관계 설정 시, 삭제 동작을 적절히 설정해야 데이터 무결성을 유지할 수 있음.
주요 정리
- 외래 키는 테이블 간의 관계를 정의.
- on_delete 옵션으로 데이터 삭제 시 동작을 반드시 지정해야 함.
- 외래 키를 통해 데이터 중복을 방지하고, 효율적으로 관계를 관리할 수 있음.
- 적절한 데이터 관계 설계를 통해 성능을 향상시킬 수 있음.
6.OneToOne 모델 이해하기,AbstractUser
from django.db import models from django.contrib.auth.models import AbstractUser class 아이디(AbstractUser): pass class Sale(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) age = models.IntegerField(default=0) person = models.ForeignKey("Person", on_delete=models.CASCADE) class Person(models.Model): 회원 = models.OneToOneField(아이디, on_delete=models.CASCADE) # first_name = models.CharField(max_length=30) # last_name = models.CharField(max_length=30)
1. 모델 설명
아이디 모델
- AbstractUser를 상속받아 사용자 모델을 확장합니다.
- 기본적으로 장고의 User 모델이 제공하는 모든 필드(username, password, email, first_name, last_name, 등)를 그대로 사용합니다.
- 추가적으로 사용자와 관련된 필드를 필요에 따라 정의할 수 있습니다. 현재는 추가 필드가 없으므로 pass로 처리했습니다.
Person 모델
- 사용자와 관련된 추가 정보를 관리하는 모델입니다.
- OneToOneField를 사용하여 아이디 모델과 일대일 관계를 설정했습니다.
- 이는 한 사용자가 하나의 Person 데이터만 가지도록 보장합니다.
- on_delete=models.CASCADE를 설정하여 아이디 객체가 삭제되면 관련된 Person 객체도 삭제됩니다.
Sale 모델
- 판매와 관련된 정보를 저장합니다.
- Person 모델과 ForeignKey로 연결되어, 한 명의 Person이 여러 개의 판매 데이터를 가질 수 있습니다(1:N 관계).
2. 설정 파일 (settings.py)
- 사용자 모델을 아이디로 변경하려면 AUTH_USER_MODEL 설정이 필요합니다.
- 현재 설정 파일에서 다음과 같이 선언했습니다
AUTH_USER_MODEL = 'sales.아이디'
이로써 프로젝트는 기본 User 모델 대신 아이디 모델을 사용하게 됩니다.
3. 장고 모델 등록과 마이그레이션
새 모델 적용 절차:
기존 생성 파일 삭제( 0001_initial.py, db.sqlite3)
모델 작성 및 수정
위의 코드처럼 사용자 정의 모델과 관련 모델을 작성합니다.마이그레이션 파일 생성
python manage.py makemigrations python manage.py migrate
4. 주요 참고 사항
데이터베이스 재설정
사용자 모델(AUTH_USER_MODEL)을 변경하면 기존 데이터베이스와 호환되지 않으므로 초기 개발 단계에서 모델을 설정한 후 프로젝트를 진행해야 합니다.
만약 이미 데이터베이스가 있다면 새로 초기화하거나, 데이터 마이그레이션 작업이 필요합니다.관리자 페이지에서 사용자 관리
사용자 정의 모델을 사용할 경우, 관리자 페이지에서 이를 관리할 수 있도록 추가 설정이 필요합니다:
from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import 아이디 @admin.register(아이디) class CustomUserAdmin(UserAdmin): pass
7.Django 데이터베이스 관리 및 활용
1. 모델 정의 (Models)
Django에서 모델은 데이터베이스의 구조를 정의합니다. 각 클래스는 하나의 데이터베이스 테이블을 나타냅니다.
from django.db import models from django.contrib.auth.models import AbstractUser # 사용자 모델 확장 class 아이디(AbstractUser): pass # 판매(Sale) 테이블 class Sale(models.Model): first_name = models.CharField(max_length=30) # 이름 last_name = models.CharField(max_length=30) # 성 age = models.IntegerField(default=0) # 나이 person = models.ForeignKey("Person", on_delete=models.CASCADE) # 관계 정의 (Person과 연결) # 사람(Person) 테이블 class Person(models.Model): 회원 = models.OneToOneField(아이디, on_delete=models.CASCADE) # 아이디와 일대일 관계 def __str__(self): return self.회원.email # 객체 출력 시 이메일 반환
2. 데이터베이스 테이블 생성
모델을 정의한 후, Django의 마이그레이션을 통해 데이터베이스 테이블을 생성합니다.
모델 변경 사항 감지 python manage.py makemigrations 데이터베이스에 적용 python manage.py migrate
3. 관리자(Admin) 페이지 설정
Django는 기본적으로 관리자 페이지를 제공하여 데이터 관리가 가능합니다.
슈퍼유저 생성
관리자 페이지에 로그인하려면 슈퍼유저를 생성해야 합니다.
python manage.py createsuperuser
- 사용자 이름, 이메일, 비밀번호를 설정.
관리자 페이지 URL
모델 등록 (admin.py)
관리자 페이지에서 Person과 Sale 모델을 관리하려면 모델을 등록해야 합니다.
from django.contrib import admin from .models import Person, Sale admin.site.register(Person) admin.site.register(Sale)
4. Django Shell로 데이터 조작
Django Shell은 데이터베이스 조작을 위한 인터페이스를 제공합니다.
Shell 실행
python manage.py shell
데이터 작업 예제
# 모델 가져오기 from sales.models import 아이디, Person, Sale # 슈퍼유저 조회 superuser = 아이디.objects.get(username='admin') # Person 생성 person = Person.objects.create(회원=superuser) # Sale 생성 sale = Sale.objects.create( first_name="John", last_name="Doe", age=30, person=person ) # 데이터 조회 sales = Sale.objects.all() for sale in sales: print(sale.first_name, sale.last_name, sale.age) # 데이터 수정 sale.age = 35 sale.save() # 데이터 삭제 sale.delete()
5. 관계형 데이터 관리
Django에서는 모델 간 관계를 정의하여 데이터를 관리할 수 있습니다.
관계 예제
ForeignKey (다대일 관계)
- Sale 모델의 person 필드는 Person 모델과 연결됩니다.
- 관계 정의
person = models.ForeignKey("Person", on_delete=models.CASCADE)
- CASCADE: 관련 Person 삭제 시 연결된 Sale도 삭제.
OneToOneField (일대일 관계)
- Person 모델의 회원 필드는 아이디 모델과 연결됩니다.
회원 = models.OneToOneField(아이디, on_delete=models.CASCADE)
6. 모델 출력 커스터마이징
__str__ 메서드를 사용하면 모델 객체를 문자열로 표현할 수 있습니다.
예를 들어, Person 모델에서 email을 반환하도록 설정:
class Person(models.Model): 회원 = models.OneToOneField(아이디, on_delete=models.CASCADE) def __str__(self): return self.회원.email
Shell에서 출력 시
print(person) # user@example.com
7. SQLite 데이터 확인
Django의 기본 데이터베이스는 SQLite입니다. 이를 확인하려면 SQLite Browser 같은 도구를 사용할 수 있습니다.
- 파일 위치: 프로젝트 폴더 내 db.sqlite3
- 테이블과 데이터를 시각적으로 확인 가능.
8. 데이터 입력 및 출력 흐름
회원 및 판매 데이터 입력
1.아이디 모델에 슈퍼유저 생성 python manage.py createsuperuser 2.Person 모델에 슈퍼유저 연결 person = Person.objects.create(회원=superuser) 3.Sale 모델에 데이터 추가 sale = Sale.objects.create( first_name="Jane", last_name="Smith", age=28, person=person )
출력
- Sale 데이터를 출력하면 Person과 연결된 데이터를 포함하여 출력됩니다.
9. 데이터베이스 관리 팁
- Django ORM 활용: SQL문 없이 Python 코드로 데이터베이스 작업 가능.
- Admin 페이지: 데이터를 빠르게 추가/수정/삭제 가능.
- Shell 사용: 데이터 조작 및 디버깅에 유용.
참고: Django 공식 문서
8.Django 관리자(Admin) 페이지 설정 및 활용
1. Django Admin 페이지 소개
- Django Admin은 데이터베이스 테이블(모델)을 웹 인터페이스를 통해 관리할 수 있는 도구입니다.
- 관리자 페이지 기본 URL:
http://127.0.0.1:8000/admin
Admin 페이지 주요 기능
- 데이터 조회
- 데이터 추가, 수정, 삭제
- 모델 데이터의 편리한 관리
2.Admin 페이지 활성화
슈퍼유저 생성
- 관리자 페이지에 접근하려면 **슈퍼유저(Superuser)**를 생성해야 합니다.
python manage.py createsuperuser Admin 페이지 URL로 접속 http://127.0.0.1:8000/admin
3. 모델 등록
Admin 페이지에서 데이터 관리하려면 모델을 등록해야 합니다
from django.contrib import admin from .models import 아이디, Sale, Person # 모델 등록 admin.site.register(아이디) # 사용자 모델 admin.site.register(Sale) # 판매 데이터 모델 admin.site.register(Person) # 사람 데이터 모델
등록 과정
- admin.py 파일 열기 (myapp/admin.py).
- django.contrib.admin에서 admin 모듈 가져오기.
- models.py의 모델을 admin.site.register()를 통해 등록.
4. Admin 페이지 등록 후 화면
모델 등록 후 관리자 페이지에서 확인할 수 있는 기본 화면 구성:
- 모델 이름: 등록된 모델이 화면에 표시.
- 데이터 관리:
- 목록 조회
- 데이터 추가
- 데이터 수정
- 데이터 삭제
5. 관리자 페이지 커스터마이징
Django Admin의 기본 제공 기능 외에도, ModelAdmin 클래스를 사용하여 관리 페이지를 커스터마이징할 수 있습니다.
1) 목록에 표시할 필드 설정
class PersonAdmin(admin.ModelAdmin): list_display = ('회원',) # 목록에 표시할 필드 admin.site.register(Person, PersonAdmin)
2) 검색 필드 추가
class SaleAdmin(admin.ModelAdmin): search_fields = ('first_name', 'last_name') # 검색 가능한 필드 admin.site.register(Sale, SaleAdmin)
3) 필터 추가
class SaleAdmin(admin.ModelAdmin): list_filter = ('age',) # 필터 옵션 추가 admin.site.register(Sale, SaleAdmin)
4) 읽기 전용 필드 설정
class PersonAdmin(admin.ModelAdmin): readonly_fields = ('회원',) # 읽기 전용 필드 설정 admin.site.register(Person, PersonAdmin)
6. Django Admin 모델 등록 정리
1) 기본 등록
admin.site.register(모델명)
2) ModelAdmin 커스터마이징 등록
class 모델명Admin(admin.ModelAdmin): list_display = ('필드1', '필드2') # 목록에 표시할 필드 search_fields = ('필드1',) # 검색 가능 필드 list_filter = ('필드2',) # 필터링 가능 필드 readonly_fields = ('필드3',) # 읽기 전용 필드 admin.site.register(모델명, 모델명Admin)
admin.py
from django.contrib import admin from .models import 아이디, Sale,Person admin.site.register(아이디) admin.site.register(Sale) admin.site.register(Person)
참고: Django 공식 문서
9.Django 첫 화면(View) 구성 및 URL 매핑
Django에서 웹 애플리케이션을 구축할 때, **뷰(View)**는 클라이언트의 요청을 받아 데이터를 처리한 후 응답을 반환하는 핵심 역할을 합니다.
이번에는 간단한 홈페이지를 구성하고, URL 매핑을 통해 브라우저에서 접근할 수 있도록 설정하는 방법을 정리합니다.
1. 기본 View 작성
Django에서 View는 요청을 처리하고 응답을 반환하는 Python 함수 또는 클래스입니다. 아래는 View를 작성하는 기본적인 방법입니다.
View 작성 코드
from django.http import HttpResponse from django.shortcuts import render def 홈페이지(request): return HttpResponse("응 나야")
설명
- HttpResponse:
- HTTP 요청에 대한 응답을 생성합니다.
- 문자열 형태로 응답 내용을 반환할 수 있습니다.
- View 함수 구조:
- 파라미터: 요청 객체 (request).
- 반환값: HTTP 응답 객체.
요약:
HttpResponse("응 나야")를 사용하여 브라우저에서 "응 나야"라는 텍스트를 출력하는 간단한 View를 생성합니다.
2. URL 매핑
View를 생성한 후, 클라이언트가 특정 URL로 접근하면 해당 View가 호출되도록 URL 매핑을 설정합니다.
URL 매핑 코드
from django.contrib import admin from django.urls import path from sales.views import 홈페이지 urlpatterns = [ path('admin/', admin.site.urls), # 관리자 페이지 path('', 홈페이지), # 루트 URL ]
설명
- path() 함수:
- 첫 번째 인자: URL 경로 (''는 루트 URL을 의미).
- 두 번째 인자: 호출할 View 함수 (홈페이지).
- URL 매핑 동작:
- 브라우저에서 http://127.0.0.1:8000/로 접속하면 홈페이지 View가 실행됩니다.
3. 서버 실행 및 결과 확인
개발 서버 실행
python manage.py runserver
접속
- 브라우저에서 http://127.0.0.1:8000/로 이동하면 **"응 나야"**라는 텍스트가 출력됩니다.
4. View 작성 과정 정리
- View 생성:
- views.py 파일에 함수나 클래스를 정의합니다.
- 예: 홈페이지 함수.
- URL 매핑:
- urls.py 파일에서 View를 특정 URL에 연결합니다.
- 예: path('', 홈페이지).
- 응답 확인:
- 브라우저에서 지정한 URL로 접근하여 View의 응답을 확인합니다.
5. Django View의 주요 개념
요청(Request)와 응답(Response):
- 요청 객체 (request)는 클라이언트의 HTTP 요청 정보를 포함합니다.
- View 함수는 요청 객체를 처리한 후, 응답 객체를 반환합니다.
View의 반환값:
- HttpResponse: HTML, 텍스트 등 간단한 응답을 반환.
- render: 템플릿을 렌더링하여 HTML 페이지 반환.
6. Django 공식 문서 참고
10.Django Template 시스템과 HTML 렌더링
1. Django Template 설정
settings.py의 TEMPLATES 설정
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / '폴더'], # 커스텀 템플릿 경로 추가 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
설명
- DIRS:
- 커스텀 템플릿 디렉토리를 지정합니다.
- 예: BASE_DIR / '폴더'는 프로젝트 루트 디렉토리의 폴더를 템플릿 경로로 지정.
- APP_DIRS:
- 각 앱의 templates 폴더를 템플릿 디렉토리로 자동 인식.
- context_processors:
- 템플릿에서 사용할 기본 컨텍스트 데이터를 처리합니다.
2. HTML 파일 구성
Django는 기본적으로 앱 내 templates 폴더를 탐색하며, 커스텀 디렉토리를 지정하면 그 경로도 포함합니다.
HTML 파일 예시
- sales/templates/newfolder/아무거나1.html
<html> <head></head> <body> <h1>아무거나</h1> </body> </html>
2. 폴더/아무거나2.html
<html> <head></head> <body> <h1>아무거나2</h1> </body> </html>
3. View 함수에서 템플릿 렌더링
View 코드 (sales/views.py)
from django.shortcuts import render def 홈페이지(request): # 첫 번째 HTML 파일 # return render(request, 'newfolder/아무거나1.html') # 두 번째 HTML 파일 return render(request, '아무거나2.html')
설명
- render() 함수:
- 첫 번째 인자: request 객체.
- 두 번째 인자: 템플릿 경로 (앱별 templates 폴더 또는 DIRS 경로 기준).
- 세 번째 인자(옵션): 컨텍스트 데이터 (context).
- 경로 지정:
- 앱 템플릿 폴더: 'newfolder/아무거나1.html'.
- 커스텀 템플릿 폴더: '아무거나2.html'.
4. URL 매핑
urls.py
from django.contrib import admin from django.urls import path from sales.views import 홈페이지 urlpatterns = [ path('admin/', admin.site.urls), # 관리자 페이지 path('', 홈페이지), # 루트 URL ]
설명
- path('', 홈페이지)는 루트 URL (http://127.0.0.1:8000/)에 요청이 오면 홈페이지 View를 호출합니다.
5. Template 경로 탐색 순서
Django는 다음 순서로 템플릿 파일을 탐색합니다:
- **DIRS**에 지정된 경로.
- 예: BASE_DIR / '폴더'.
- **APP_DIRS**를 통해 앱별 templates 폴더.
- 예: sales/templates/newfolder.
11.HTML에 생명을! 콘텍스트(context)
1. 개요
장고(Django)에서는 HTML 템플릿을 단순히 정적인 페이지로 제공하는 것이 아니라, 컨텍스트(context) 를 활용하여 동적인 데이터를 전달할 수 있습니다. 컨텍스트를 사용하면 서버에서 가공된 데이터를 HTML 템플릿에 주입하여 웹 페이지를 보다 동적으로 만들 수 있습니다.
2. 컨텍스트의 개념
컨텍스트(Context)는 파이썬의 딕셔너리 형태로 구성됩니다. 즉, 키(Key)와 값(Value)로 이루어져 있으며, 템플릿 내에서 해당 키 값을 호출하면 연결된 데이터를 사용할 수 있습니다.
context = { "메뉴명": "짜장", "가격": "700원" }
이 컨텍스트 데이터를 장고의 render() 함수의 세 번째 인자로 전달하면 템플릿에서 활용할 수 있습니다.
3. 컨텍스트 적용 예제
(1) 뷰 함수에서 컨텍스트 전달
from django.http import HttpResponse from django.shortcuts import render from .models import 아이디 def 홈페이지(request): 드실분 = 아이디.objects.all() context = { "메뉴명": "짜장", "가격": "700원", "손님": 드실분 } return render(request, '아무거나2.html', context)
위 코드에서 드실분 = 아이디.objects.all()을 통해 데이터베이스에서 모든 아이디 정보를 가져와 손님이라는 키 값으로 컨텍스트에 추가합니다.
(2) 템플릿에서 컨텍스트 데이터 사용
<html> <head></head> <body> <h1>아무거나 먹자</h1> <br/> <p>점심 : {{ 메뉴명 }}</p> <p>예산 : {{ 가격 }}</p> <p>드실분 :</p> <ul> {% for 드실사람 in 손님 %} <li>{{ 드실사람 }}</li> {% endfor %} </ul> <p>밥먹는 사람: {{ 손님 }}</p> </body> </html>
이렇게 하면, 손님 리스트에 있는 모든 데이터가 <ul> 리스트 형태로 출력됩니다.
4. 템플릿에서 컨텍스트 활용 방법
(1) 기본 데이터 출력
<p>메뉴: {{ 메뉴명 }}</p> <p>가격: {{ 가격 }}</p>
(2) 반복문을 이용한 리스트 출력
<ul> {% for 사람 in 손님 %} <li>{{ 사람 }}</li> {% endfor %} </ul>
장고의 템플릿 언어에서 {% for %} ... {% endfor %} 구문을 사용하면 리스트 형태의 데이터를 반복 출력할 수 있습니다.
(3) 조건문 활용
{% if 손님 %} <p>손님이 있습니다.</p> {% else %} <p>손님이 없습니다.</p> {% endif %}
템플릿 내에서 {% if %} ... {% else %} ... {% endif %} 구문을 이용하여 조건에 따라 HTML을 동적으로 변경할 수도 있습니다.
5. 결론
- 컨텍스트(Context)는 파이썬의 딕셔너리 형태로 데이터를 저장하며, 템플릿에서 이를 활용할 수 있습니다.
- render(request, '템플릿.html', context) 형식으로 컨텍스트를 전달하면, 템플릿에서 {{ 키이름 }} 형태로 데이터를 출력할 수 있습니다.
- 장고 템플릿 언어를 활용하면 반복문, 조건문 등을 통해 더욱 동적인 페이지를 만들 수 있습니다.
이제 컨텍스트를 활용하여 데이터베이스의 정보를 효과적으로 출력하는 웹 페이지를 구현해보세요!
12.Django 프로젝트의 효율적인 URL 관리
Django 프로젝트에서 URL을 효율적으로 관리하는 방법을 학습합니다. 특히 namespace와 app_name을 활용하여 URL을 체계적으로 구성하는 방법을 살펴봅니다.
1. 프로젝트 수준에서 URL 설정
먼저 djangocrm 프로젝트의 urls.py를 확인합니다.
""" URL configuration for djangocrm project. The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/5.1/topics/http/urls/ """ from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('홈페이지/', include('sales.urls', namespace='홈페이지')), ]
설명
- admin/ 경로는 Django의 기본 관리자 페이지입니다.
- 홈페이지/ 경로는 sales 앱의 urls.py를 포함하며, namespace를 '홈페이지'로 설정하였습니다.
- include()를 사용하여 앱의 urls.py를 연결합니다.
2. 앱 수준에서 URL 설정
sales 앱 내부의 urls.py 파일을 확인합니다.
from django.urls import path from .views import 홈페이지 app_name = "홈페이지" urlpatterns = [ path("", 홈페이지) ]
설명
- app_name을 '홈페이지'로 설정하여 네임스페이스를 지정합니다.
- 기본 경로("")에 홈페이지 뷰를 연결합니다.
3. namespace와 app_name의 역할
Django에서 namespace와 app_name을 설정하는 이유는 다음과 같습니다.
✅ namespace
- 프로젝트 수준의 urls.py에서 앱을 구별하는 역할을 합니다.
- 여러 앱에서 동일한 URL 이름을 사용할 때 충돌을 방지합니다.
✅ app_name
- namespace와 함께 사용되며, 각 앱의 URL을 명확하게 구분할 수 있도록 돕습니다.
- 예를 들어, 템플릿에서 {% url '홈페이지:홈페이지' %}와 같이 사용할 수 있습니다.
4. URL 네임스페이스 적용 흐름
Django의 URL 라우팅 흐름을 다시 정리하면 다음과 같습니다.
- 사용자가 /홈페이지/로 접근하면 djangocrm/urls.py가 실행됩니다.
- include('sales.urls', namespace='홈페이지')를 통해 sales/urls.py로 이동합니다.
- sales/urls.py에서 path("", 홈페이지)를 확인하고 views.py의 홈페이지 뷰를 실행합니다.
5. 네임스페이스 활용 예시
템플릿에서 네임스페이스를 활용하면 다음과 같이 URL을 호출할 수 있습니다.
<a href="{% url '홈페이지:홈페이지' %}">홈페이지 이동</a>
이렇게 하면 namespace를 활용하여 URL 구조가 변경되어도 쉽게 유지보수가 가능합니다.
6. 마무리
Django 프로젝트에서 namespace와 app_name을 활용하여 URL을 효율적으로 관리하는 방법을 알아보았습니다. 이를 활용하면 대규모 프로젝트에서도 URL 충돌을 방지하고 유지보수가 쉬워집니다.
13.Django URL 설정 및 뷰 연결
1. Django URL 설정 및 뷰 연결
Django 프로젝트에서 URL을 설정하고, 해당 URL에 대응하는 뷰(View)를 연결하는 방법을 학습합니다.
1.1 URL 설정
from django.urls import path from .views import 세일목록, 세일상세 app_name = "홈페이지" urlpatterns = [ path("", 세일목록), # http://127.0.0.1:8000/홈페이지/2/ path("<pk>/", 세일상세) ]
위 코드에서 urlpatterns 리스트를 통해 URL과 뷰 함수를 연결합니다.
- path("", 세일목록): 기본 경로에서 세일목록 뷰를 실행합니다.
- path("<pk>/", 세일상세): 특정 PK 값을 받아 세일상세 뷰를 실행합니다.
2. 뷰(View) 설정
Django의 뷰는 클라이언트 요청을 처리하고, 적절한 응답을 반환하는 역할을 합니다.
2.1 세일목록 뷰 (목록 조회)
from django.http import HttpResponse from django.shortcuts import render from .models import Sale def 세일목록(request): 사람 = Sale.objects.all() context = { "사람키": 사람 } return render(request, 'newfolder/세일목록.html', context)
- Sale.objects.all()을 통해 데이터베이스에서 모든 Sale 객체를 가져옵니다.
- context 딕셔너리를 생성하여 데이터를 템플릿에 전달합니다.
- render() 함수를 사용하여 세일목록.html 템플릿을 렌더링합니다.
2.2 세일상세 뷰 (상세 조회)
def 세일상세(request, pk): return HttpResponse("<h1>여기 상세 정보입니다.</h1>")
- URL에서 받은 pk 값에 따라 상세 정보를 반환합니다.
- 현재는 단순한 HTML 응답을 반환하도록 설정되어 있습니다.
3. 템플릿 설정
Django의 템플릿 시스템을 이용하여 동적인 HTML 페이지를 생성할 수 있습니다.
3.1 세일목록.html
<html> <head> <style> .세일{ padding-top: 20px; padding-bottom: 30px; padding-right: 10px; padding-left: 10px; background-color: #f5f5f5; } </style> </head> <body> <h1>이것이 세일 목록들 입니다.</h1> {% for 인간 in 사람키 %} <div class="세일"> {{ 인간.last_name }} {{ 인간.first_name }}, 나이는 {{ 인간.age }}세 </div> <br/> {% endfor %} </body> </html>
- for 문을 사용하여 사람키 리스트를 반복하며 각 데이터를 출력합니다.
- 스타일을 추가하여 가독성을 높였습니다.
4. 학습 요점
- Django URL 설정: urlpatterns를 활용하여 URL과 뷰를 연결합니다.
- 뷰 함수 작성:
- 세일목록에서 Sale.objects.all()을 사용하여 데이터를 가져옵니다.
- 세일상세에서는 단순 HTML 응답을 반환합니다.
- 템플릿 시스템 활용:
- for 문을 사용하여 데이터를 반복 출력합니다.
- 스타일을 적용하여 UI를 개선합니다.
이제 Django 프로젝트에서 기본적인 모델 데이터를 조회하고, URL을 통해 연결하는 방법을 익혔습니다!
14. Django 세일 목록 및 상세 페이지 구현
Django를 활용하여 세일(Sale) 목록과 상세 페이지를 구현하는 과정입니다. 기본적으로 pk(Primary Key)를 기반으로 특정 데이터를 조회하여 상세 정보를 보여주는 방식으로 동작합니다.
1. 모델(Model) 정의
Django의 ORM을 사용하여 Sale 및 Person 모델을 정의합니다.
from django.db import models from django.contrib.auth.models import AbstractUser # 사용자 모델 확장 class 아이디(AbstractUser): pass # Sale 모델 class Sale(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) age = models.IntegerField(default=0) person = models.ForeignKey("Person", on_delete=models.CASCADE) def __str__(self): return f"{self.last_name} {self.first_name}" # Person 모델 class Person(models.Model): 회원 = models.OneToOneField(아이디, on_delete=models.CASCADE) def __str__(self): return self.회원.email
주요 포인트
- Sale 모델: first_name, last_name, age 등의 필드를 가지며, Person 모델과 ForeignKey 관계를 맺음.
- Person 모델: Django의 기본 사용자 모델을 확장한 아이디(AbstractUser) 모델과 OneToOneField 관계를 맺음.
2. 뷰(View) 구현
각각의 페이지를 처리하는 Django 뷰를 작성합니다.
from django.shortcuts import render from .models import Sale # 세일 목록 페이지 def 세일목록(request): 사람 = Sale.objects.all() context = { "사람키": 사람 } return render(request, 'newfolder/세일목록.html', context) # 세일 상세 페이지 def 세일상세(request, pk): 사람 = Sale.objects.get(id=pk) context = { "사람키": 사람 } return render(request, 'newfolder/세일상세.html', context)
주요 포인트
- 세일목록(request): 모든 Sale 객체를 가져와 세일목록.html에 전달.
- 세일상세(request, pk): pk(Primary Key)를 이용해 특정 Sale 객체를 조회하여 세일상세.html에 전달.
3. 템플릿(Template) 작성
HTML 페이지에서 데이터를 출력하는 방식입니다.
세일 목록 템플릿 (세일목록.html)
<h1>세일 목록</h1> <ul> {% for 사람 in 사람키 %} <li> <a href="{% url '세일상세' 사람.id %}"> {{ 사람.last_name }} {{ 사람.first_name }} ({{ 사람.age }}세) </a> </li> {% endfor %} </ul>
주요 포인트
- {% for 사람 in 사람키 %}: 전달받은 데이터 리스트를 반복 출력.
- <a href="{% url '세일상세' 사람.id %}">: 해당 사용자의 상세 페이지로 이동하는 링크를 생성.
세일 상세 템플릿 (세일상세.html)
<html> <head> <style> .세일 { padding: 20px 10px 30px 10px; background-color: #f5f5f5; } </style> </head> <body> <h1>이것이 고객 {{ 사람키.first_name }}님의 나이 정보입니다.</h1> <p>이 분의 나이는 {{ 사람키.age }}</p> </body> </html>
주요 포인트
- {{ 사람키.first_name }}: 선택한 사용자의 이름을 출력.
- {{ 사람키.age }}: 선택한 사용자의 나이를 출력.
4. URL 설정
각 뷰를 URL과 연결하여 페이지를 요청할 수 있도록 합니다.
from django.urls import path from .views import 세일목록, 세일상세 urlpatterns = [ path('', 세일목록, name="세일목록"), path('sale/<int:pk>/', 세일상세, name="세일상세"), ]
주요 포인트
- path('', 세일목록, name="세일목록"): 기본 경로에서 세일 목록 페이지를 표시.
- path('sale/<int:pk>/', 세일상세, name="세일상세"): pk 값으로 특정 세일 정보를 조회하여 상세 페이지를 표시.
5. pk를 활용한 상세 페이지 링크
Django에서 pk를 기반으로 특정 데이터를 조회하는 방식입니다.
<a href="{% url '세일상세' 사람.id %}"> {{ 사람.last_name }} {{ 사람.first_name }} </a>
pk를 활용하는 이유
- Django 공식 문서에서 pk(Primary Key)를 활용하여 데이터베이스의 특정 레코드를 조회하는 것이 일반적인 방법임.
- pk는 각 레코드(객체)를 구분할 수 있는 고유한 값이므로 URL을 통해 특정 데이터를 정확히 조회할 수 있음.
6. 상세 페이지의 URL에 pk 표시 확인
브라우저에서 링크를 클릭하면 URL이 아래와 같이 변합니다.
http://localhost:8000/sale/2/
- 2는 pk 값으로, 데이터베이스의 특정 레코드를 식별하는 역할을 함.
개발자 도구(F12) → "검사" 기능을 활용하여 pk 값이 올바르게 출력되는지 확인할 수 있음.
???? 7. str 메서드 추가 (모델 출력 형식 개선)
현재 Sale 모델의 객체를 출력하면 <Sale: Sale object (2)>와 같은 형태로 보이는데, 이를 가독성 좋게 변경할 수 있습니다.
class Sale(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) age = models.IntegerField(default=0) person = models.ForeignKey("Person", on_delete=models.CASCADE) def __str__(self): return f"{self.last_name} {self.first_name}"
개선 효과
- 기존: <Sale: Sale object (2)>
- 변경 후: 홍길동 김봉자
15.Django 폼(Form) 개요
Django의 폼(Form)은 사용자가 웹에서 데이터를 입력하고 제출할 수 있도록 도와주는 중요한 기능 중 하나입니다. 장고에서는 **일반 폼(Form)**과 모델 폼(ModelForm) 두 가지 유형의 폼을 제공합니다. 이번 강의에서는 일반 폼을 직접 구현하여 사용자의 데이터를 받아들이는 방법을 살펴보겠습니다.
1. Django 폼(Form) 구현
1.1 SaleForm 클래스 정의
먼저, 사용자가 입력할 폼 필드를 정의하는 클래스를 작성합니다. Django의 forms.Form 클래스를 상속받아 SaleForm을 생성합니다.
from django import forms class SaleForm(forms.Form): first_name = forms.CharField(max_length=30) last_name = forms.CharField(max_length=30) age = forms.IntegerField(min_value=0)
이 폼에는 세 개의 필드가 포함됩니다:
- first_name: 최대 30자의 문자열 입력
- last_name: 최대 30자의 문자열 입력
- age: 최소값 0 이상의 정수 입력
2. View 함수 구현
사용자가 폼을 제출하면 Django의 뷰(View) 함수가 이를 처리합니다.
def 세일_입력(request): print(request.POST) context = { "폼키": SaleForm() } return render(request, 'newfolder/세일_입력.html', context)
- request.POST 데이터를 출력하여 폼 제출 후 전달된 데이터를 확인할 수 있습니다.
- SaleForm()을 context에 담아 템플릿에서 사용할 수 있도록 전달합니다.
- render()를 통해 세일_입력.html 템플릿을 렌더링합니다.
3. HTML 템플릿 구성
폼을 실제 웹 페이지에서 렌더링하기 위해 세일_입력.html 파일을 작성합니다.
<html> <head> </head> <body> <h1>세일 입력 페이지</h1> <form method="post"> {% csrf_token %} {{ 폼키.as_p }} <button type="submit">전송</button> </form> </body> </html>
- <form method="post">를 통해 데이터를 서버로 전송할 수 있도록 설정합니다.
- {% csrf_token %}은 Django의 보안 기능으로, CSRF 공격을 방지하기 위해 필수적으로 포함해야 합니다.
- {{ 폼키.as_p }}를 사용하면 Django에서 자동으로 폼을 렌더링해줍니다.
- <button type="submit">전송</button>을 통해 폼을 제출할 수 있습니다.
4. 폼 제출 후 서버 로그 확인
폼을 제출하면 서버에서 다음과 같은 로그를 출력할 수 있습니다.
<QueryDict: {}> [31/Jan/2025 12:43:12] "GET /%ED%99%88%ED%8E%98%EC%9D%B4%EC%A7%80/make/ HTTP/1.1" 200 762 <QueryDict: {'csrfmiddlewaretoken': ['uMsVI9mkYM1zVN4ZmArwDGiqknRR2MwY4kzddfaMhQp70tDcMNEX5dwvoG68KX71'], 'first_name': ['111'], 'last_name': ['222'], 'age': ['333']}> [31/Jan/2025 12:43:19] "POST /%ED%99%88%ED%8E%98%EC%9D%B4%EC%A7%80/make/ HTTP/1.1" 200 762
위 로그를 통해 GET 요청과 POST 요청이 정상적으로 이루어지고 있는지 확인할 수 있습니다.
16. 장고의 폼(Form) 2.일반 폼- 입력값 유효성 검증과 cleaned_data, redirect
장고 폼(Form) 개요
장고에서 폼을 사용하면 사용자의 입력 데이터를 효율적으로 검증하고 저장할 수 있습니다. 이번 강의에서는 cleaned_data를 활용하여 입력 데이터를 검증하고 저장하는 과정을 설명합니다.
세일 목록 페이지 구현
from django.shortcuts import render from .models import Sale def 세일목록(request): 사람 = Sale.objects.all() context = {"사람키": 사람} return render(request, 'newfolder/세일목록.html', context)
- Sale.objects.all()을 사용하여 모든 Sale 객체를 가져옵니다.
- 가져온 데이터를 context에 담아 템플릿으로 전달합니다.
세일 상세 페이지 구현
from django.shortcuts import render from .models import Sale def 세일상세(request, pk): 사람 = Sale.objects.get(id=pk) context = {"사람키": 사람} return render(request, 'newfolder/세일상세.html', context)
- pk 값을 통해 특정 Sale 객체를 조회하여 상세 정보를 가져옵니다.
- 조회한 데이터를 context에 담아 템플릿으로 전달합니다.
폼을 이용한 세일 입력 처리
from django.shortcuts import render, redirect from .models import Sale, Person from .forms import SaleForm def 세일_입력(request): 폼 = SaleForm() if request.method == "POST": print("포스트 메소드로 왔네요") 폼 = SaleForm(request.POST) if 폼.is_valid(): print("유효하네요.") print("폼 cleaned_data : ", 폼.cleaned_data) first_name = 폼.cleaned_data["first_name"] last_name = 폼.cleaned_data["last_name"] age = 폼.cleaned_data["age"] person = Person.objects.first() Sale.objects.create( first_name=first_name, last_name=last_name, age=age, person=person ) print("세일이 입력되었습니다.") return redirect("/홈페이지") context = {"폼키": SaleForm} return render(request, 'newfolder/세일_입력.html', context)
✅ 코드 설명
- request.method가 POST이면 사용자가 폼을 제출한 것이므로 데이터를 처리합니다.
- is_valid() 메서드를 사용하여 입력 데이터의 유효성을 검증합니다.
- cleaned_data를 통해 정제된 데이터를 가져와 Sale 객체를 생성합니다.
- redirect("/홈페이지")를 사용하여 입력 후 홈페이지로 이동합니다.
cleaned_data 활용
cleaned_data란?
- is_valid() 검증 후, 사용자가 입력한 데이터가 cleaned_data에 저장됩니다.
- 이를 통해 데이터의 정합성을 체크하고, 유효한 데이터만 저장할 수 있습니다.
예제: cleaned_data 출력
if form.is_valid(): print("폼 cleaned_data :", form.cleaned_data)
출력 예시:
폼 cleaned_data : {'first_name': '홍', 'last_name': '길동', 'age': 30}
관리자(admin)에서 데이터 확인
- 새 데이터를 입력한 후 admin 페이지에서 정상적으로 저장되었는지 확인할 수 있습니다.
- Sale 모델에 새 데이터가 추가되었는지 확인해보세요.
결론
- cleaned_data를 활용하여 입력값을 정제하고 저장하는 방법을 익혔습니다.
- redirect()를 사용하여 입력 후 특정 페이지로 이동하도록 설정했습니다.
- admin 페이지에서 저장된 데이터를 확인할 수 있습니다.
17. 장고의 폼(Form) 3.모델폼(ModelForm)
1. 모델(Model) 정의
from django.db import models from django.contrib.auth.models import AbstractUser class 아이디(AbstractUser): pass class Sale(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) age = models.IntegerField(default=0) person = models.ForeignKey("Person", on_delete=models.CASCADE) def __str__(self): return f"{self.last_name} {self.first_name}" class Person(models.Model): 회원 = models.OneToOneField(아이디, on_delete=models.CASCADE) def __str__(self): return self.회원.email
2. 폼(Form) 정의
from django import forms from .models import Sale class SaleModelForm(forms.ModelForm): class Meta: model = Sale fields = ( "first_name", "last_name", "age", "person" ) class SaleForm(forms.Form): first_name = forms.CharField(max_length=30) last_name = forms.CharField(max_length=30) age = forms.IntegerField(min_value=0)
3. 뷰(View) 정의
from django.http import HttpResponse from django.shortcuts import render, redirect from .models import Sale, Person from .forms import SaleForm, SaleModelForm def 세일목록(request): 사람 = Sale.objects.all() context = { "사람키": 사람 } return render(request, 'newfolder/세일목록.html', context) def 세일상세(request, pk): 사람 = Sale.objects.get(id=pk) context = { "사람키": 사람 } return render(request, 'newfolder/세일상세.html', context) def 세일_입력(request): 폼 = SaleModelForm() if request.method == "POST": 폼 = SaleModelForm(request.POST) if 폼.is_valid(): 폼.save() return redirect("/홈페이지") context = { "폼키": SaleModelForm } return render(request, 'newfolder/세일_입력.html', context)
4. 템플릿(Template)
<html> <head> </head> <body> <h1>세일 입력 페이지</h1> <form method="post"> {% csrf_token %} {{ 폼키.as_p }} <button type="submit">전송</button> </form> </body> </html>
5. ModelForm을 사용하는 이유
- ModelForm은 모델과 직접 연결되어 있어, 코드 작성이 간결해지고 유지보수가 쉬워짐.
- 기존의 Form 클래스를 사용하면 개별 필드를 하나씩 정의해야 하지만, ModelForm은 Meta 클래스를 사용하여 모델의 필드를 자동으로 가져올 수 있음.
- ModelForm.save() 메서드를 호출하면 해당 모델의 인스턴스를 자동으로 저장할 수 있음.
ModelForm 사용 전후 비교
기존 Form 사용 시:
class SaleForm(forms.Form): first_name = forms.CharField(max_length=30) last_name = forms.CharField(max_length=30) age = forms.IntegerField(min_value=0)
- 직접 필드를 정의해야 함.
ModelForm 사용 시:
class SaleModelForm(forms.ModelForm): class Meta: model = Sale fields = ("first_name", "last_name", "age", "person")
- Meta 클래스를 이용해 모델의 필드를 자동으로 가져옴.
6. ModelForm을 활용한 데이터 저장
기존 Form을 사용한 데이터 저장 방식
def 세일_입력(request): 폼 = SaleForm() if request.method == "POST": 폼 = SaleForm(request.POST) if 폼.is_valid(): first_name = 폼.cleaned_data["first_name"] last_name = 폼.cleaned_data["last_name"] age = 폼.cleaned_data["age"] person = Person.objects.first() Sale.objects.create( first_name=first_name, last_name=last_name, age=age, person=person ) return redirect("/홈페이지")
- cleaned_data를 이용해 개별 데이터를 추출한 후 Sale.objects.create()를 호출해야 함.
ModelForm을 사용한 데이터 저장 방식
def 세일_입력(request): 폼 = SaleModelForm() if request.method == "POST": 폼 = SaleModelForm(request.POST) if 폼.is_valid(): 폼.save() return redirect("/홈페이지") context = { "폼키": SaleModelForm } return render(request, 'newfolder/세일_입력.html', context)
- 폼.save() 한 줄만 추가하면 자동으로 데이터가 저장됨.
7. ModelForm을 사용해야 하는 이유 정리
- 코드 간소화: 모델과 직접 연결되어 있어 불필요한 코드 작성이 줄어듦.
- 유지보수 용이: 모델의 필드가 변경되더라도 ModelForm을 수정할 필요가 거의 없음.
- 자동 검증: Django의 ModelForm은 모델 필드와 일치하는 유효성 검사를 자동으로 수행함.
- 데이터 저장 간소화: 폼.save() 메서드만으로 데이터를 데이터베이스에 쉽게 저장할 수 있음.
이와 같이 ModelForm을 활용하면 Django의 폼 관리를 훨씬 더 효율적으로 할 수 있습니다!
18. 장고의 폼(Form)을 사용한 CRUD 구현 - update 1
1. 개요
장고(Django)의 모델 폼(ModelForm)을 사용하여 데이터를 업데이트하는 기능을 구현하는 다음 강의
2. 세일(Sale) 데이터 업데이트 기능 구현
2.1 뷰(View) 함수 작성
다음은 특정 Sale 객체를 가져와 업데이트할 수 있도록 구현한 뷰 함수입니다.
def 세일_업데이트(request, pk): 사람 =Sale.objects.get(id=pk) if request.method == "POST": 폼=SaleForm(request.POST) if 폼.is_valid(): first_name =폼.cleaned_data["first_name"] last_name =폼.cleaned_data["last_name"] age =폼.cleaned_data["age"] person=Person.objects.first() 사람.first_name = first_name 사람.last_name = last_name 사람.age = age 사람.person = person 사람.save() return redirect("/홈페이지") else: 폼 =SaleModelForm(instance=사람) context={ "사람키":사람, "폼키" : 폼 } return render(request, 'newfolder/세일_업데이트.html', context)
2.2 템플릿(HTML) 코드
해당 폼을 HTML에서 렌더링하는 코드입니다.
<html> <head> </head> <body> <h1>{{ 사람키.last_name }} {{ 사람키.first_name }} 님의 개인 수정 정보를 수정해 주세요.</h1> <form method="post"> {% csrf_token %} {{ 폼키.as_p }} <button type="submit">전송</button> </form> </body> </html>
3. 코드 설명
3.1 뷰 함수 동작 방식
- pk(Primary Key)를 기반으로 특정 Sale 객체를 가져옵니다.
- 사용자가 POST 요청을 보내면 폼을 검증한 후, 해당 객체의 데이터를 업데이트합니다.
- 업데이트된 데이터를 저장하고, 홈 페이지로 리디렉션합니다.
- GET 요청 시 기존 데이터를 가진 폼을 렌더링하여 사용자에게 제공합니다.
3.2 HTML 템플릿 동작 방식
- 사람키(객체)를 통해 사용자의 기존 정보를 보여줍니다.
- 장고의 {% csrf_token %}을 사용하여 보안성을 강화합니다.
- 폼키.as_p를 사용하여 폼 필드를 자동으로 렌더링합니다.
- 전송 버튼을 클릭하면 입력된 데이터가 서버로 전송됩니다.
4. URL 매핑
이제 urls.py 파일에서 위의 뷰 함수를 URL과 연결해야 합니다.
from django.urls import path from .views import 세일목록, 세일상세, 세일_입력 , 세일_업데이트 app_name="홈페이지" urlpatterns = [ path("", 세일목록), #http://127.0.0.1:8000/홈페이지/2/ path("<int:pk>/", 세일상세), path("<int:pk>/업데이트/", 세일_업데이트), path("make/", 세일_입력), ]
5. 실행 및 테스트
- 브라우저에서 http://127.0.0.1:8000/세일/업데이트/1/로 접속합니다.
- 기존 데이터를 확인하고 수정한 후 전송 버튼을 클릭합니다.
- 수정된 데이터가 반영되었는지 확인합니다.
6. 마무리
이번 강의에서는 장고의 모델 폼을 사용하여 데이터 업데이트 기능을 구현하는 방법을 배웠습니다. URL 매핑을 통해 뷰 함수와 템플릿을 연결하고, 폼을 통해 데이터를 업데이트하는 과정을 이해하는 것이 중요합니다. 다음 강의에서는 CRUD 기능 중 삭제(Delete) 기능을 구현하는 방법을 다룰 예정입니다.
19. 장고의 폼(Form)을 사용한 CRUD - ModelForm을 이용한 Update와 Delete
1. 개요
장고(Django)에서 ModelForm을 사용하면 기존 데이터를 쉽게 수정(update)하거나 삭제(delete)할 수 있습니다. 이번 강의에서는 ModelForm을 활용하여 데이터를 업데이트하고 삭제하는 방법을 알아봅니다.
2. 세일 업데이트 (Update)
def 세일_업데이트(request, pk): 사람 = Sale.objects.get(id=pk) if request.method == "POST": 폼 = SaleModelForm(request.POST, instance=사람) if 폼.is_valid(): 폼.save() return redirect("/홈페이지") else: 폼 = SaleModelForm(instance=사람) context = { "사람키": 사람, "폼키": 폼 } return render(request, 'newfolder/세일_업데이트.html', context)
설명
- Sale.objects.get(id=pk)를 통해 특정 객체를 가져옵니다.
- POST 요청이면 폼을 제출받아 유효성을 검사한 후 저장합니다.
- GET 요청이면 기존 데이터를 포함한 폼을 렌더링합니다.
3. 세일 삭제 (Delete)
def 세일_지우기(request, pk): 사람 = Sale.objects.get(id=pk) 사람.delete() return redirect("/홈페이지")
설명
- Sale.objects.get(id=pk)를 이용해 특정 객체를 가져옵니다.
- delete() 메서드를 호출해 해당 객체를 삭제합니다.
4. URL 설정
from django.urls import path from .views import 세일목록, 세일상세, 세일_입력, 세일_업데이트, 세일_지우기 app_name = "홈페이지" urlpatterns = [ path("", 세일목록), path("<int:pk>/", 세일상세), path("<int:pk>/업데이트/", 세일_업데이트), path("<int:pk>/지우기/", 세일_지우기), path("make/", 세일_입력), ]
설명
- 특정 ID의 데이터를 수정할 수 있도록 <int:pk>/업데이트/ URL을 추가했습니다.
- 특정 ID의 데이터를 삭제할 수 있도록 <int:pk>/지우기/ URL을 추가했습니다.
5. 템플릿 코드 (HTML 폼)
<html> <head> </head> <body> <h1>{{ 사람키.last_name }} {{ 사람키.first_name }} 님의 정보를 수정해 주세요.</h1> <form method="post"> {% csrf_token %} {{ 폼키.as_p }} <button type="submit">전송</button> </form> </body> </html>
설명
- {{ 폼키.as_p }}를 사용하여 장고의 폼을 자동으로 렌더링합니다.
- CSRF 보호를 위해 {% csrf_token %}을 추가합니다.
- 수정된 데이터를 전송하기 위한 <button>을 추가합니다.
6. 강의 요약
- ModelForm을 사용하면 데이터를 쉽게 수정 및 삭제할 수 있습니다.
- instance 매개변수를 이용하면 기존 데이터를 폼에 채워서 수정할 수 있습니다.
- 삭제는 delete() 메서드를 호출하는 간단한 방식으로 구현할 수 있습니다.
- URL 패턴을 설정하여 사용자가 데이터를 수정 및 삭제할 수 있도록 구성합니다.
20. Django URL namespace 사용하기
1. URL Namespace 개요
Django에서 URL 네임스페이스(namespace)는 프로젝트 내에서 URL을 체계적으로 관리하고 유지보수하기 위해 사용됩니다. 네임스페이스를 활용하면 URL 패턴을 변경하더라도 전체 프로젝트에서 한 곳만 수정하면 되므로, 유지보수가 용이해집니다.
2. Django URL 설정
아래는 Django에서 네임스페이스를 적용한 URL 설정 예제입니다.
from django.urls import path from .views import 세일목록, 세일상세, 세일_입력, 세일_업데이트, 세일_지우기 app_name = "홈페이지" urlpatterns = [ path("", 세일목록, name="목록"), path("<int:pk>/", 세일상세, name="상세"), path("<int:pk>/업데이트/", 세일_업데이트, name="업뎃"), path("<int:pk>/지우기/", 세일_지우기, name="지우기"), path("make/", 세일_입력, name="생성"), ]
여기서 app_name = "홈페이지"를 지정하여 URL 네임스페이스를 설정하고, 각각의 URL 패턴에 name을 부여하여 코드 내에서 쉽게 참조할 수 있도록 했습니다.
3. Django Template에서 URL Namespace 사용
아래는 템플릿에서 URL 네임스페이스를 활용하여 동적으로 링크를 생성하는 방법입니다.
<html> <head> <style> .세일 { padding-top: 20px; padding-bottom: 30px; padding-right: 10px; padding-left: 10px; background-color: #f5f5f5; } </style> </head> <body> <a href="{% url '홈페이지:생성' %}">세일 작성하기</a> <h1>이것이 세일 목록들입니다.</h1> {% for 인간 in 사람키 %} <div class="세일"> <a href="{% url '홈페이지:상세' 인간.pk %}"> {{ 인간.last_name }} {{ 인간.first_name }}, 나이는 {{ 인간.age }}세 </a> </div> <br/> {% endfor %} </body> </html>
위 코드에서 {% url '홈페이지:생성' %}와 같이 url 태그 안에서 네임스페이스를 활용하여 URL을 동적으로 생성할 수 있습니다.
4. URL 네임스페이스를 활용한 유지보수 용이성
네임스페이스를 활용하면 URL 패턴을 한 곳에서 관리할 수 있어 유지보수가 쉬워집니다. 예를 들어, 기존 URL make/를 입력/으로 변경한다고 가정해 봅시다.
- 기존 방식: 5만 개의 링크를 하나씩 변경해야 함
- 네임스페이스 방식: urlpatterns에서 path("입력/", 세일_입력, name="생성")로 변경하면 자동으로 반영됨
이처럼 네임스페이스를 사용하면 프로젝트 전반에 걸쳐 URL 구조 변경이 필요한 경우에도 최소한의 코드 수정만으로 대응할 수 있습니다.
5. URL 네임스페이스 적용 시 유의사항
- app_name을 반드시 설정해야 합니다.
- urlpatterns 내 각 URL 패턴에 name을 부여해야 합니다.
- 템플릿에서 url 태그 사용 시 네임스페이스:URL이름 형식으로 참조해야 합니다.
6. 결론
Django의 URL 네임스페이스를 활용하면 대규모 프로젝트에서도 효율적으로 URL을 관리할 수 있습니다. 이를 통해 코드의 유지보수성을 높이고, URL 변경 시 최소한의 수정으로 대응할 수 있습니다. 따라서 Django 프로젝트를 개발할 때는 URL 네임스페이스를 적극 활용하는 것이 좋습니다.
21. 템플릿 확장(template extending)
1. 템플릿 확장이란?
장고(Django)의 템플릿 확장(template extending) 기능은 여러 페이지에서 공통적인 레이아웃을 유지하기 위해 사용됩니다.
예를 들어, 모든 페이지에 동일한 스타일과 구조를 적용하고 싶을 때, 기본 템플릿(Base Template) 을 만들고 이를 확장하여 사용하면 효율적으로 개발할 수 있습니다.
2. 기본 템플릿 (와꾸.html) 만들기
먼저, 기본이 되는 와꾸.html(Base Template)을 생성합니다
<html> <head> <title>타이틀 넣어주면 되고.. 또.. 뭐...</title> <style> .세일 { padding-top: 20px; padding-bottom: 30px; padding-right: 10px; padding-left: 10px; background-color: #f5f5f5; } </style> </head> <body> {% block content %} {% endblock %} {% include "프로그램.html" %} </body> </html>
설명
- {% block content %} {% endblock %}
→ 이 블록 안에 개별 페이지의 내용을 삽입합니다. - {% include "프로그램.html" %}
→ 프로그램.html 파일을 포함하여 자바스크립트 기능을 추가할 수 있습니다.
3. 템플릿 확장 (세일목록.html)
세일목록.html에서 와꾸.html을 확장하여 사용합니다.
{% extends "와꾸.html" %} {% block content %} <a href="{% url '홈페이지:생성' %}">세일 작성하기</a> <h1>이것이 세일 목록들 입니다.</h1> {% for 인간 in 사람키 %} <div class="세일"> <a href="{% url '홈페이지:상세' 인간.pk %}"> {{ 인간.last_name }} {{ 인간.first_name }} , 나이는 {{ 인간.age }}세 </a> </div> <br /> {% endfor %} {% endblock content %}
설명
- {% extends "와꾸.html" %}
→ 와꾸.html을 기반으로 확장합니다. - {% block content %} ... {% endblock content %}
→ 와꾸.html의 {% block content %}에 세일 목록을 삽입합니다.
4. 자바스크립트 기능 추가 (프로그램.html)
템플릿에 포함될 자바스크립트 파일을 만듭니다.
<script> console.log("안녕"); </script>
설명
- {% include "프로그램.html" %}를 사용하여 와꾸.html에서 해당 파일을 포함하면 모든 페이지에 적용됩니다.
5. 템플릿 확장의 장점
- 코드 중복 감소: 기본 레이아웃을 한 번 정의하면 여러 페이지에서 재사용 가능
- 유지보수 용이: 기본 템플릿만 수정하면 모든 확장된 페이지에 적용됨
- 일관된 디자인 유지: 전체 페이지의 스타일과 구조를 통일할 수 있음
6. 템플릿 확장의 응용
만약 모든 페이지에 새로운 기능(예: 자바스크립트 기능 추가)이 필요하다면, 기본 템플릿만 수정하면 전체 페이지에 적용됩니다.
이처럼 템플릿 확장은 여러 페이지에 공통 요소를 추가하고 유지하는 데 매우 유용합니다.
22. Tailwind CSS를 활용한 디자인 적용
1. 파이썬 장고 프로젝트 - Tailwind CSS를 활용한 디자인 적용
1.1 디자인 프레임워크란?
웹사이트 작업 시, 모든 스타일을 직접 지정할 필요 없이 기존에 만들어진 디자인 프레임워크를 활용하면 간편하게 만들 수 있습니다. 대표적인 디자인 프레임워크에는 Bootstrap, Tailwind CSS 등이 있습니다.
1.2 Tailwind CSS 적용 방법
Tailwind CSS는 유틸리티 퍼스트(Utility-First) 방식의 CSS 프레임워크로, 클래스명만으로 손쉽게 스타일을 적용할 수 있습니다.
1.2.1 Tailwind CSS CDN 추가
Tailwind CSS를 사용하려면 CDN(Content Delivery Network)을 추가해야 합니다.
설치 방법:
<head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <script src="https://unpkg.com/@tailwindcss/browser@4"></script> </head>
위 코드를 HTML 파일의 <head> 태그 안에 삽입하면 Tailwind CSS를 사용할 수 있습니다.
2. Tailwind CSS 클래스 적용하기
Tailwind CSS는 클래스명을 추가하는 것만으로 다양한 스타일을 적용할 수 있습니다.
2.1 배경 색상 적용
<div class="bg-blue-500 text-white p-4">배경이 파란색입니다.</div>
- bg-blue-500: 배경색을 파란색으로 지정
- text-white: 글자 색상을 흰색으로 지정
- p-4: 내부 여백 추가
2.2 플렉스 박스 적용
<div class="flex justify-center items-center h-64 bg-gray-200"> <p class="text-lg font-bold">가운데 정렬된 텍스트</p> </div>
- flex: 플렉스 박스 레이아웃 적용
- justify-center: 가로 중앙 정렬
- items-center: 세로 중앙 정렬
- h-64: 높이를 64단위로 설정
- bg-gray-200: 배경을 회색으로 지정
2.3 Tailwind CSS를 이용한 레이아웃 적용
<main class="max-w-7xl mx-auto bg-purple-600 bg-opacity-75 text-white"> {% block content %} {% endblock %} </main>
- max-w-7xl: 최대 너비를 7XL로 지정
- mx-auto: 가운데 정렬
- bg-purple-600: 배경을 보라색으로 지정
- bg-opacity-75: 배경의 투명도를 75%로 설정
- text-white: 글자 색상을 흰색으로 지정
3. Tailwind CSS와 Django 템플릿 적용
Django 프로젝트에서 Tailwind CSS를 적용하려면 템플릿 파일에서 Tailwind 클래스를 활용할 수 있습니다.
3.1 Django 템플릿에서 Tailwind CSS 적용 예시
{% include "프로그램.html" %}
Django의 {% include %} 태그를 사용하면 별도의 HTML 파일을 불러와서 적용할 수 있습니다.
4. 결론
Tailwind CSS를 활용하면 Django 프로젝트에서 손쉽게 웹사이트 디자인을 적용할 수 있습니다.
- CDN을 추가하여 손쉽게 사용 가능
- 다양한 유틸리티 클래스를 활용하여 직관적인 스타일 지정 가능
- Django 템플릿과 결합하여 효율적으로 웹사이트 디자인 가능
23. Django + tailblocks 디자인 프레임워크 적용 화면 꾸미기 2
1. Django 프로젝트 개요
Django는 파이썬 기반의 웹 프레임워크로, 강력한 기능을 제공하면서도 빠른 개발이 가능합니다. 이번 강의에서는 Django를 이용하여 세일 관리 시스템을 제작하며, Tailwind CSS를 활용한 디자인 프레임워크 적용 방법을 학습합니다.
2. 프로젝트의 주요 화면
2.1. 메뉴 페이지 (메뉴.html)
이 페이지는 네비게이션 메뉴를 구성하는 역할을 하며, 목록 페이지와 회원가입 및 로그인 버튼을 포함합니다. Tailwind CSS를 사용하여 반응형 디자인을 적용하였습니다.
<header class="text-gray-600 body-font"> <div class="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center"> <a href="/" class="flex title-font font-medium items-center text-gray-900 mb-4 md:mb-0"> <span class="ml-3 text-xl">세일관리</span> </a> <nav class="md:ml-auto flex flex-wrap items-center text-base justify-center"> <a class="mr-5 hover:text-gray-900" href="{% url '홈페이지:목록' %}">목록</a> <a class="mr-5 hover:text-gray-900">회원가입</a> </nav> <button class="inline-flex items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0"> 로그인 </button> </div> </header>
2.2. 첫 화면 (첫화면.html)
이 페이지는 프로젝트의 첫 화면이며, 사용자가 처음 접속했을 때 보이는 랜딩 페이지 역할을 합니다.
{% extends "와꾸.html" %} {% block content %} <section class="text-gray-600 body-font"> <div class="container mx-auto flex px-5 py-24 items-center justify-center flex-col"> <img class="lg:w-2/6 md:w-3/6 w-5/6 mb-10 object-cover object-center rounded" alt="hero" src="https://dummyimage.com/720x600"> <div class="text-center lg:w-2/3 w-full"> <h1 class="title-font sm:text-4xl text-3xl mb-4 font-medium text-gray-900">장고 프로젝트</h1> <p class="mb-8 leading-relaxed">장고 세일 관리 입니다.</p> </div> </div> </section> {% endblock content %}
2.3. 세일 목록 페이지 (세일목록.html)
사용자가 등록한 세일 정보를 리스트 형태로 출력하는 페이지입니다. for 문을 활용하여 데이터베이스에 저장된 사용자 목록을 동적으로 렌더링합니다.
{% extends "와꾸.html" %} {% block content %} <div class="w-full text-center font-bold text-lg "> 이것이 세일 목록들 입니다. </div> <section class="text-gray-600 body-font"> <div class="w-full mb-5 px-5 flex justify-end"> <a href="{% url '홈페이지:생성' %}" class=" p-3 bg-gray-600 border-gray-700 text-white hover:bg-gray-700 cursor:pointer rounded-lg">세일 작성하기</a> </div> <div class="container px-5 py-24 mx-auto flex flex-wrap"> <div class="flex flex-col w-full md:flex-row -m-4"> {% for 인간 in 사람키 %} <div class="p-4 w-full md:w-1/2 "> <div class="flex border-2 rounded-lg border-gray-200 border-opacity-50 p-8 sm:flex-row flex-col"> <div class="w-16 h-16 sm:mr-8 sm:mb-0 mb-4 inline-flex items-center justify-center rounded-full bg-indigo-100 text-indigo-500 flex-shrink-0"> <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" class="w-8 h-8" viewBox="0 0 24 24"> <path d="M22 12h-4l-3 9L9 3l-3 9H2"></path> </svg> </div> <div class="flex-grow"> <h2 class="text-gray-900 text-lg title-font font-medium mb-3"> {{인간.last_name}} {{인간.first_name}}</h2> <p class="leading-relaxed text-base"> 나이는 {{인간.age}}세 </p> <a href="{% url '홈페이지:상세' 인간.pk %}" class="mt-3 text-indigo-500 inline-flex items-center"> 상세보기 </a> </div> </div> </div> {% endfor %} </div> </div> </section> {% endblock content %}
24. Django + tailblocks 디자인 프레임워크 적용 화면 꾸미기 3
1. Django ModelForm을 사용한 폼 생성
Django의 ModelForm을 활용하여 Sale 모델을 기반으로 입력 폼을 생성할 수 있습니다. widgets 속성을 사용하여 입력 필드의 스타일을 지정할 수 있습니다.
from django import forms from .models import Sale class SaleModelForm(forms.ModelForm): class Meta: model = Sale fields = ( "first_name", "last_name", "age", "person" ) styleInput="w-full max-w-sm border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:border-indigo-400 transition" widgets ={ "first_name": forms.TextInput(attrs={ "class": styleInput, "placeholder": "이름을 입력하세요", }), "last_name": forms.TextInput(attrs={ "class": styleInput, "placeholder": "성을 입력하세요", }), "age": forms.NumberInput(attrs={ "class": styleInput, "placeholder": "나이를 입력하세요", }), "person": forms.Select(attrs={ "class": styleInput, }), }
또한, forms.Form을 활용하여 별도의 폼을 생성할 수도 있습니다.
class SaleForm(forms.Form): first_name = forms.CharField(max_length=30) last_name = forms.CharField(max_length=30) age = forms.IntegerField(min_value=0)
2. Django 템플릿을 활용한 상세 정보 페이지
Django 템플릿을 활용하여 사용자 정보를 표시하는 페이지를 구성할 수 있습니다.
{% extends "와꾸.html" %} {% block content %} <section class="text-gray-600 body-font overflow-hidden"> <div class="container px-5 py-24 mx-auto"> <div class="lg:w-4/5 mx-auto flex flex-wrap"> <div class="lg:w-1/2 w-full lg:pr-10 lg:py-6 mb-6 lg:mb-0"> <h1 class="text-gray-900 text-3xl title-font font-medium mb-4">{{사람키.last_name }} {{사람키.first_name }}</h1> <div class="flex mb-4"> <a class="flex-grow text-indigo-500 border-b-2 border-indigo-500 py-2 text-lg px-1 cursor-pointer">고객정보</a> <a class="flex-grow border-b-2 border-gray-300 py-2 text-lg px-1 cursor-pointer">평가</a> <a href="{% url '홈페이지:업뎃' 사람키.pk %}" class="flex-grow border-b-2 border-gray-300 py-2 text-lg px-1 cursor-pointer">정보수정</a> </div> <p class="leading-relaxed mb-4">짜장면을 좋아하시는 연구소 소장님</p> <div class="flex border-t border-gray-200 py-2"> <span class="text-gray-500">나이</span> <span class="ml-auto text-gray-900">{{사람키.age}}</span> </div> <div class="flex justify-end"> <a href="{% url '홈페이지:목록' %}" class="flex ml-auto text-white bg-blue-500 border-0 py-2 px-6 focus:outline-none hover:bg-blue-600 rounded cursor-pointer">목록으로 돌아가기</a> </div> </div> <img alt="ecommerce" class="lg:w-1/2 w-full lg:h-auto h-64 object-cover object-center rounded" src="https://picsum.photos/400/400"> </div> </div> </section> {% endblock content %}
3. Django 템플릿을 활용한 정보 수정 페이지
사용자 정보를 수정할 수 있는 페이지를 템플릿으로 구성할 수 있습니다.
{% extends "와꾸.html" %} {% block content %} <section class="text-gray-600 body-font overflow-hidden"> <div class="container px-5 py-24 mx-auto"> <h1 class="text-center text-4xl font-bold mb-10"> {{사람키.last_name}} {{사람키.first_name}} 님의 정보를 수정하세요. </h1> <div class="lg:w-4/5 mx-auto flex flex-wrap"> <div class="lg:w-1/2 w-full lg:pr-10 lg:py-6 mb-6 lg:mb-0"> <form method="post"> {% csrf_token %} <div class="w-full flex flex-col"> <div class="w-full flex justify-between items-center mb-4"> <label class="w-[50px] text-gray-700 text-sm font-bold" for="id_last_name">성</label> {{ 폼키.last_name }} </div> <div class="w-full flex justify-between items-center mb-4"> <label class="w-[50px] text-gray-700 text-sm font-bold" for="id_first_name">이름</label> {{ 폼키.first_name }} </div> <div class="w-full flex justify-between items-center mb-4"> <label class="w-[50px] text-gray-700 text-sm font-bold" for="id_age">나이</label> {{ 폼키.age }} </div> </div> <input type="hidden" name="id" value="{{사람키.pk}}"> <div class="flex justify-end space-x-4 mt-15"> <button type="button" onclick="deleteCustomer(event, '{% url '홈페이지:지우기' 사람키.pk %}')" class="text-white bg-red-500 border-0 py-2 px-6 focus:outline-none hover:bg-red-600 rounded cursor-pointer">삭제하기</button> <button type="submit" class="text-white bg-indigo-500 border-0 py-2 px-6 focus:outline-none hover:bg-indigo-600 rounded cursor-pointer">수정하기</button> </div> </form> </div> <img alt="ecommerce" class="lg:w-1/2 w-full lg:h-auto h-64 object-cover object-center rounded" src="https://picsum.photos/400/400"> </div> </div> </section> {% endblock content %}
4. 고객 정보 삭제 스크립트
고객 정보를 삭제하는 버튼을 클릭하면 확인 메시지를 띄우고, 삭제 요청을 서버로 보냅니다.
<script> function deleteCustomer(event, url) { event.preventDefault() if (confirm('고객을 정말 삭제하시겠습니까?')) { const form = document.createElement('form'); form.method = 'POST'; form.action = url; const csrfToken = document.querySelector("input[name='csrfmiddlewaretoken']").value; const csrfInput = document.createElement('input'); csrfInput.type = 'hidden'; csrfInput.name = 'csrfmiddlewaretoken'; csrfInput.value = csrfToken; form.appendChild(csrfInput); document.body.appendChild(form); form.submit(); } } </script>
25. 클래스형 뷰(class view)를 이용한 CRUD 구현,NoReverseMatch
1. Django 클래스형 뷰(Class-Based Views) 개요
Django는 웹 프레임워크로서 CRUD(Create, Read, Update, Delete) 기능을 쉽게 구현할 수 있도록 다양한 기능을 제공합니다. 기존에는 함수형 뷰(Function-Based View, FBV)로 CRUD를 구현했지만, Django에서 제공하는 클래스형 뷰(Class-Based View, CBV)를 사용하면 더욱 간결하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.
2. URL 설정 및 클래스형 뷰 적용
from django.urls import path from .views import 세일_목록View, 세일_상세View, 세일_입력View, 세일_업데이트View, 세일_지우기View app_name = "홈페이지" urlpatterns = [ path("", 세일_목록View.as_view(), name="목록"), path("<int:pk>/", 세일_상세View.as_view(), name="상세"), path("<int:pk>/업데이트/", 세일_업데이트View.as_view(), name="업뎃"), path("<int:pk>/지우기/", 세일_지우기View.as_view(), name="지우기"), path("ma_monde/", 세일_입력View.as_view(), name="생성"), ]
Django의 path 함수에서 as_view() 메서드를 사용하여 클래스형 뷰를 등록할 수 있습니다.
3. 클래스형 뷰 구현
3.1 첫 화면 뷰
from django.views import generic class 첫화면View(generic.TemplateView): template_name = '첫화면.html'
3.2 목록 뷰 (ListView)
class 세일_목록View(generic.ListView): template_name = 'newfolder/세일목록.html' queryset = Sale.objects.all() context_object_name = "사람키"
3.3 상세 뷰 (DetailView)
class 세일_상세View(generic.DetailView): template_name = 'newfolder/세일상세.html' queryset = Sale.objects.all() context_object_name = "사람키"
3.4 입력 뷰 (CreateView)
class 세일_입력View(generic.CreateView): template_name = 'newfolder/세일_입력.html' form_class = SaleModelForm def get_success_url(self): return reverse("홈페이지:목록")
3.5 업데이트 뷰 (UpdateView)
class 세일_업데이트View(generic.UpdateView): template_name = 'newfolder/세일_업데이트.html' form_class = SaleModelForm queryset = Sale.objects.all() context_object_name = "사람키" def get_success_url(self): return reverse("홈페이지:목록")
3.6 삭제 뷰 (DeleteView)
class 세일_지우기View(generic.DeleteView): queryset = Sale.objects.all() def get_success_url(self): return reverse("홈페이지:목록")
4. 템플릿 파일 (예시: 세일_입력.html)
{% extends "와꾸.html" %} {% block content %} <section class="text-gray-600 body-font overflow-hidden"> <div class="container px-5 py-24 mx-auto"> <h1 class="text-center text-4xl font-bold mb-15">세일 입력 페이지</h1> <div class="max-w-3xl mx-auto"> <form method="post"> {% csrf_token %} <div class="w-full flex flex-col"> <div class="w-full grid grid-cols-10 gap-4 items-center mb-4"> <label class="col-span-3 text-gray-700 text-xl font-bold">성</label> <div class="col-span-7">{{ form.last_name }}</div> </div> <div class="w-full grid grid-cols-10 gap-4 items-center mb-4"> <label class="col-span-3 text-gray-700 text-xl font-bold">이름</label> <div class="col-span-7">{{ form.first_name }}</div> </div> <div class="w-full grid grid-cols-10 gap-4 items-center mb-4"> <label class="col-span-3 text-gray-700 text-xl font-bold">나이</label> <div class="col-span-7">{{ form.age }}</div> </div> </div> <div class="flex justify-end space-x-4 mt-15"> <button type="submit" class="text-white bg-indigo-500 py-2 px-6 hover:bg-indigo-600 rounded cursor-pointer"> 작성하기 </button> </div> </form> </div> </div> </section> {% endblock content %}
5. 정리 및 결론
클래스형 뷰(Class-Based View)를 활용하면 Django에서 CRUD 기능을 보다 효율적으로 구현할 수 있습니다.
- ListView : 객체 목록을 보여줌
- DetailView : 특정 객체의 상세 정보를 보여줌
- CreateView : 새로운 객체를 생성함
- UpdateView : 기존 객체를 수정함
- DeleteView : 객체를 삭제함
Django가 제공하는 제네릭 뷰를 활용하면 코드 중복을 줄이고 유지보수성을 높일 수 있습니다.
26. Django 프로젝트 - 사용자 인증 (로그인 및 로그아웃)
1. 개요
Django에서는 기본적으로 제공하는 인증 시스템을 활용하여 사용자 로그인과 로그아웃을 쉽게 구현할 수 있습니다. 이번 강의에서는 Django의 LoginView와 LogoutView를 활용하여 로그인 및 로그아웃 기능을 만드는 방법을 설명합니다.
2. 프로젝트 설정
2.1 URL 설정
Django의 urls.py에서 로그인과 로그아웃 URL을 설정합니다.
from django.contrib import admin from django.urls import path, include from django.contrib.auth.views import LoginView, LogoutView from sales.views import 첫화면View, CustomLogoutView urlpatterns = [ path('admin/', admin.site.urls), path('', 첫화면View.as_view()), path('홈페이지/', include('sales.urls', namespace='홈페이지')), path('로그인/', LoginView.as_view(), name='로긴'), path('로그아웃/', CustomLogoutView.as_view(), name='록아웃'), ]
2.2 설정 파일 변경
로그인 후 리디렉션될 페이지를 설정합니다.
# settings.py LOGIN_REDIRECT_URL = "/홈페이지"
3. 로그인 템플릿 생성
로그인 폼을 제공하는 login.html 템플릿을 작성합니다.
{% extends "와꾸.html" %} {% block content %} <form method="post"> <section class="text-gray-600 body-font"> {% csrf_token %} <div class="container px-5 py-24 mx-auto flex flex-wrap items-center"> <div class="lg:w-2/6 mx-auto md:w-1/2 bg-gray-100 rounded-lg p-8 flex flex-col md:ml-auto w-full mt-10 md:mt-0"> <h2 class="text-gray-900 text-lg font-medium title-font mb-5 text-center">로그인 해 주세요</h2> {% if form.non_field_errors %} <div class="mb-4 p-3 bg-red-100 text-red-600 rounded"> {% for error in form.non_field_errors %} <p>{{ error }}</p> {% endfor %} </div> {% endif %} <div class="relative mb-4"> <label for="id_username" class="leading-7 text-sm text-gray-600">유저이름</label> <input type="text" id="id_username" name="username" required class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"> {% if form.username.errors %} <p class="mt-1 text-red-500 text-sm"> {% for error in form.username.errors %} {{ error }} {% endfor %} </p> {% endif %} </div> <div class="relative mb-4"> <label for="id_password" class="leading-7 text-sm text-gray-600">비밀번호</label> <input type="password" id="id_password" name="password" required class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"> {% if form.password.errors %} <p class="mt-1 text-red-500 text-sm"> {% for error in form.password.errors %} {{ error }} {% endfor %} </p> {% endif %} </div> <button class="text-white bg-indigo-500 border-0 py-2 px-8 focus:outline-none hover:bg-indigo-600 rounded text-lg cursor-pointer"> 로그인 </button> </div> </div> </section> </form> {% endblock content %}
4. 헤더 설정
사용자의 로그인 여부에 따라 메뉴를 다르게 표시하는 header.html을 설정합니다.
<header class="text-gray-600 body-font"> <div class="container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center"> <a href="/" class="flex title-font font-medium items-center text-gray-900 mb-4 md:mb-0"> <span class="ml-3 text-xl">세일관리</span> </a> <nav class="md:ml-auto flex flex-wrap items-center text-base justify-center"> <a class="mr-5 hover:text-gray-900" href="{% url '홈페이지:목록' %}">목록</a> {% if not request.user.is_authenticated %} <a class="mr-5 hover:text-gray-900">회원가입</a> {% endif %} </nav> {% if request.user.is_authenticated %} {{ request.user.username }} 님 <a href="{% url '록아웃' %}" class="ml-5 inline-flex items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0"> 로그아웃 </a> {% else %} <a href="{% url '로긴' %}" class="inline-flex items-center bg-gray-100 border-0 py-1 px-3 focus:outline-none hover:bg-gray-200 rounded text-base mt-4 md:mt-0"> 로그인 </a> {% endif %} </div> </header>
5. 로그아웃 구현
Django에서 기본 제공하는 LogoutView를 활용하여 로그아웃 기능을 구현합니다.
from django.contrib.auth import logout from django.shortcuts import redirect from django.views import View class CustomLogoutView(View): def get(self, request): logout(request) return redirect('/')
6. 결론
이제 로그인 및 로그아웃 기능이 정상적으로 동작합니다. Django에서 제공하는 기본 뷰를 활용하면 쉽고 빠르게 인증 시스템을 구축할 수 있습니다.
27. 파이썬 장고(Python Django) 프로젝트 - 인증 처리 2 - 회원가입 만들기
1. 회원가입 기능 개요
Django에서는 기본적으로 제공되는 인증 기능을 활용하여 회원가입 기능을 구현할 수 있습니다. 그러나 로그인과 로그아웃 기능과 달리, 회원가입은 직접 뷰(View)를 생성하고, 회원가입 폼을 구성해야 합니다. 이를 위해 Django의 UserCreationForm을 확장하여 우리만의UserCreationForm을 만들고, 이를 기반으로 회원가입 뷰를 작성합니다.
2. 회원가입 폼 생성
회원가입 폼은 Django에서 제공하는 UserCreationForm을 확장하여 제작합니다. 기본적인 사용자 정보(아이디, 이메일, 비밀번호)를 입력받을 수 있도록 설정합니다.
from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth import get_user_model User = get_user_model() styleInput = "w-full max-w-sm border border-gray-300 rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:border-indigo-400 transition" class 우리만의UserCreationForm(UserCreationForm): class Meta: model = User fields = ("username", "email", "password1", "password2") widgets = { "username": forms.TextInput(attrs={"class": styleInput, "placeholder": "아이디를 입력하세요"}), "email": forms.EmailInput(attrs={"class": styleInput, "placeholder": "이메일을 입력하세요"}), "password1": forms.PasswordInput(attrs={"class": styleInput, "placeholder": "비밀번호를 입력하세요"}), "password2": forms.PasswordInput(attrs={"class": styleInput, "placeholder": "비밀번호를 다시 입력하세요"}) }
3. 회원가입 뷰(View) 작성
회원가입 뷰는 Django의 CreateView를 확장하여 작성하며, 회원가입 성공 시 로그인 페이지로 이동하도록 설정합니다.
from django.views import generic from django.contrib import messages from django.urls import reverse from .forms import 우리만의UserCreationForm class 회원가입View(generic.CreateView): template_name = 'registration/회원가입.html' form_class = 우리만의UserCreationForm def get_success_url(self): return reverse("로긴") def form_valid(self, form): response = super().form_valid(form) messages.success(self.request, "회원가입을 축하합니다! 로그인 후 서비스를 이용하세요.") return response
4. URL 설정
회원가입 기능을 사용하기 위해 urls.py에 경로를 추가합니다.
from django.urls import path, include from django.contrib.auth.views import LoginView from sales.views import 회원가입View urlpatterns = [ path('로그인/', LoginView.as_view(), name='로긴'), path('회원가입/', 회원가입View.as_view(), name='가입'), ]
5. 회원가입 템플릿 작성
회원가입 페이지는 Django 템플릿을 활용하여 작성합니다. 사용자 입력 필드를 구성하고, 에러 메시지를 출력할 수 있도록 설정합니다.
{% extends "와꾸.html" %} {% block content %} <form method="post"> <section class="text-gray-600 body-font"> {% csrf_token %} <div class="container px-5 py-24 mx-auto flex flex-wrap items-center"> <div class="lg:w-2/6 mx-auto md:w-1/2 bg-gray-100 rounded-lg p-8 flex flex-col md:ml-auto w-full mt-10 md:mt-0"> <h2 class="text-gray-900 text-lg font-medium title-font mb-5 text-center">회원가입을 해 주세요</h2> <!-- 로그인 실패 시 전체적인 에러 메시지 표시 --> {% if form.non_field_errors %} <div class="mb-4 p-3 bg-red-100 text-red-600 rounded"> {% for error in form.non_field_errors %} <p>{{ error }}</p> {% endfor %} </div> {% endif %} <!-- 유저이름 입력 필드 --> <div class="relative mb-4"> <label for="id_username" class="leading-7 text-sm text-gray-600">유저이름</label> <input type="text" id="id_username" name="username" required class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"> <!-- 유저이름 입력 에러 메시지 --> {% if form.username.errors %} <p class="mt-1 text-red-500 text-sm"> {% for error in form.username.errors %} {{ error }} {% endfor %} </p> {% endif %} </div> <!-- 이메일 입력 필드 --> <div class="relative mb-4"> <label for="email" class="leading-7 text-sm text-gray-600">이메일</label> <input type="email" id="email" name="email" required class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"> <!-- 이메일 입력 에러 메시지 --> {% if form.email.errors %} <p class="mt-1 text-red-500 text-sm"> {% for error in form.email.errors %} {{ error }} {% endfor %} </p> {% endif %} </div> <!-- 비밀번호 입력 필드 --> <div class="relative mb-4"> <label for="id_password1" class="leading-7 text-sm text-gray-600">비밀번호</label> <input type="password" id="id_password1" name="password1" required class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"> <!-- 비밀번호 입력 에러 메시지 --> {% if form.password1.errors %} <p class="mt-1 text-red-500 text-sm"> {% for error in form.password1.errors %} {{ error }} {% endfor %} </p> {% endif %} </div> <!-- 비밀번호 확인 입력 필드 --> <div class="relative mb-4"> <label for="id_password2" class="leading-7 text-sm text-gray-600">비밀번호 확인</label> <input type="password" id="id_password2" name="password2" required class="w-full bg-white rounded border border-gray-300 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out"> <!-- 비밀번호 확인 입력 에러 메시지 --> {% if form.password2.errors %} <p class="mt-1 text-red-500 text-sm"> {% for error in form.password2.errors %} {{ error }} {% endfor %} </p> {% endif %} </div> <button class="text-white bg-indigo-500 border-0 py-2 px-8 focus:outline-none hover:bg-indigo-600 rounded text-lg cursor-pointer"> 로그인 </button> </div> </div> </section> </form> {% endblock content %}
6. 회원가입 성공 메시지 출력
회원가입이 성공적으로 완료되었을 때, Django의 messages 프레임워크를 활용하여 성공 메시지를 출력할 수 있습니다.
{% if messages %} {% for message in messages %} <div class="max-w-7xl text-center mt-15 text-green-600 font-bold"> {{ message }} </div> {% endfor %} {% endif %}
이렇게 구현하면 Django의 기본 제공 기능을 활용하면서도, 사용자 친화적인 회원가입 시스템을 구축할 수 있습니다.
28.Django Signal을 활용한 자동 UserProfile 생성
1. 개요
Django의 Signal 기능을 활용하여 새로운 사용자가 생성될 때 자동으로 UserProfile을 생성하는 방법을 설명합니다. 이를 통해 회원 가입 시 별도의 추가 작업 없이 프로필이 자동으로 생성되는 시스템을 구축할 수 있습니다.
2. 모델 정의
from django.db import models from django.contrib.auth.models import AbstractUser from django.db.models.signals import post_save from django.dispatch import receiver # 사용자 모델 (AbstractUser 상속) class 아이디(AbstractUser): pass # 사용자 모델 (AbstractUser 상속) class UserProfile(models.Model): 회원 = models.OneToOneField(아이디, on_delete=models.CASCADE) def __str__(self): return self.회원.username # 개인 정보 모델 class Person(models.Model): 회원 = models.OneToOneField(아이디, on_delete=models.CASCADE) 조직 = models.OneToOneField(UserProfile, on_delete=models.CASCADE) def __str__(self): return self.회원.email # 판매 데이터 모델 class Sale(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) age = models.IntegerField(default=0) person = models.ForeignKey(Person, on_delete=models.CASCADE) def __str__(self): return f"{self.last_name} {self.first_name}" # 사용자 생성 시 자동으로 UserProfile 생성 @receiver(post_save, sender=아이디) def 회원생성signal(sender, instance, created, **kwargs): #print("**** instance, created :",sender, instance, created) if created: UserProfile.objects.create(회원=instance) print(f"새로운 회원이 생성되었습니다: {instance.username}") #post_save.connect(회원생성signal, sender=아이디)
3. Admin 설정
from django.contrib import admin from .models import 아이디, Sale,Person,UserProfile admin.site.register(아이디) admin.site.register(Sale) admin.site.register(Person) admin.site.register(UserProfile)
4. Signal을 이용한 UserProfile 자동 생성
from django.db.models.signals import post_save from django.dispatch import receiver from .models import 아이디, UserProfile # 사용자 생성 시 자동으로 UserProfile 생성 @receiver(post_save, sender=아이디) def 회원생성signal(sender, instance, created, **kwargs): #print("**** instance, created :",sender, instance, created) if created: UserProfile.objects.create(회원=instance) print(f"새로운 회원이 생성되었습니다: {instance.username}") #post_save.connect(회원생성signal, sender=아이디)
(1) post_save 시그널이란?
- 특정 모델(여기서는 아이디)의 객체가 저장될 때 실행됩니다.
- created=True 조건을 추가하여, 새로운 객체가 생성될 때만 실행되도록 설정합니다.
- UserProfile.objects.create(회원=instance)을 통해 자동으로 UserProfile을 생성합니다.
(2) 시그널을 사용하여 자동화
- 사용자가 생성될 때마다 UserProfile이 자동으로 생성됩니다.
- 추가적인 설정 없이도 Django의 내장 기능을 활용하여 간편하게 관리할 수 있습니다.
- 콘솔에서 print()를 통해 로그를 남기면, 동작 확인이 가능합니다.
5. 데이터베이스 마이그레이션
새로운 모델을 정의하고 적용하려면 다음 명령어를 실행해야 합니다:
python manage.py makemigrations python manage.py migrate
기존 데이터베이스를 사용 중이라면, 필요에 따라 초기화 후 재설정이 필요할 수 있습니다.
6. 테스트 방법
새로운 사용자 생성
- Django Admin을 통해 새 사용자 추가
- 또는 Python shell에서 직접 생성:
from django.contrib.auth import get_user_model User = get_user_model() user = User.objects.create(username='testuser', password='testpassword')
UserProfile 자동 생성 확인
- UserProfile.objects.all()을 실행하여 자동 생성 여부 확인
from .models import UserProfile print(UserProfile.objects.all())
사용자를 삭제하면 연결된 UserProfile도 삭제되는지 확인
7. 결론
- Django의 Signal을 활용하면, 특정 이벤트 발생 시 자동으로 관련 데이터를 처리할 수 있습니다.
- 본 예제에서는 사용자가 생성될 때 자동으로 UserProfile이 생성되는 로직을 구현했습니다.
- 이를 응용하여 다양한 자동화 기능을 추가할 수 있습니다.
추가 개발: 더 복잡한 권한 관리 및 조직 구조 반영을 위해 Group, Permission 등을 활용할 수도 있습니다.
29.sqLite에서 PostgreSQL로- 장고 PostgreSQL DB 연동
1. PostgreSQL 설치
- 운영체제에 맞는 PostgreSQL 및 pgAdmin을 다운로드하여 설치합니다.
- 설치 과정에서 설정한 비밀번호를 기억해둡니다.
2. pgAdmin에서 데이터베이스 생성
1) 서버 그룹 생성
- pgAdmin 실행 후, 마우스 오른쪽 클릭 → Create → Server Group 생성
2) 서버 추가
- Create → Server에서
- 이름 지정
- Connection 탭에서 Host: localhost, Port: 5432, Username: postgres, Password 입력
3) 데이터베이스 생성
- Create → Database에서 이름을 지정하고 생성
3. Django 프로젝트 설정 변경
- settings.py의 DATABASES 설정을 다음과 같이 수정
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'your_database_name', 'USER': 'your_username', 'PASSWORD': 'your_password', 'HOST': 'localhost', 'PORT': '5432', } }
4. 필수 패키지 설치
pip install psycopg2
5. 마이그레이션 실행
python manage.py migrate
6. 슈퍼유저 생성
python manage.py createsuperuser
7. 서버 실행 후 확인
python manage.py runserver
- 정상적으로 실행되면 PostgreSQL 연동 완료!
댓글 ( 0)
댓글 남기기