Friday, 22 March 2019

django 20 registration authentication

open webpage, not log in yet

click add, update, delete album will redirect to login page

new user, register account

new user registered

after registration, log in 

add, update, delete are enabled now, update first album picture

after submit update, log out, changes are saved


#music/urls

from django.urls import path
from . import views

app_name = 'music'

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),

    path('register/', views.UserRegistration.as_view(), name='register'),

    path('login/', views.UserLogin.as_view(), name='login'),

    path('logout/', views.UserLogout, name='logout'),

    #/music/id/
    path('<pk>/', views.DetailView.as_view(), name='detail'),

    #music/album/add/
    path('album/add/', views.AlbumCreate.as_view(), name='album-add'),

    #music/album/id/
    path('album/<pk>/', views.AlbumUpdate.as_view(), name='album-update'),

    #music/album/id/delete/
    path('album/<pk>/delete/', views.AlbumDelete.as_view(), name='album-delete'),
]

--------------------------------------------------
#music/views

from django.views import generic
from .models import Album
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

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']

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

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

#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()

            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')

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

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

-----------------------------------------------------
#project1/settings

#redirect to login page if not authenticated
LOGIN_URL = 'music:login'

--------------------------------------
#music/forms

from django.contrib.auth.models import User
from django import forms

class RegistrationForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ['username', 'email', 'password']

#ModelForm creates new. login existing, use Form instead
class LoginForm(forms.Form):
    username = forms.CharField(widget=forms.TextInput())
    password = forms.CharField(widget=forms.PasswordInput)
    fields = ['username', 'password']

------------------------------------------------
#music/template/music/login_form

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

{% block body %}
    <div class="container-fluid">

        <div class="row">

            <div class="col-sm-12 col-md-7">

                <div class="panel panel-default">

                    <div class="panel-body">

                        <form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
                            {% csrf_token %}
                            <div class="form-group">
                                <h3 class="col-sm-offset-2 col-sm-10">Login</h3>
                            </div>
                            {% include 'music/form-template.html' %}
                            <div class="form-group">
                                <div class="col-sm-offset-2 col-sm-10">
                                    Don't have an account?
                                    <a href="{% url 'music:register' %}">Register one</a>
                                </div>
                            </div>
                            <div class="form-group">
                                <div class="col-sm-offset-2 col-sm-10">
                                    <button type="submit" class="btn btn-success" >Submit</button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>

{% endblock %}

------------------------------------------
#music/templates/music/base

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% load staticfiles %}
    <!-- my css -->
    <link rel="stylesheet" type="text/css" href="{% static 'music/style.css' %}"/>
    <!-- bootstrap -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
    <!-- google fonts -->
    <link href="https://fonts.googleapis.com/css?family=Srisakdi" rel="stylesheet">
    <title>{% block title %}Django{% endblock %}</title>
</head>
<body>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>

    <nav class="navbar navbar-expand-lg navbar-light" style="background-color: #fcefe5;">
        <a class="navbar-brand" style="font-family: 'Srisakdi', serif; font-weight: bold; text-shadow: 4px 4px 4px #aaa;" href="{% url 'music:index' %}">Django</a>

        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
         <span class="navbar-toggler-icon"></span>
        </button>

        <div class="collapse navbar-collapse" id="navbarTogglerDemo02">
          <ul class="navbar-nav">
            <li class="nav-item active">
              <a class="nav-link" href="{% url 'music:index' %}"><span class="glyphicon glyphicon-cd" aria-hidden="true"></span>&nbsp Albums</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#"><span class="glyphicon glyphicon-music" aria-hidden="true"></span>&nbsp Songs</a>
            </li>
          </ul>

            <form class="navbar-form navbar-left" role="search" method="get" action="#">
                <div class="form-group">
                    <input type="text" name="q" value=""/>
                </div>
                <button type="submit" >Search</button>
            </form>

            <ul class="navbar-nav navbar-right">
                <li>
                    <a class="nav-link" href="{% url 'music:album-add' %}">
                        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>&nbsp; Add Album
                    </a>
                </li>
                <li>
                    {% if user.is_authenticated %}
                        <a class="nav-link" href="{% url 'music:logout' %}">
                            <span class="glyphicon glyphicon-off" aria-hidden="true"></span>&nbsp; Logout {{user.username}}
                        </a>
                    {% else %}
                        <a class="nav-link" href="{% url 'music:login' %}">
                            <span class="glyphicon glyphicon-user" aria-hidden="true"></span>&nbsp; Login
                        </a>
                    {% endif %}
                </li>
            </ul>
        </div>
    </nav>

    {% block body %}
    {% endblock %}
</body>
</html>

----------------------------------------
#music/templates/music/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 -->
                            <form action="{% url 'music:album-update' album.id %}" method="post" style="display: inline;">
                                {% csrf_token %}
                                <input type="hidden" name="album_id" value="{{album.id}}"/>
                                <button type="submit" class="btn btn-default btn-sm">
                                    <span class="glyphicon glyphicon-pencil"></span>
                                </button>
                            </form>

                            <!-- Delete -->
                            <form action="{% url 'music:album-delete' album.id %}" method="post" style="display: inline;">
                                {% csrf_token %}
                                <input type="hidden" name="album_id" value="{{album.id}}"/>
                                <button type="submit" class="btn btn-default btn-sm">
                                    <span class="glyphicon glyphicon-trash"></span>
                                </button>
                            </form>

                            <!-- Favorite -->
                            <a href="" class="btn btn-default btn-sm btn-favorite">
                                <span class="glyphicon glyphicon-star {% if album.is_favorite %}active{% endif %}"></span>
                            </a>
                        </div>
                    </div>
                </div>
            {% endfor %}
        </div>
    </div>
{% endblock %}

--------------------------------------
#music/templates/music/form-template

{% for field in form %}

    <div class="form-group">

        <div class="col-sm-offset-2 col-sm-10">

            <span class="text-danger small">{{ field.errors }}</span>
        </div>
        <label class="control-label col-sm-2">{{ field.label_tag }}</label>
        <div class="col-sm-10">{{ field }}</div>
    </div>
{% endfor %}

reference:
https://stackoverflow.com/questions/42792734/django-authenticate-a-user-with-that-username-already-exists
https://wsvincent.com/django-user-authentication-tutorial-login-and-logout/
https://kite.com/python/docs/django.contrib.auth.logout
https://docs.djangoproject.com/en/2.1/topics/auth/default/
https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Authentication
https://stackoverflow.com/questions/39554829/django-use-post-in-updateview-to-populate-forms-fields-with-instances-exist

No comments:

Post a Comment