[Django] 비 SPA 방식으로 장고 Forms/Views를 적극 활용한 인스타그램 St 만들기#6_instagram 앱 생성과 포스팅 쓰기 구현

아직·2022년 7월 13일
0
post-thumbnail

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>의 목록(여기서는 튜플)이 반환된다.

동등한 클래스지만, 관계를 설정할 때는 인간적인 교통 정리가 필요해 보인다.

0개의 댓글