open webpage, not log in yet
click add, update, delete album will redirect to login page
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>  Albums</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#"><span class="glyphicon glyphicon-music" aria-hidden="true"></span>  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> 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> Logout {{user.username}}
</a>
{% else %}
<a class="nav-link" href="{% url 'music:login' %}">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span> 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