SSAFY/Django

[Django] 좋아요, follow, hashtag 간단 코딩

황성안 2021. 4. 1. 08:42
728x90

0401

순서

  1. like
  2. like with through
  3. follow
  4. hashtag
  5. gravatar
  6. git branching..

fontAwesome(https://fontawesome.com/)

 

이쁜 폰트 써보기

 

 

1.like

좋아요 추가하기

article > models.py

    like_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL, #M:N with User Model
        related_name='like_articles', # For User Model
        )

마이그레이션, 마이그레이트

 

폰트어썸 > 마이페이지 > kit > (내코드 복사)

templates > base.html(헤드쪽에 넣어주기)

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://kit.fontawesome.com/80da99576a.js" crossorigin="anonymous"></script>
  {% bootstrap_css %}
  <title>Document</title>
</head>

 

폰트어썸에들어가서 마음에드는아이콘 선택후 빨강 동그라미 복사

image-20210401092527224

 

articles >

detail.html

  <h2>DETAIL</h2>
  <h3>{{ article.pk }} 번째 글</h3>
  <hr>
  <p>제목 : {{ article.title }}</p>
  <p>내용 : {{ article.content }}</p>
  <p>작성시각 : {{ article.created_at|naturalday }}</p>
  <p>수정시각 : {{ article.updated_at|naturaltime }}</p>
  <hr>
  <form action="{% url 'articles:like' article.pk %}" method="POST">
    {% csrf_token %}
    <button>
      <i class="far fa-heart"></i>
    </button>
  </form>
  <hr>

urls.py

#like
    path('<int:pk>/like/', views.like, name='like'),

views.py

좋아요와 관련하여 직접 확인해보기

def like(request, pk):
    # 1. 좋아요 누른 게시글 가져오기
    article = get_object_or_404(Article, pk=pk)

    # 2. 게시글 좋아요 누른 유저 목록에
    # 내가 없다면 추가하기
    print(article.like_users)
    print(type(article.like_users))
    print(article.like_users.all())
    print( help(article.like_users) )
    # 3. 게시글 좋아요 누른 유저 목록에
    # 재가 있다면 제거하기
    return redirect('articles:detail', article.pk)

https://docs.djangoproject.com/en/3.1/ref/models/relations/

related_name 과 관련된 것입니다.

 

print( help(article.like_users) )

이친구를 한번 보겠습니다.

어디서 뭘상속받았는지 전부 알려주는 친구!

class ManyRelatedManager(django.contrib.auth.models.UserManager)
 |  ManyRelatedManager(*args, **kwargs)
 |
 |  Method resolution order:
 |      ManyRelatedManager
 |      django.contrib.auth.models.UserManager
 |      django.contrib.auth.base_user.BaseUserManager
 |      django.db.models.manager.Manager
 |      django.db.models.manager.BaseManagerFromQuerySet
 |      django.db.models.manager.BaseManager
 |      builtins.object
 |# 메소드 안만큼 상속을 받았다는 것
 |  Methods defined here:
 |
 |  __call__(self, *, manager)
 |
 |  __init__(self, instance=None)
 |
 |  add(self, *objs, through_defaults=None)
 |
 |  clear(self)
 |
 |  create(self, *, through_defaults=None, **kwargs)
 |
 |  get_or_create(self, *, through_defaults=None, **kwargs)

#메소드 밑에서부터는 상속받은 클래스들을 보여줍니다.

 

 

여튼 뷰로 넘어가서..

 

image-20210401094514609

def like(request, pk):
    # 1. 좋아요 누른 게시글 가져오기
    article = get_object_or_404(Article, pk=pk)

    # 2. 게시글 좋아요 누른 유저 목록에
    # 내가 없다면 추가하기
    if article.like_users.filter(pk=request.user.pk).exists():
        article.like_users.remove(request.user)
    # 3. 게시글 좋아요 누른 유저 목록에
    # 내가 있다면 제거하기
    else:
        article.like_users.add(request.user)

    return redirect('articles:detail', article.pk)

 

DB확인하기

 

좋아요 몇명이 좋아하는지

detail.html

  <p>{{ article.like_users.count}} 명이 좋아합니다.</p>

좋아요 이름. 시간 표시하기

templates. detail html

  <div>
    {% for like in article.like_set.all %}
      <p>유저 : {{ like.user }} | 좋아요 누른 날짜 : {{ like.created_at|naturaltime }} </p>
    {% endfor %}
  </div>

 

좋아요 기능 중개테이블

class Like(models.Model):
    '''
    좋아요 기능을 위한 article과 유저 사이의 중개테이블
    '''


    article = models.ForeignKey('Article', on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    created_at = models.DataTimeField(auto_now_add=True)# 언제 좋아요 눌렀는지

중개테이블만 만들면안된다

like_users 로가서 through 로가자.

 

from django.db import models
from django.conf import settings

# Create your models here.
class Article(models.Model):
    title = models.CharField(max_length=10)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    like_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='like_articles',
        through='Like',
        )


    def __str__(self):
        return self.title


class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    content = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.content


class Like(models.Model):
    '''
    좋아요 기능을 위한 article과 유저 사이의 중개테이블
    '''
    article = models.ForeignKey('Article', on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

article그리고 마이그레이션 폴더로간다 04,05 를 지운다

그리고 다시 migrations와 migrate를 하면 성공!

그것을 안하면

image-20210401103456340

이런 오류가 발생하니 주의

 

프로필 추가하기

메인에서 사용자를 눌렀을떄 프로필 페이지로가기

index.html

{% extends 'base.html' %}

{% block content %}
  <h1>Articles</h1>
  {% if request.user.is_authenticated %}
    <a href="{% url 'articles:create' %}">[CREATE]</a>
  {% else %}
    <a href="{% url 'accounts:login' %}">[새 글을 작성하려면 로그인하세요.]</a>
  {% endif %}
  <hr>
  {% for article in articles %}
    <p>
      <b>
        <a href="{% url 'accounts:profile' article.user.username %}">
          작성자 : {{ article.user }}
        </a>
      </b>
    </p>
    <p>글 번호 : {{ article.pk }}</p>
    <p>글 제목 : {{ article.title }}</p>
    <p>글 내용 : {{ article.content }}</p>
    <a href="{% url 'articles:detail' article.pk %}">[DETAIL]</a>
    <hr>
  {% endfor %}
{% endblock %}

accounts > urls.py

from django.urls import path
from . import views


app_name = 'accounts'
urlpatterns = [
    path('login/', views.login, name='login'),
    path('logout/', views.logout, name='logout'),
    path('signup/', views.signup, name='signup'),
    path('delete/', views.delete, name='delete'),
    path('update/', views.update, name='update'),
    path('password/', views.change_password, name='change_password'),

    #profile
    path('<str:username>/', views.profile, name='profile'),
]

accounts > views.py

from django.shortcuts import render, redirect
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
# from django.contrib.auth import login as auth_login, logout as auth_logout
from django.views.decorators.http import require_POST, require_http_methods
from django.contrib.auth.decorators import login_required
from django.contrib.auth import update_session_auth_hash
from django.contrib.auth.forms import (
    AuthenticationForm, 
    UserCreationForm, 
    PasswordChangeForm,
)
from .forms import CustomUserChangeForm, CustomUserCreationForm


# Create your views here.
@require_http_methods(['GET', 'POST'])
def login(request):
    if request.user.is_authenticated:
        return redirect('articles:index')

    if request.method == 'POST':
        form = AuthenticationForm(request, request.POST)
        # form = AuthenticationForm(request, data=request.POST)
        if form.is_valid():
            auth_login(request, form.get_user())
            return redirect(request.GET.get('next') or 'articles:index')
    else:
        form = AuthenticationForm()
    context = {
        'form': form,
    }
    return render(request, 'accounts/login.html', context)


@require_POST
def logout(request):
    if request.user.is_authenticated:
        auth_logout(request)
    return redirect('articles:index')


@require_http_methods(['GET', 'POST'])
def signup(request):
    if request.user.is_authenticated:
        return redirect('articles:index')

    if request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            auth_login(request, user)
            return redirect('articles:index')
    else:
        form = CustomUserCreationForm()
    context = {
        'form': form,
    }
    return render(request, 'accounts/signup.html', context)


@require_POST
def delete(request):
    if request.user.is_authenticated:
        request.user.delete()
        auth_logout(request)
    return redirect('articles:index')


@login_required
@require_http_methods(['GET', 'POST'])
def update(request):
    if request.method == 'POST':
        form = CustomUserChangeForm(request.POST, instance=request.user)
        if form.is_valid():
            form.save()
            return redirect('articles:index')
    else:
        form = CustomUserChangeForm(instance=request.user)
    context = {
        'form': form,
    }
    return render(request, 'accounts/update.html', context)


@login_required
@require_http_methods(['GET', 'POST'])
def change_password(request):
    if request.method == 'POST':
        form = PasswordChangeForm(request.user, request.POST)
        # form = PasswordChangeForm(user=request.user, data=request.POST)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.user)
            return redirect('articles:index')
    else:
        form = PasswordChangeForm(request.user)
    context = {
        'form': form,
    }
    return render(request, 'accounts/change_password.html', context)


def profile(request, username):
    # 1. 현재 요청을 보낸 유저가 보고자하는 유저를 가져오기

    from django.contrib.auth import get_user_model
    User = get_user_model()
    profile_user = User.objects.get(username=username)
    context = {
        'profile_user':profile_user,
    }
    return render(request, 'accounts/profile.html', context)

accounts > profile.html

{% extends 'base.html' %}

{% block content %}
    <h1>{{ profile_user }}님의 프로필 페이지</h1>
    {% comment %} 팔로우 버튼 {% endcomment %}
    <form action="" method="POST">
    {% csrf_token %}
    <button>Follow</button>
    </form>

    {% comment %} 팔로워 목록 {% endcomment %}


    {% comment %} 팔로잉 목록 {% endcomment %}



{% endblock  %}

 

3. 팔로우 만들기

accounts > models.py

from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser

# Create your models here.
class User(AbstractUser):
    followings = models.ManyToManyField('self', related_name='followers',)

forms.py

from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from django.contrib.auth import get_user_model


class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = get_user_model()
        fields = ('username', 'email', 'first_name', 'last_name',)


class CustomUserCreationForm(UserCreationForm):

    class Meta(UserCreationForm.Meta):
        model = get_user_model()
        fields = UserCreationForm.Meta.fields

철수 > 영희

철수.follwings.all() => [영희, ]

영희.follwings.all() => []

 

철수.followers.all() =>[영희, ]

영희.followers.all()=>[]

하지만 위에 옵션에서 symmetrical=False 를써줘야지 대칭 수락이안됨 저게없으면

한명이 팔로우를 하게되면 자동으로 팔로워 를 서로 하게된다.

 

accounts > profile.html

{% extends 'base.html' %}

{% block content %}
    <a href="{% url 'articles:index' %}">홈으로가기</a>
    <h1>{{ profile_user }}님의 프로필 페이지</h1>
    {% comment %} 팔로우 버튼 {% endcomment %}
    <form action="{% url 'accounts:follow' profile_user.pk %}" method="POST">
    {% csrf_token %}
    {% if request.user in profile_user.followers.all %}
        <button class="btn btn-danger">UnFollow</button>
    {% else %}
        <button class="btn btn-primary">Follow</button>
    {% endif %}
    </form>
    {% comment %} 팔로워 목록 {% endcomment %}
    <div>
        <p>
         팔로워 목록 : 
            {% for follower in profile_user.followers.all %}
                {{ follower }}
            {% endfor %}
        </p>
    </div>

    {% comment %} 팔로잉 목록 {% endcomment %}
    <div>
        <p>
            팔로잉 목록 :
            {% for following in profile_user.followers.all %}
                {{ following }}
            {% endfor %}
        </p>
    </div>


{% endblock  %}

urls.py

def follow(request, pk):
    # User = get_user_model()
    # #팔로우
    # user = get_object_or_404(User, pk=pk)
    # if user != request.user:
    #     #팔로워 ==> request.user
    #     #만약에 팔로워라면?
    #     if user.follow.filter(pk=request.user.pk).exists():
    #         user.follow.remove(request.user) #삭제하기
    #     else:
    #         user.follow.add(request.user)
    # return redirect('accounts:profile', user.username)
    User = get_user_model() # User 모델 == 클래스
    you = get_object_or_404(User, pk=pk)
    me = request.user

    if you.followers.filter(pk=me.pk).exists():
        you.followers.remove(me)
    else:
        you.followers.add(me)
    return redirect('accounts:profile', you.username)

 

 

4. hashtag

articles. models.py

from django.db import models
from django.conf import settings

# Create your models here.
class Hashtag(models.Model):
    content = models.TextField(unique=True)


class Article(models.Model):
    hashtags = models.ManyToManyField( 'Hashtag', related_name='articles', blank=True,    ) #blank=true 는 유효성 검사에서 제외하겠다.
    title = models.CharField(max_length=10)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    like_users = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='like_articles',
        through='Like',
        )


    def __str__(self):
        return self.title


class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    content = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.content


class Like(models.Model):
    '''
    좋아요 기능을 위한 article과 유저 사이의 중개테이블
    '''
    article = models.ForeignKey('Article', on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True) 

.# 이하 hastag 를 해주려면 파싱을 해줘야한다.

articles. views.py

from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_safe, require_http_methods, require_POST
from django.http import HttpResponse, HttpResponseForbidden
from .models import Article, Comment, Hashtag
from .forms import ArticleForm, CommentForm

# Create your views here.
@require_safe
def index(request):
    articles = Article.objects.order_by('-pk')
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index.html', context)


@login_required
@require_http_methods(['GET', 'POST'])
def create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save(commit=False)
            article.user = request.user
            article.save()
            #hashtag
            for word in article.content.split():
                # word : ex) 오늘 # 장고 # 많이 #힘들다
                if word.startswith('#'):
                    # 해쉬태그 테이블에 우선 새로운 데이터를 생성하고
                    hashtag = Hashtag.objects.create(content=word)
                    # 방금 생성된 해쉬태그와 현재 게시글을 관계 지어준다.
                    # (article 과 hashtag의 중개 테이블에 관계르 생성하는 부분)
                    article.hashtags.add(hashtag)
            return redirect('articles:detail', article.pk)
    else:
        form = ArticleForm()
    context = {
        'form': form,
    }
    return render(request, 'articles/create.html', context)


@require_safe
def detail(request, pk):
    article = get_object_or_404(Article, pk=pk)
    comment_form = CommentForm()
    comments = article.comment_set.all()
    context = {
        'article': article,
        'comment_form': comment_form,
        'comments': comments,
    }
    return render(request, 'articles/detail.html', context)


@require_POST
def delete(request, pk):
    article = get_object_or_404(Article, pk=pk)
    if request.user.is_authenticated:
        if request.user == article.user:
            article.delete()
            return redirect('articles:index')
    return redirect('articles:detail', article.pk)


@login_required
@require_http_methods(['GET', 'POST'])
def update(request, pk):
    article = get_object_or_404(Article, pk=pk)
    if request.user == article.user:
        if request.method == 'POST':
            form = ArticleForm(request.POST, instance=article)
            if form.is_valid():
                form.save()
                return redirect('articles:detail', article.pk)
        else:
            form = ArticleForm(instance=article)
    else:
        return redirect('articles:index')
        # return HttpResponseForbidden()
    context = {
        'form': form,
        'article': article,
    }
    return render(request, 'articles/update.html', context)
        

@require_POST
def comments_create(request, pk):
    if request.user.is_authenticated:
        article = get_object_or_404(Article, pk=pk)
        comment_form = CommentForm(request.POST)
        if comment_form.is_valid():
            comment = comment_form.save(commit=False)
            comment.article = article
            comment.user = request.user
            comment.save()
            return redirect('articles:detail', article.pk)
        context = {
            'comment_form': comment_form,
            'article': article,
        }
        return render(request, 'articles/detail.html', context)
    return redirect('accounts:login')
    # return HttpResponse(status=401)


@require_POST
def comments_delete(request, article_pk, comment_pk):
    if request.user.is_authenticated:
        comment = get_object_or_404(Comment, pk=comment_pk)
        if request.user == comment.user:
            comment.delete()
        # return HttpResponseForbidden()
    return redirect('articles:detail', article_pk)
    # return HttpResponse(status=401)

def like(request, pk):
    # 1. 좋아요 누른 게시글 가져오기
    article = get_object_or_404(Article, pk=pk)

    # 2. 게시글 좋아요 누른 유저 목록에
    # 내가 없다면 추가하기
    if article.like_users.filter(pk=request.user.pk).exists():
        article.like_users.remove(request.user)
    # 3. 게시글 좋아요 누른 유저 목록에
    # 내가 있다면 제거하기
    else:
        article.like_users.add(request.user)

    return redirect('articles:detail', article.pk)

create 세이브 함수 밑에서 넣는다.

image-20210401150458111

중복으로 해시테그가 사용이안된다.

우리는 get_or_create()를 사용해볼것이다.

https://docs.djangoproject.com/en/3.1/ref/models/querysets/#get-or-create

 

https://docs.djangoproject.com/en/3.1/howto/custom-template-tags/

를 보자

image-20210401153105236

articles 에 폴더를 하나만든다.

image-20210401153249501

hashtag_link.pk

from django import template

register = template.Library()

@register.filter
def hashtag_check(article):
    '''
    article의 content를 파싱해서 #으로 시작하는 단어들을 
    a태그로 감싸줍니다. 
    ex) {{ article|hashtag_check }}
    '''
    content = article.content
    hashtags = article.hashtags.all() # #디장고 #오늘

    for hashtag in hashtags:
        # #디장고 => <a href="">#디장고 </a>
        content = content.replace(
            hashtag.content,
            f'<a href="#">{hashtag.content}</a>'
        )

    return content

detail.html

{% load hashtag_link %}

  <p>내용 : {{ article|hashtag_check }}</p>
{% extends 'base.html' %}
{% load humanize %}
{% load hashtag_link %}

{% block content %}
  <h2>DETAIL</h2>
  <h3>{{ article.pk }} 번째 글</h3>
  <hr>
  <p>제목 : {{ article.title }}</p>
  <p>내용 : {{ article|hashtag_check }}</p>
  <p>작성시각 : {{ article.created_at|naturalday }}</p>
  <p>수정시각 : {{ article.updated_at|naturaltime }}</p>
  <hr>
  <form action="{% url 'articles:like' article.pk %}" method="POST">
    {% csrf_token %}
    <button class="btn btn-white">
    {% if request.user not in article.like_users.all %}
      <i class="far fa-heart"></i>
    {% else %}
      <i class="fas fa-heart" style="color: red;"></i>
    {% endif %}
    </button>
  </form>
  <p>{{ article.like_users.count}} 명이 좋아합니다.</p>
  <div>
    {% for like in article.like_set.all %}
      <p>유저 : {{ like.user }} | 좋아요 누른 날짜 : {{ like.created_at|naturaltime }} </p>
    {% endfor %}
  </div>
  <hr>
  {% if request.user == article.user %}
    <a href="{% url 'articles:update' article.pk %}" class="btn btn-primary">[UPDATE]</a>
    <form action="{% url 'articles:delete' article.pk %}" method="POST">
      {% csrf_token %}
      <button class="btn btn-danger">DELETE</button>
    </form>
  {% endif %}
  <a href="{% url 'articles:index' %}">[back]</a>
  <hr>
  <h4>댓글 목록</h4>
  <p>{{ comments|length }}개의 댓글이 있습니다.</p>
  <ul>
    {% for comment in comments %}
      <li>
        {{ comment.user }} - {{ comment.content }}
        {% if request.user == comment.user %}
          <form action="{% url 'articles:comments_delete' article.pk comment.pk %}" method="POST" class="d-inline">
            {% csrf_token %}
            <input type="submit" value="DELETE">
          </form>
        {% endif %}
      </li>
    {% empty %}
      <p>아직 댓글이 없네요...</p>
    {% endfor %}
  </ul>
  <hr>
  {% if request.user.is_authenticated %}
    <form action="{% url 'articles:comments_create' article.pk %}" method="POST">
      {% csrf_token %}
      {{ comment_form }}
      <input type="submit">
    </form>
  {% else %}
    <a href="{% url 'accounts:login' %}">[댓글을 작성하려면 로그인 하세요.]</a>
  {% endif %}
{% endblock %}
  

이렇게하면 게시판에

a태그가 붙습니다

image-20210401155233907

다만 장고의 보안때문에 html의 약간의 추가가 필요ㅕ합니다.(safe)

  <p>내용 : {{ article|hashtag_check|safe }}</p>

그러고 나면

image-20210401155455743

잘됩니다만 해쉬테그가 잘안되는 것은 알고리즘 수정이필요합니다

ex) create 부분의 해쉬태그 알고리즘부분 수정필요

 

 

해쉬태그를 클리갛면 게시물 전부불러오기

articles. urls.py

from django.urls import path
from . import views


app_name = 'articles'
urlpatterns = [
    path('', views.index, name='index'),
    path('create/', views.create, name='create'),
    path('<int:pk>/', views.detail, name='detail'),
    path('<int:pk>/delete/', views.delete, name='delete'),
    path('<int:pk>/update/', views.update, name='update'),
    path('<int:pk>/comments/', views.comments_create, name='comments_create'),
    path('<int:article_pk>/comments/<int:comment_pk>/delete/', views.comments_delete, name='comments_delete'),
    
    #like
    path('<int:pk>/like/', views.like, name='like'),

    #hashtag
    path('<int:hash_pk>/hashtag/', views.hashtag, name="hashtag"),
]

 

views.py

from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_safe, require_http_methods, require_POST
from django.http import HttpResponse, HttpResponseForbidden
from .models import Article, Comment, Hashtag
from .forms import ArticleForm, CommentForm

# Create your views here.
@require_safe
def index(request):
    articles = Article.objects.order_by('-pk')
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index.html', context)


@login_required
@require_http_methods(['GET', 'POST'])
def create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save(commit=False)
            article.user = request.user
            article.save()
            #hashtag
            for word in article.content.split():
                # word : ex) 오늘 # 장고 # 많이 #힘들다
                if word.startswith('#'):
                    # 해쉬태그 테이블에 우선 새로운 데이터를 생성하고
                    hashtag, created = Hashtag.objects.get_or_create(content=word)
                    # 방금 생성된 해쉬태그와 현재 게시글을 관계 지어준다.
                    # (article 과 hashtag의 중개 테이블에 관계르 생성하는 부분)
                    article.hashtags.add(hashtag)
            return redirect('articles:detail', article.pk)
    else:
        form = ArticleForm()
    context = {
        'form': form,
    }
    return render(request, 'articles/create.html', context)


@require_safe
def detail(request, pk):
    article = get_object_or_404(Article, pk=pk)
    comment_form = CommentForm()
    comments = article.comment_set.all()
    context = {
        'article': article,
        'comment_form': comment_form,
        'comments': comments,
    }
    return render(request, 'articles/detail.html', context)


@require_POST
def delete(request, pk):
    article = get_object_or_404(Article, pk=pk)
    if request.user.is_authenticated:
        if request.user == article.user:
            article.delete()
            return redirect('articles:index')
    return redirect('articles:detail', article.pk)


@login_required
@require_http_methods(['GET', 'POST'])
def update(request, pk):
    article = get_object_or_404(Article, pk=pk)
    if request.user == article.user:
        if request.method == 'POST':
            form = ArticleForm(request.POST, instance=article)
            if form.is_valid():
                article = form.save()
                #hashtag
                # update 에서는 hashtag 관꼐를 초기화 해줘야함
                # 기존의 해쉬태그도 수정
                article.hashtags.clear()
                for word in article.content.split():
                # word : ex) 오늘 # 장고 # 많이 #힘들다
                    if word.startswith('#'):
                        # 해쉬태그 테이블에 우선 새로운 데이터를 생성하고
                        hashtag, created = Hashtag.objects.get_or_create(content=word)
                        # 방금 생성된 해쉬태그와 현재 게시글을 관계 지어준다.
                        # (article 과 hashtag의 중개 테이블에 관계르 생성하는 부분)
                        article.hashtags.add(hashtag)
                return redirect('articles:detail', article.pk)
        else:
            form = ArticleForm(instance=article)
    else:
        return redirect('articles:index')
        # return HttpResponseForbidden()
    context = {
        'form': form,
        'article': article,
    }
    return render(request, 'articles/update.html', context)
        

@require_POST
def comments_create(request, pk):
    if request.user.is_authenticated:
        article = get_object_or_404(Article, pk=pk)
        comment_form = CommentForm(request.POST)
        if comment_form.is_valid():
            comment = comment_form.save(commit=False)
            comment.article = article
            comment.user = request.user
            comment.save()
            return redirect('articles:detail', article.pk)
        context = {
            'comment_form': comment_form,
            'article': article,
        }
        return render(request, 'articles/detail.html', context)
    return redirect('accounts:login')
    # return HttpResponse(status=401)


@require_POST
def comments_delete(request, article_pk, comment_pk):
    if request.user.is_authenticated:
        comment = get_object_or_404(Comment, pk=comment_pk)
        if request.user == comment.user:
            comment.delete()
        # return HttpResponseForbidden()
    return redirect('articles:detail', article_pk)
    # return HttpResponse(status=401)

def like(request, pk):
    # 1. 좋아요 누른 게시글 가져오기
    article = get_object_or_404(Article, pk=pk)

    # 2. 게시글 좋아요 누른 유저 목록에
    # 내가 없다면 추가하기
    if article.like_users.filter(pk=request.user.pk).exists():
        article.like_users.remove(request.user)
    # 3. 게시글 좋아요 누른 유저 목록에
    # 내가 있다면 제거하기
    else:
        article.like_users.add(request.user)

    return redirect('articles:detail', article.pk)


def hashtag(request, hash_pk):
    tag = get_object_or_404(Hashtag, pk=hash_pk)

    context = {
        'tag':tag,
    }
    return render(request, 'articles/hashtag.html', context)

hashtag.html

related_name 을 articles 로 설정했다. for 문에

{% extends 'base.html' %}

{% block content %}
    <h1>{{ tag.content }}</h1>
    <hr>

    <div>
        {% for article in tag.articles.all %}
            제목 : {{ article.title }}
        {% endfor %}
    </div>

{% endblock  %}

hashtag_link.py

from django import template

register = template.Library()

@register.filter
def hashtag_check(article):
    '''
    article의 content를 파싱해서 #으로 시작하는 단어들을 
    a태그로 감싸줍니다. 
    ex) {{ article|hashtag_check }}
    '''
    content = article.content
    hashtags = article.hashtags.all() # #디장고 #오늘

    for hashtag in hashtags:
        # #디장고 => <a href="">#디장고 </a>
        content = content.replace(
            hashtag.content,
            f'<a href="/articles/{hashtag.pk}/hashtag/">{hashtag.content}</a>'
        )

    return content

 

 

5. branching

가장 최신 commit 을 불러온다? 준다?

협업할떄 쓰는 것입니둥두둥

협업하기 폴더 안에서

django-admin startproject config .
gitstatus
git add.
git commit -m "install"

팀원

git checkout -b 'hwangsoengahn' 
#브랜치를 만들어서 그 공간으로 이동하는것
git add.
git log
python manage.py startapp soengahn
# 성안 파이썬 폴더만들기
git commit -m "add soengahn"
git push origin 이름
merge request

푸시만했다고 병합된건 아니다

왼쪽에 merge request를보거나 우측 상단에 create reques

병합 요청을한다(프로젝트팀장)

image-20210401165754254

 

 

image-20210401165918498

이건 충돌되있다는 뜻

이중에 괜찮은 아이디어가있다면 merge 를 팀장이 클릭해서 머지해준다.

그리고 항상 gitignore 신경써주자.

 

프로젝트 끝났으면 지우자

git checkout master
git branch -D hwangseongahn

 

git checkout -b 'HSA/'

만약 모르고 마스터로 푸시해버리면?

 

728x90

'SSAFY > Django' 카테고리의 다른 글

[Django] swagger  (0) 2021.04.27
[Django] REST - API ( 맛보기 )  (0) 2021.04.26
[Django] 로그인한 사용자 판별하기  (0) 2021.03.27
[Django] 댓글 삭제  (0) 2021.03.26
[Django] SQL 과 장고 ORM 사용 방법  (0) 2021.03.26