logged in as bob, show bob's posts
click update profile, change username to bobby
profile updated, select bobby's posts
display all bobby's posts (originally bob's)
select change password, error if old password not match
all field entered right, password updated, bobby still logged in
log out bobby, and log in again with new password
login successful
#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('editProfile/', views.UserProfileUpdate.as_view(), name='profile-update'),
path('changePassword/', views.UserPasswordUpdate, name='password-update'),
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/song/add/
path('song/<album_pk>/add/', views.SongCreate.as_view(), name='song-add'),
#music/song/id/
path('song/<album_pk>/<pk>/', views.SongUpdate.as_view(), name='song-update'),
#music/song/id/delete/
path('song/<album_pk>/<pk>/delete/', views.SongDelete.as_view(), name='song-delete'),
]
-------------------------------------------------------------
#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, update_session_auth_hash
from .forms import RegistrationForm, LoginForm, ProfileUpdateForm
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib import messages
from django.contrib.auth.models import User
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.decorators import login_required
post_num = 4
author_name = None
#get list of username
def get_authors():
authorNames = []
for author in User.objects.all():
authorNames.append(author.username)
return authorNames
author_names = get_authors()
class IndexView(generic.ListView):
template_name = 'music/index.html'
paginate_by = post_num
def get_paginate_by(self, queryset):
global post_num
post_num = self.request.GET.get('postNum', self.paginate_by)
return post_num
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['post_num'] = post_num
context['author_name'] = author_name
context['all_authors_names'] = author_names
return context
def get_queryset(self):
global author_name
author_name = self.request.GET.get('userName', None)
if(author_name not in [None,'None','All']):
author_id = User.objects.get(username=author_name).pk
return Album.objects.filter(author=author_id).order_by('-date_posted')
else:
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 profile update
class UserProfileUpdate(LoginRequiredMixin, View):
form_class = ProfileUpdateForm
template_name = 'music/registration_form.html'
def get(self, request):
#get request, display UserForm with prefilled fields
form = ProfileUpdateForm(instance=self.request.user)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = ProfileUpdateForm(request.POST, instance=self.request.user)
if form.is_valid():
form.save()
#update author_names
global author_names
author_names = get_authors()
messages.success(request, 'profile updated')
return redirect('music:index')
return render(request, self.template_name, {'form': form})
#user password update
@login_required
def UserPasswordUpdate(request):
if request.method == 'POST':
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
user = form.save()
#keep current user logged in
update_session_auth_hash(request, user)
messages.success(request, 'password updated!')
return redirect('music:index')
else:
messages.error(request, 'Please correct the error below.')
else:
form = PasswordChangeForm(request.user)
return render(request, 'music/registration_form.html', {'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')
--------------------------------------------
#forms
from django.contrib.auth.models import User
from django import forms
from django.contrib.auth.forms import UserChangeForm
class RegistrationForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password']
class LoginForm(forms.Form):
username = forms.CharField(widget=forms.TextInput())
password = forms.CharField(widget=forms.PasswordInput)
fields = ['username', 'password']
class ProfileUpdateForm(UserChangeForm):
def __init__(self, *args, **kwargs):
super(ProfileUpdateForm, self).__init__(*args, **kwargs)
del self.fields['password']
class Meta:
model = User
fields = ('username','email','first_name','last_name')
--------------------------------------------
#templates/base
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- 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">
<!-- my css -->
<link rel="stylesheet" type="text/css" href="{% static 'music/style.css' %}">
<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="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span> {{user.username}} ▼
</a>
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<a class="dropdown-item" href="{% url 'music:logout' %}">
<span class="glyphicon glyphicon-off" aria-hidden="true"></span> Log out
</a>
<a class="dropdown-item" href="{% url 'music:profile-update' %}">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span> Update Profile
</a>
<a class="dropdown-item" href="{% url 'music:password-update' %}">
<span class="glyphicon glyphicon-barcode" aria-hidden="true"></span> Change Password
</a>
</div>
{% 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>
{% if messages %}
{% for message in messages %}
{% if message.tags == 'error' %}
<div class="alert alert-danger">{{message}}</div>
{% else %}
<div class="alert alert-{{message.tags}}">{{message}}</div>
{% endif %}
{% endfor %}
{% endif %}
{% block body %}
{% endblock %}
</body>
</html>
reference:
http://chuanshuoge2.blogspot.com/2019/04/django-31-update-user-profile.html
No comments:
Post a Comment