Django 포스팅 쓰기 구현하기

2022. 2. 14. 14:58강의 정리/Django 기초

반응형

출처 : https://www.inflearn.com/course/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%A5%EA%B3%A0-%EC%9B%B9%EC%84%9C%EB%B9%84%EC%8A%A4/dashboard

 

장고(Django)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!

 


 

포스팅 쓰기 구현하기

사진 1장 : 이미지 필터는 리액트에서

 

caption과 태그 쓰기

 

Location


#shell

python manage.py startapp insta

 

 

#프로젝트/settings/common.py(=settings.py)

INSTALLED_APPS = [
    # Django Apps
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Third Apps
    'debug_toolbar',
    'bootstrap4',
    'django_pydenticon',

    # Local Apps
    'accounts',
    'insta', # 추가
  
]

 

 

#insta/urls.py

from django.urls import path
from . import views

app_name = 'insta'

urlpatterns = [
    path('post/new', views.post_new, name='post_new'),
    ]

 

 

#프로젝트/urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/' , include('accounts.urls')),
    path('', include('insta.urls')), # 추가

    path('', login_required(TemplateView.as_view(template_name='root.html')), name='root' ), # re_path를 사용하면 모든 주소에 매칭이 된다.
    path('identicon/images/<path:data>/', pydenticon_image, name='pydenticon_image'),

]

 

 

#insta/views.py

from django.contrib import messages
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from .forms import PostForm
from django.http import HttpResponseRedirect
from django.shortcuts import redirect

@login_required
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.tag_set # TODO
            post.save()
            messages.success(request, "포스팅을 저장했습니다.")
            return redirect("/")  # TODO: get_absolute_url 모델단에 구현하기
    
    else:
        form = PostForm()

    return  render(request, "insta/post_form.html", {
        "form" : form,
    })

# get_absoulte_url 이란???

https://wayhome25.github.io/django/2017/05/05/django-url-reverse/

 

URL Reverse, 아는 사람은 꼭 쓴다는 get_absolute_url() · 초보몽키의 개발공부로그

특정 모델에 대한 Detail뷰를 작성할 경우, Detail뷰에 대한 URLConf설정을 하자마자, 필히 get_absolute_url설정을 해주세요. 코드가 보다 간결해집니다

wayhome25.github.io

 

 

#insta/models.py

\from django.db import models

# User 외래키로 삼는 법
from django.conf import settings

class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    photo = models.ImageField(upload_to="insta/post/%Y%m%d")
    # 내용
    caption = models.TextField()
    tag_set = models.ManyToManyField('Tag', blank=True)
    location = models.CharField(max_length=100) 

    def __str__(self):
        return self.caption

    
    #def get_absolute_url(self):
     #   return reverse("model_detail", kwargs={"pk": self.pk})
    

class Tag(models.Model):
    name = models.CharField(max_length=50, unique=True)

    def __str__(self):
        return self.name

_ 장고에서는 Tag를 지원해주지만, 공부를 위해 직접 Tag 모델을 만들어보았다.

https://wikidocs.net/9723

 

01) 태그

[TOC] # 패키지 선택 [Django 태그 라이브러리 비교](https://djangopackages.org/grids/g/tagging/) 사이트에서 보면 대표적으로 ...

wikidocs.net

 

 

 

 

#프로젝트/templates/프로젝트/root.html

{% extends "layout.html" %}

{% block content %}
    <div class="container">
        <div class="row">
            <div class="col-sm-12">
                Instagram
                <hr/>
                <a href="{% url 'insta:post_new' %}" class="btn btn-primary">새 포스팅 쓰기</a>             
            </div>
        </div>
    </div>
{% endblock %}

 

 

 

 

#insta/forms.py

from django import forms
from .models import Post


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields =  [
            'photo', 'caption', 'location'
        ]

        # 장고에서는 widgets 를 통해 특정 필드 위젯을 변경할 수 있다.
        widgets = {
            "caption" : forms.Textarea,
        }

https://docs.djangoproject.com/en/4.0/ref/forms/widgets/

 

Widgets | Django documentation | Django

Django The web framework for perfectionists with deadlines. Overview Download Documentation News Community Code Issues About ♥ Donate

docs.djangoproject.com

 

 

 

#insta/templates/insta/layout.html

{% extends "layout.html" %}

 

 

 

#insta/templates/insta/post_form.html

{% extends "insta/layout.html" %}
{% load bootstrap4 %}

{% block content %}
    <div class="container">
        <div class="row">
            <div class="col-sm-6 offset-sm-3">
                {% include "_form.html" with form_title="새 포스팅 쓰기" submit_label="새 포스팅 쓰기"  %}
            </div>
        </div>
    </div>  
{% endblock %}

 

 

 

 

#insta/admin.py

from django.contrib import admin
from .models import Post, Tag

@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
    pass

@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
    pass

 

 

 


 

Tag 기능 구현하기

 

#insta/models.py

import re
from django.db import models

# User 외래키로 삼는 법
from django.conf import settings

class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    photo = models.ImageField(upload_to="insta/post/%Y%m%d")
    # 내용
    caption = models.TextField()
    tag_set = models.ManyToManyField('Tag', blank=True)
    location = models.CharField(max_length=100) 

    # Post 객체가 생성되면 아래 __str__함수가 호출된다.
    def __str__(self):
        return self.caption

    # 태그 기능
    def extract_tag_list(self):
        # "#"이 붙고 뒤에 문자가 오면 태그로 분류 저장한다.
        tag_name_list = re.findall(r"#([a-zA-Z\dㄱ-힣]+)", self.caption)
        
        # tag가 저장될 list
        tag_list = []
        
        # caption(본문)에서 #이 들어간 문자열을 TAG의 name에 저장해준다.
        for tag_name in tag_name_list:
            tag, _ = Tag.objects.get_or_create(name=tag_name)
            tag_list.append(tag)
        return tag_list


    #def get_absolute_url(self):
     #   return reverse("model_detail", kwargs={"pk": self.pk})
    

class Tag(models.Model):
    name = models.CharField(max_length=50, unique=True)

    def __str__(self):
        return self.name

 

 

#insta/views.py

from django.contrib import messages
from django.shortcuts import render
from django.contrib.auth.decorators import login_required

from .forms import PostForm
from .models import Tag

from django.http import HttpResponseRedirect
from django.shortcuts import redirect


@login_required
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
            # manytomany는 실제 pk 값이 있어야하기에 form이 저장된 상태로 해야한다.
            post.save()
            # post의 tag_list를 호출하여 Post 모델의 tag_set에 저장한다.
            post.tag_set.add(*post.extract_tag_list())

            messages.success(request, "포스팅을 저장했습니다.")
            return redirect("/")  # TODO: get_absolute_url 모델단에 구현하기
    
    else:
        form = PostForm()

    return  render(request, "insta/post_form.html", {
        "form" : form,
    })

 

 

 

반응형