1)
path('', include('instagram.urls'))
instagra의 urls.py에 있는 각각의 path들이 prefix없이 작동할 수 있도록
2)
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
외래키에서는 모델의 참조가 되는 클래스와 on_delete 옵션을 지정해줘야 한다.
3)
CommandError: Conflicting migrations detected; multiple leaf nodes in the migration graph: (0003_user_avatar, 0003_user_profile in accounts).
To fix them run 'python manage.py makemigrations --merge'
instagram 앱에서 모델을 만들고 makemigations까지 실행했으나 migrate에서 오류가 났다. accounts 앱에 적용된 0003 파일과 적용 안된 0003 파일이 있었는데, 적용 안된 0003을 지우고 정상적으로 실행됐다.
4)
<a href="{% url "instagram:post_new %}" class="btn btn-primary"> 새 포스팅 쓰기 </a>
urls.py에서 app_name을 지정해줬고 path name도 붙여줄 수 있다. "새 포스팅 쓰기"를 클릭 시 urls.py에 지정돼 있는 /post/new로 넘어간다.
5)
def post_new(request):
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
request는 valid하더라도 필수 항목인 author가 채워지지 않고 commit=True로 넘어갈 경우 IntegrityError가 발생할 것이므로 post.author를 저장하고 post.save()를 진행한다.
6)
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
pass
@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
포스팅을 저장한 다음, 각 모델의 인스턴스가 저장되는 영역을 admin 페이지에 만들고 확인할 수 있다.
7)
def extract_tag_list(self):
tag_name_list = re.findall(r"#([a-zA-Z\dㄱ-힣]+)", self.caption)
tag_list = []
for tag_name in tag_name_list:
tag, _ = Tag.objects.get_or_create(name=tag_name)
tag_list.append(tag)
return tag_list
+
def post_new(request):
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
post.tag_set.add(post.extracgt_tag_list())
#뒤에 영문, 숫자, 한글의 조합으로 이뤄진 부분만을 가져와서 tag_name_list로 반환한다.
이 리스트 순회하면서 Tag에 속한 객체들과 비교해서 없으면 만들고 있으면 가져오는 작업(getor_create)을 실행한다. 객체와 불리언 값으로 이뤄진 튜플을 반환하는 함수라고 하는데 불리언 값을 생략()함으로써 강사님이 목록을 반환한다고 하신 것 같다.
포스트에 있는 태그들을 솎아내고(tag_name_list) Tag.ojbects라는 Tag 풀과 비교해서 더 큰 tag_list를 만들어내는 작업으로 이해된다.
이를 tag_set에 깔끔하게 옮겨 담는다. 리스트를 풀어 넣을 때 가 붙음에 주의하자. manytomany 관계는 post와 tag간의 관계를 별도의 mapping table에 기록해야 하므로 pk가 반드시 필요하다. 를 붙이지 않으면 id 값 때문에 오류가 발생한다.
이 작업은 post가 db에 저장돼야 하므로 post.save()가 post.tag_set- 에 선행한다.
8)
"class Chapter(models.Model):
title = models.CharField(max_length=255, unique=True)
class Book(models.Model):
title = models.CharField(max_length=256)
chapters = models.ManyToManyField(Chapter)
>>> book = Book.objects.create(title="Ulysses")
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, True)
>>> book.chapters.get_or_create(title="Telemachus")
(<Chapter: Telemachus>, False)
>>> Chapter.objects.create(title="Chapter 1")
<Chapter: Chapter 1>
>>> book.chapters.get_or_create(title="Chapter 1")
# Raises IntegrityError"
실습처럼 Tag.objects로 접근해도 <Tag: X>의 목록이 생기고 예제처럼 Chapter와 manytomany 관계에 있는 Book을 이용해서 Book.objects.create(title="Ulysses").chapters로 접근해도 <Chapter: Y>의 목록(여기서는 튜플)이 반환된다.
동등한 클래스지만, 관계를 설정할 때는 인간적인 교통 정리가 필요해 보인다.