본문 바로가기

카테고리 없음

내일배움캠프 2022.06.16 TIL

오늘의 과제

1. Django 프로젝트를 생성하고, user 라는 앱을 만들어서 settings.py 에 등록해보세요.
2. user/models.py에 `Custom user model`을 생성한 후 django에서 user table을 생성 한 모델로 사용할 수 있도록 설정해주세요.
3. user/models.py에 사용자의 상세 정보를 저장할 수 있는 `UserProfile` 이라는 모델을 생성해주세요.
4. blog라는 앱을 만든 후 settings.py에 등록해주세요.
5. blog/models.py에 <카테고리 이름, 설명>이 들어갈 수 있는 `Category`라는 모델을 만들어보세요.
6. blog/models.py에 <글 작성자, 글 제목, 카테고리, 글 내용>이 들어갈 수 있는 `Article` 이라는 모델을 만들어보세요.(카테고리는 2개 이상 선택할 수 있어야 해요)
7. Article 모델에서 외래 키를 활용해서 작성자와 카테고리의 관계를 맺어주세요.
8. admin.py에 만들었던 모델들을 추가해 사용자와 게시글을 자유롭게 생성, 수정 할 수 있도록 설정해주세요.
9. CBV 기반으로 로그인 / 로구아웃 기능을 구현해주세요,
10. CBV 기반으로 로그인 한 사용자의 게시글의 제목을 리턴해주는 기능을 구현해주세요.

 

1. Django 프로젝트 및 user 앱 생성 후 settings.py에 등록하기

 

django-admin startproject DRF .

위의 명령어를 통해 DRF 라는 이름의 Django 프로젝트를 생성한다.

django-admin startapp user

위의 명령어를 통해 user 라는 이름의 앱을 생성한다.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'user',
]

DRF 폴더의 settings.py 내의 INSTALLED_APPS 리스트에 user 앱을 추가해준다.

 

 

2. user/models.py에 Custom user model을 생성하고, Django에서 user table을 생성한 모델로 사용할 수 있도록 설정하기

 

Django에서 커스텀 유저 모델을 생성하기 위해서는 두 개의 클래스 (BaseUserManager, AbstractBaseUser)를 구현해야한다. BaseUserManager 클래스는 유저를 생성할 때 사용하는 헬퍼(Helper) 클래스이며, 실제 모델(Model) 은 AbstractBaseUser을 상속받아 생성하는 클래스이다. 

 

우선, 헬퍼 클래스인 BaseUserManager를 상속받는 UserManager 클래스를 만들어보자.

class UserManager(BaseUserManager):
    def create_user(self, username, password=None):
        if not username:
            raise ValueError('Users must have an username')
        user = self.model(
            username=username,
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    # python manage.py createsuperuser 사용 시 해당 함수가 사용됨
    def create_superuser(self, username, password=None):
        user = self.create_user(
            username=username,
            password=password
        )
        user.is_admin = True
        user.save(using=self._db)
        return user

위와 같이 UserManager 클래스를 작성해준다. create_user 함수는 말 그대로 user를 생성해주는 함수이고, create_superuser 함수는 superuser를 생성해주는 함수이다.

python manage.py createsuperuser

위와 같은 명령어가 입력될 시, create_superuser 함수가 호출된다.

 

이번에는 실제 모델인 AbstractBaseUser을 상속받는 User 클래스를 만들어보자.

class User(AbstractBaseUser):
    username = models.CharField("사용자 계정", max_length=20, unique=True)
    email = models.EmailField("이메일 주소", max_length=100)
    password = models.CharField("비밀번호", max_length=128)
    fullname = models.CharField("이름", max_length=20)
    join_date = models.DateField("가입일", auto_now_add=True)

    # is_active가 False일 경우 계정이 비활성화됨
    is_active = models.BooleanField(default=True)

    # is_staff에서 해당 값 사용
    is_admin = models.BooleanField(default=False)

    # id로 사용 할 필드 지정.
    # 로그인 시 USERNAME_FIELD에 설정 된 필드와 password가 사용된다.
    USERNAME_FIELD = 'username'

    # user를 생성할 때 입력받은 필드 지정
    REQUIRED_FIELDS = []

    objects = UserManager()  # custom user 생성 시 필요

    def __str__(self):
        return self.username

    # 로그인 사용자의 특정 테이블의 crud 권한을 설정, perm table의 crud 권한이 들어간다.
    # admin일 경우 항상 True, 비활성 사용자(is_active=False)의 경우 항상 False
    def has_perm(self, perm, obj=None):
        return True

    # 로그인 사용자의 특정 app에 접근 가능 여부를 설정, app_label에는 app 이름이 들어간다.
    # admin일 경우 항상 True, 비활성 사용자(is_active=False)의 경우 항상 False
    def has_module_perms(self, app_label):
        return True

    # admin 권한 설정
    @property
    def is_staff(self):
        return self.is_admin

위와 같이 User 클래스를 작성해준다. 

 

이제 Django가 user table을 생성한 모델로 사용할 수 있도록 해보자. settings.py를 수정해주면 된다.

AUTH_USER_MODEL = 'user.User'

위의 코드를 settings.py에 추가해준다.

 

 

3. user/models.py에 사용자의 상세 정보를 등록할 수 있는 UserProfile 모델 생성하기

사용자의 상세 정보들을 하나의 column으로 지정해준다. 나의 경우, username, description, nickname, age, hobby를 column으로 할 수 있도록 지정해주었다. 또, hobby의 경우 클래스를 하나 더 생성하여 Many-to-Many 관계를 가질 수 있도록 설정하였다.

class UserProfile(models.Model):
    user = models.OneToOneField(User, verbose_name="유저", on_delete=models.CASCADE)
    description = models.TextField("한 줄 소개", max_length=256)
    nickname = models.TextField("별명", max_length=50)
    age = models.IntegerField("나이")
    hobby = models.ManyToManyField(Hobby, verbose_name="취미")

    def __str__(self):
        return f"{self.user.username} 님의 프로필"

위와 같이 UserProfile을 작성하였다.

class Hobby(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name

Hobby 클래스는 위와 같이 작성하였다.

 

 

4. blog 앱 생성 후, settings.py에 등록하기

 

django-admin startapp blog

위의 명령어를 통해 blog 라는 이름의 앱을 추가해준다.

 

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'user',
    'blog',
]

DRF 폴더의 settings.py 내의 INSTALLED_APPS 리스트에 blog 앱을 추가해준다.

 

 

5. blog/models.py에 <카테고리 이름, 설명>이 들어갈 수 있는 'Category' 모델 생성하기

class Category(models.Model):
    name = models.CharField(max_length=50)
    description = models.TextField(max_length=100)

    def __str__(self):
        return self.name

위와 같이 models.py에 Category 클래스를 생성해주었다.

 


6. blog/models.py에 <글 작성자, 글 제목, 카테고리, 글 내용>이 들어갈 수 있는 'Article' 이라는 모델 생성하기 (카테고리는 2개 이상 선택 가능하도록)

class Article(models.Model):
    username = models.ForeignKey(UserModel, on_delete=models.CASCADE)
    title = models.TextField(max_length=100)
    category = models.ManyToManyField(Category, related_name="articles")
    contents = models.TextField(max_length=256)

    def __str__(self):
        return f"{self.user.username} 님의 게시글"

위와 같이 username은 UserModel로부터 사용자의 이름을 foreign key로 가져올 수 있도록 하였다. 왜냐하면 게시글 하나 당 작성자는 한 명일 수 밖에 없기 때문이다. 그러나 한 명의 사용자는 여러 게시글을 작성할 수 있으므로 One-to-Many 관계를 가지는 것을 알 수 있다. 반면, category는 하나의 category에 여러 게시글이 있을 수 있고, 하나의 게시글도 여러 개의 category를 가질 수 있으므로 Many-to-Many 관계를 가질 수 있도록 설정해주었다.

 


7. Article 모델에서 외래 키를 활용해서 작성자와 카테고리의 관계를 맺어주세요.

위와 동일합니다.

 


8. admin.py에 만들었던 모델들을 추가해 사용자와 게시글을 자유롭게 생성, 수정할 수 있도록 설정하기

admin.site.register(User)
admin.site.register(UserProfile)
admin.site.register(Hobby)

user/admin.py에 다음과 같이 작성해준다.

 

admin.site.register(Category)
admin.site.register(Article)

blog/admin.py에 다음과 같이 작성해준다.

 


9. CBV 기반으로 로그인 / 로그아웃 기능 구현하기

class UserApiView(APIView):
    def post(self, request):
        username = request.data.get('username', '')
        password = request.data.get('password', '')

        user = authenticate(request, username=username, password=password)
        if not user:
            return Response({"error": "존재하지 않는 계정이거나 패스워드가 일치하지 않습니다."})

        login(request, user)
        return Response({"message": "로그인 성공!!"})

    def delete(self, request):
        logout(request)
        return Response({"message": "로그아웃 성공!!"})

다음과 같이 UserApiView 클래스를 작성해준다. POST 메소드가 들어왔을 경우에는 로그인을 시도하고, DELETE 메소드가 들어왔을 경우에는 로그아웃을 하도록 작성해주었다.

 


10. CBV 기반으로 로그인 한 사용자의 게시글의 제목을 리턴해주는 기능을 구현하기

class UserArticleView(APIView):
    permission_classes = [permissions.AllowAny]

    def get(self, request):
        user = request.user
        articles = Article.objects.filter(user_id=user.id).values()
        titles=[]
        for article in articles:
            titles.append(article['title'])
        title_list_str=", ".join(titles)
        return Response({"title": title_list_str})

위와 같이 articles를 가져와서 title들을 titles라는 리스트에 추가한 후, 이를 쉼표로 이어붙인 문자열형으로 바꿔 리턴해준다.