Sunday, 14 April 2019

django 27 update/delete user restriction

author is listed at footer of every post 

if logged in as bob, can't edit/delete chuanshuo's post. Only the author can edit/delete his own post

edit own post no problem

#music/views

from django.views import generic
from .models import Album, Song
from django.views.generic.edit import  CreateView, UpdateView, DeleteView, View
from django.urls import reverse_lazy
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from .forms import RegistrationForm, LoginForm
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib import messages

class IndexView(generic.ListView):
    template_name = 'music/index.html'

    def get_queryset(self):
        return  Album.objects.all()

class DetailView(generic.DetailView):
    model = Album
    template_name = 'music/detail.html'

#protected route, require authentication
class AlbumCreate(LoginRequiredMixin, CreateView):
    model = Album
    fields = ['artist', 'album_title', 'genre', 'album_logo']

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

class AlbumUpdate(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = Album
    fields = ['artist', 'album_title', 'genre', 'album_logo']

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def test_func(self):
        album = self.get_object()
        if self.request.user == album.author:
            return True
        return False

class AlbumDelete(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = Album
    #redirect to home page after delete
    success_url = reverse_lazy('music:index')

    def test_func(self):
        album = self.get_object()
        if self.request.user == album.author:
            return True
        return False

#protected route, require authentication
class SongCreate(LoginRequiredMixin, CreateView):
    model = Song
    fields = ['file_type', 'song_title', 'is_favorite']

    #overwrite field['album']
    def form_valid(self, form):
        form.instance.album = Album.objects.get(pk=self.kwargs['album_pk'])
        return super().form_valid(form)

    #pass variable song_album to song_form template
    def get_context_data(self, **kwargs):
        context = super(SongCreate, self).get_context_data(**kwargs)

        song_album = Album.objects.get(pk=self.kwargs['album_pk']).album_title

        context.update({'song_album':song_album})
        return context

class SongUpdate(LoginRequiredMixin, UpdateView):
    model = Song
    fields = ['file_type', 'song_title', 'is_favorite']

    # overwrite field['album']
    def form_valid(self, form):
        form.instance.album = Album.objects.get(pk=self.kwargs['album_pk'])
        return super().form_valid(form)

    # pass variable song_album to song_form template
    def get_context_data(self, **kwargs):
        context = super(SongUpdate, self).get_context_data(**kwargs)

        song_album = Album.objects.get(pk=self.kwargs['album_pk']).album_title

        context.update({'song_album': song_album})
        return context

class SongDelete(LoginRequiredMixin, DeleteView):
    model = Song
    #redirect to detail page after delete
    def get_success_url(self):
        return  reverse_lazy('music:detail',kwargs={'pk': self.kwargs['album_pk']})

#user registration
class UserRegistration(View):
    form_class = RegistrationForm
    template_name = 'music/registration_form.html'

    def get(self, request):
        #get request, display UserForm with empty fields
        form = self.form_class(None)
        return render(request, self.template_name, {'form': form})

    def post(self, request):
        form = self.form_class(request.POST)

        if form.is_valid():

            user = form.save(commit=False)

            #clearned/normalized data
            password = form.cleaned_data['password']

            user.set_password(password)
            user.save()

            messages.success(request, 'registration successful')
            return redirect('music:login')

        return render(request, self.template_name, {'form': form})

#user login
class UserLogin(View):
    form_class = LoginForm
    template_name = 'music/login_form.html'

    def get(self, request):
        #get request, display UserForm with empty fields
        form = self.form_class(None)
        return render(request, self.template_name, {'form': form})

    def post(self, request):
        form = self.form_class(request.POST)

        if form.is_valid():

            #clearned/normalized data
            username = form.cleaned_data['username']
            password = form.cleaned_data['password']

            #returns User objects if credentials are correct
            user = authenticate(username=username, password=password)

            if user is not None:

                if user.is_active:
                    login(request, user)
                    return redirect('music:index')

        messages.error(request, 'error logging in')
        return render(request, self.template_name, {'form': form})

def UserLogout(request):
    logout(request)
    return redirect('music:index')

-----------------------------------------------
#music/template/index

{% extends 'music/base.html' %}
{% block title %}Albums{% endblock %}

{% block body %}
    <div class="container-fluid">
        <div class="row">
            {% for album in object_list %}
                <div class="col" style="margin-left: auto; margin-right: auto; margin-top: 5px; margin-bottom: 5px;">
                    <div class="card" style="width: 200px;">
                        <img src="{{album.album_logo.url}}" class="card-img-top" style="height: 150px" alt="{{album.album_title}}">

                        <div class="card-body">
                            <div style="height: 40px"><h5 class="card-title">Album: {{album.album_title}}</h5></div>
                            <div style="height: 40px"><p class="card-text">Artist: {{album.artist}}</p></div>

                            <!-- Detail -->
                            <a href="{% url 'music:detail' album.id %}" class="btn btn-primary btn-sm">View Detail</a>

                            <!-- Edit -->
                            <a class="btn btn-default btn-sm" href="{% url 'music:album-update' album.id %}">
                                <span class="glyphicon glyphicon-pencil"></span>
                            </a>

                            <!-- Delete -->
                            <a class="btn btn-default btn-sm" href="{% url 'music:album-delete' album.id %}">
                                <span class="glyphicon glyphicon-trash"></span>
                            </a>

                        </div>

                        <div class="card-footer text-muted">
                            Created by {{album.author}} @ {{album.date_posted}}
                        </div>
                    </div>
                </div>
            {% endfor %}
        </div>
    </div>
{% endblock %}

No comments:

Post a Comment