django의 permission 기능에 대해 찾아보던 중 유익해보는 포스트를 발견했다. 그런데 거기서 아래와 같은 model 설정을 보게 되었다.출처: [Django] Authentication 과 Permissions
눈이 번뜩 뜨였다. FK를 사용하여 테이블을 연결하면 운동 기록들을 사용자에 직접 연결해놓을 수 있지 않을까?
지금까지는 각 테이블마다 username이라는 필드를 생성하고 CharField로 받았다.
ABC라는 username을 가진 사용자가 로그인하고 운동을 수행한 뒤 저장 버튼을 누르면, Unity앱에서는 playerprefs에 보관하고 있던 ABC라는 username과 함께 count / day / time 등의 값을 보낸다.
서버에서는 받은 데이터를 데이터베이스에 저장한다.
그 후 앱이나 웹에서 특정 username을 포함하여 원하는 자원에 연결된 url로 요청을 보내면, 각 기록을 받아갈 수 있도록 하였다.
이렇게 해도 큰 문제는 없었다. 하지만 FK를 한번 써보고싶단 생각이 있었기 때문에 바로 해볼 것이다.
from django.db import models
from django.contrib.auth.models import AbstractUser, PermissionsMixin
# 계정 정보
class User(AbstractUser, PermissionsMixin):
class Meta:
ordering = ['date_joined']
# 이두 운동 관련된 모델
class BicepsCurl(models.Model):
username = models.CharField(max_length=25)
count = models.IntegerField()
count1 = models.IntegerField()
count2 = models.IntegerField()
sum_times = models.IntegerField(null=True)
sum_count = models.IntegerField(null=True)
times = models.FloatField(max_length=255)
title = models.CharField(max_length=255, null=True)
day = models.CharField(max_length=255, null=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return ("TotalCount:"+str(self.count)+" LCount:"+str(self.count1)+
" RCount:"+str(self.count2)+" time:"+str(self.times)+" day:"+self.day)
class Meta:
ordering = ['created']
# 스쿼트 운동 관련 모델
class Squat(models.Model):
username = models.CharField(max_length=25)
count = models.FloatField(max_length=255)
sum_times = models.IntegerField(null=True)
sum_count = models.IntegerField(null=True)
times = models.FloatField(max_length=255)
title = models.CharField(max_length=255, null=True)
day = models.CharField(max_length=255, null=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "Count:"+str(self.count)+" Time:"+str(self.times)+" Date:"+self.day
class Meta:
ordering = ['created']
# 푸쉬업 운동 관련 모델
class PushUp(models.Model):
username = models.CharField(max_length=25)
count = models.FloatField(max_length=255)
sum_times = models.IntegerField(null=True)
sum_count = models.IntegerField(null=True)
times = models.FloatField(max_length=255)
title = models.CharField(max_length=255, null=True)
day = models.CharField(max_length=255, null=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "Count:"+str(self.count)+" Time:"+str(self.times)+" Date:"+self.day
class Meta:
ordering = ['created']
username이 공통적으로 들어가 있는 것을 볼 수 있다.
username을 단서로 하여 다른 값들을 특정하는 방법을 사용했었다.
이제 이걸 ForeignKey
로 설정해볼 것임!
다른 건 특별할 것이 없고
# 이두 운동 관련된 모델
class BicepsCurl(models.Model):
username = models.ForeignKey(User, on_delete=models.CASCADE)
...
# 스쿼트 운동 관련 모델
class Squat(models.Model):
username = models.ForeignKey(User, on_delete=models.CASCADE)
...
# 푸쉬업 운동 관련 모델
class PushUp(models.Model):
username = models.ForeignKey(User, on_delete=models.CASCADE)
models.CharField()
를 models.ForeignKey(User, on_delete=models.CASCADE)
로 바꿔주기만 했다.
이렇게 한 후 $ makemigrations
와 $ migrate
를 진행
DB를 밀고 실행했으므로 오류없이 잘 끝났다.
회원등록부터 해봤다.
굳굳 됩니다 돼요!
그 다음은 운동 기록을 저장해볼 것이다.
응 안됨.
PK 대신 Str값을 입력받았습니다
그렇다. 이제 알겠다! 특정 테이블의 PK가 다른 테이블에서의 FK가 되는 거구나!
그렇다면 User테이블의 username을 PK로 설정해주면 되겠다.
class User(AbstractUser, PermissionsMixin):
username = models.CharField(uique=True, primary_key=True, max_length=30)
class Meta:
ordering = ['date_joined']
username을 끌고 잡아와서 unique=True, primary_key=True
를 설정해줬다.
DB를 다시 밀고 $ makemigrations
와 $ migrate
를 했다.
당연히 될 줄 알았는데..django.db.utils.OperationalError: (1553, "Cannot drop index 'PRIMARY': needed in a foreign key constraint")
난리가 나버렸다..
/migrations
에 남은 파일들 때문일 수도 있겠단 생각이 든다.
지우고 실행해봤다.
됐다.. 😮
그럼 내부는 어떻게 된 거지?
원래 있어야할 'id'라는 pk가 사라졌다.
PyCharm에서 데이터베이스를 확인해봐도 pk가 없다.
다만 username에 pk를 의미하는 열쇠모양도 보이지 않는다.
일단 다른 테이블의 username
필드가 FK역할을 할 수 있는지 확인해야겠다.
how라는 username으로 등록하고 biceps-list에 이두운동 결과를 등록해봤더니 잘 작동한다.
그렇다면 조회는?
정상적으로 잘 작동한다. 🙆♂️
휴 아주아주 다행이다.
username과 password를 줘서 탈퇴까지 하고 싶었는데 이 기능을 web쪽에만 넣어두고 app엔 구현해두지 않았다.😓
이렇게 pk와 FK를 설정하는 것까진 했지만 실제로 데이터베이스에서 어떤 식으로 사용해야할지는 좀 더 많은 양의 데이터를 다뤄봐야 알 것 같은데, 이건 공공데이터 포털이나 빅데이터 파일 중 쓸 만한 것을 찾아봐야겠다.
permission에 대해 찾아다니다보니 UserManager나 custom-permission을 쓰는 것을 많이 보게 되었다. 꽤 길고 따라해보려면 시간이 좀 더 들 것 같다.
model을 초반에 설계하는 게 정말 중요하단 생각이 든다.
[해설과 함께 읽는 Django 문서] Models - Automatic primary key 필드
기본키, 후보키, 외래키, 복합키 공부하기
[Django] Authentication 과 Permissions
[Mysql, MariaDB] PrimaryKey, Autoincrement 설정방법
model(1:N - 댓글, 글-유저연동) 과 User 커스텀, humanize