본문 바로가기

Python/Django

[Django] django model과 User 연결시키기 / 해당 model을 인스턴스화한 user만 model을 delete할 수 있게 하기

참고

Referencing the User model

실습 저장소

https://github.com/JisunParkRea/djangotube_tutorial

 

JisunParkRea/djangotube_tutorial

Simple video service which can upload youtube videos using django - JisunParkRea/djangotube_tutorial

github.com


구현하고자 하는 기능

  • 해당 video를 만든 사용자만 그 비디오를 삭제할 수 있게 하기
  • video_detail 페이지로 들어가면 해당 video를 만든 사용자에게만 delete 버튼이 보여지게 하기

models.py

Video model에 author field를 추가하여, 자동적으로 user을 참조하게 하자

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

class Video(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    video_key = models.CharField(max_length=12)

models를 변경하였으므로, (migrations/ 이하도 삭제했음)

> python manage.py makemigrations video
> python manage.py migrate

* no column exists 오류!

오류 해결법:

[Django+PostgreSQL] Django model 변경 후 기존 DB table 변경하기 / 오류: video_video.author_id 칼럼 없음

views.py

author field는 video form에 의해 자동적으로 저장되는 것이 아니기 때문에,

video가 DB에 저장되기 전

author field를 user로 채워 넣어야 한다.

@login_required
def video_new(request):
    if request.method == 'POST': # 새로운 비디오 데이터를 업로드할 때
        form = VideoForm(request.POST)
        if form.is_valid():
            video = form.save(commit=False) # 받은 데이터를 바로 Video모델에 저장하지 말기
            video.author = request.user # author 추가
            video.save() # 변경사항 저장
        return redirect('video_list')
    elif request.method == 'GET': # 새로운 비디오를 추가할 템플릿을 가져와야할 때
        return render(request, 'video/video_new.html')

video_delete 메소드에 login_required decorator을 추가하자

from django.contrib.auth.decorators import login_required

@login_required
def video_delete(request, pk):
    video = get_object_or_404(Video, pk=pk)
    video.delete()
    return redirect('video_list')

templates/video/video_detail.html

{% if video.author == user %} ~~~ {% endif %} 사용!

<html>

<head>
    <title>Video Detail</title>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
</head>

<body>
    <script>
        function loading_st() {
            var ct_left = (parseInt(window.screen.width) - 450) / 2;
            var ct_top = (parseInt(window.screen.height)) / 3;
            layer_str = "<div id='loading_layer' style='position:absolute; background-color:; font-size:15px; left:" + ct_left + "px; top:" + ct_top + "px; width:400px; height:; padding:50px; text-align:center; vertical-align:middle; z-index:1000; font-weight: bold;'>로딩중입니다.</div>"
            document.write(layer_str);
        }
        function loading_ed() {
            var ta = document.getElementById('loading_layer');
            ta.style.display = 'none';
        }
        loading_st();
        window.onload = loading_ed;
    </script>
    <div class="content container">
        <header class="page-header">
            <h1 style="display: inline;">Video Detail</h1>
            {% if video.author == user %}
                <a class="btn btn-default" href="{% url 'video_delete' pk=video.pk %}" style="float: right;">Delete Video</a>
            {% endif %}
        </header>
        <div class="row">
            <div class="col-md-16">
                <div id="player"></div>
            </div>
        </div>
    </div>
</body>

<script>
    var tag = document.createElement('script');

    tag.src = "https://www.youtube.com/iframe_api";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

    var player;
    function onYouTubeIframeAPIReady() {
        player = new YT.Player('player', {
            videoId: '{{ video.video_key }}'
        });
    }
</script>

</html>

끝!