Skip to content

Commit d1380ae

Browse files
add profile edit
1 parent 378ecae commit d1380ae

File tree

6 files changed

+142
-33
lines changed

6 files changed

+142
-33
lines changed

post/forms.py

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
import re
2-
31
from django import forms
42
from django.contrib.auth.models import User
5-
from django.core.validators import EmailValidator
63

74
from .validators import LetterUsernameValidator
85

96

107
class LoginForm(forms.Form):
11-
username = forms.CharField(widget=forms.TextInput)
8+
"""Форма авторизации"""
9+
username = forms.CharField()
1210
password = forms.CharField(widget=forms.PasswordInput)
1311

1412
def __init__(self, *args, **kwargs):
@@ -29,6 +27,7 @@ def clean(self):
2927

3028

3129
class RegistrationForm(forms.ModelForm):
30+
"""Форма регистрации"""
3231
username_validator = LetterUsernameValidator()
3332
username = forms.CharField(
3433
widget=forms.TextInput,
@@ -72,3 +71,30 @@ def clean(self):
7271
class Meta:
7372
model = User
7473
fields = ('username', 'password', 'confirm_password', 'email', 'first_name', 'last_name')
74+
75+
76+
class EditProfileForm(RegistrationForm):
77+
"""Форма для изменения данных в профиле"""
78+
bio = forms.CharField(widget=forms.Textarea, required=False, max_length=300)
79+
80+
def __init__(self, *args, **kwargs):
81+
self.user = kwargs.pop('user', None)
82+
super().__init__(*args, **kwargs)
83+
self.fields['bio'].label = 'Краткая информация'
84+
85+
def clean_username(self):
86+
username = self.cleaned_data['username']
87+
if User.objects.filter(username=username).exists():
88+
if User.objects.get(username=username) != self.user:
89+
raise forms.ValidationError(f'Пользователь с логином {username} уже существует.')
90+
return username
91+
92+
def clean_email(self):
93+
email = self.cleaned_data['email']
94+
if User.objects.filter(email=email).exists():
95+
if User.objects.get(email=email) != self.user:
96+
raise forms.ValidationError(f'Email {email} уже используется в системе.')
97+
return email
98+
99+
class Meta(RegistrationForm.Meta):
100+
fields = ('username', 'password', 'confirm_password', 'email', 'first_name', 'last_name', 'bio')

post/templates/post/base.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252

5353

5454

55+
5556
</style>
5657
<link href="cover.css" rel="stylesheet">
5758
</head>
@@ -98,7 +99,7 @@ <h1 class="me-4 pe-7">
9899
{% if messages %}
99100
<br>
100101
{% for message in messages %}
101-
<div class="alert alert-success alert-dismissible fade show" role="alert"
102+
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert"
102103
style="margin-left: 450px; width: 900px;">
103104
<strong>{{ message }}</strong>
104105
</div>
@@ -126,7 +127,8 @@ <h1 class="me-4 pe-7">
126127
{% for post in posts %}
127128
<div class="card text-center">
128129
<div class="card-header">
129-
<a href="{{ post.author.get_absolute_url }}" class="text-decoration-none text-dark" style="font-weight: 600">
130+
<a href="{{ post.author.get_absolute_url }}" class="text-decoration-none text-dark"
131+
style="font-weight: 600">
130132
<img src="{{ post.author.avatar_thumbnail.url }}" alt="" width="32" height="32"
131133
class="rounded-circle me-2">{{ post.author.user.username }}
132134
</a>

post/templates/post/profile.html

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
{% extends 'post/base.html' %}
22
{% block title %}
3-
{{ profile.user.username }} | Ukiblog
3+
{{ main_profile.user.username }} | Ukiblog
44
{% endblock %}
55
{% block categories %}
66
{% endblock %}
77
{% block main %}
88
<div class="card" style="width: 800px; margin: 100px 600px 300px 500px; padding: 30px 30px">
99
<div class="card-body">
1010
<span class="text-start fs-1">
11-
<img src="{{ profile.avatar_thumbnail.url }}" alt="" width="100" height="100" class="rounded-circle me-2">
12-
<a class="ms-2 text-decoration-none">@{{ profile.user.username }}</a>
13-
{% if user == profile.user %}
14-
<a class="text-decoration-none">
11+
<img src="{{ main_profile.avatar_thumbnail.url }}" alt="" width="100" height="100" class="rounded-circle me-2">
12+
<a class="ms-2 text-decoration-none">@{{ main_profile.user.username }}</a>
13+
{% if user == main_profile.user %}
14+
<a href="{% url 'post:edit_profile' slug=main_profile.slug %}" class="text-decoration-none">
1515
<button type="button" class="btn btn-outline-primary btn-lg" style="margin-left: 200px">
1616
Настройки профиля
1717
</button>
@@ -26,28 +26,28 @@
2626
<tbody>
2727
<tr>
2828
<th scope="row">Настоящее имя</th>
29-
{% if profile.user.first_name %}
30-
<td>{{ profile.user.first_name }}</td>
29+
{% if main_profile.user.first_name %}
30+
<td>{{ main_profile.user.first_name }}</td>
3131
{% else %}
3232
<td>&mdash;</td>
3333
{% endif %}
3434
</tr>
3535
<tr>
3636
<th scope="row">Настоящая фамилия</th>
37-
{% if profile.user.last_name %}
38-
<td>{{ profile.user.last_name }}</td>
37+
{% if main_profile.user.last_name %}
38+
<td>{{ main_profile.user.last_name }}</td>
3939
{% else %}
4040
<td>&mdash;</td>
4141
{% endif %}
4242
</tr>
4343
<tr>
4444
<th scope="row">Email</th>
45-
<td>{{ profile.user.email }}</td>
45+
<td>{{ main_profile.user.email }}</td>
4646
</tr>
4747
<tr>
4848
<th scope="row">Статус</th>
4949
<td>
50-
{% if profile.author %}
50+
{% if main_profile.author %}
5151
Автор
5252
{% else %}
5353
Читатель
@@ -57,8 +57,8 @@
5757
</tbody>
5858
</table>
5959
<p class="fs-5"><strong class="text-secondary">Информация о пользователе:</strong>
60-
{% if profile.bio %}
61-
{{ profile.bio }}
60+
{% if main_profile.bio %}
61+
{{ main_profile.bio }}
6262
{% else %}
6363
отсутствует
6464
{% endif %}
@@ -77,10 +77,10 @@
7777
</ul>
7878
{% endfor %}
7979
{% else %}
80-
<p class="text-center fs-3 text-secondary">Вы не опубликовали ни одну статью :(</p>
80+
<p class="text-center fs-3 text-secondary">Публикации отсутствуют :(</p>
8181
{% endif %}
82-
{% if user == profile.user %}
83-
{% if profile.author %}
82+
{% if user == main_profile.user %}
83+
{% if main_profile.author %}
8484
<button type="button" class="btn btn-outline-primary btn-lg mt-5" style="margin-left: 200px">
8585
<a href="#" class="text-center text-decoration-none text-dark fs-5 mt-3">
8686
Опубликовать новую статью
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{% extends 'post/base.html' %}
2+
{% load crispy_forms_tags %}
3+
{% block title %}
4+
{{ profile.user.username }} | Ukiblog
5+
{% endblock %}
6+
{% block categories %}
7+
{% endblock %}
8+
{% block main %}
9+
<div class="card" style="width: 800px; margin: 100px 600px 300px 500px; padding: 30px 30px">
10+
<div class="card-body">
11+
<span class="text-start fs-1">
12+
<img src="{{ profile.avatar_thumbnail.url }}" alt="" width="100" height="100" class="rounded-circle me-2">
13+
<a class="ms-2 text-decoration-none">@{{ profile.user.username }}</a>
14+
</span>
15+
<hr>
16+
<p class="text-secondary fs-5 text-center"><strong>Настройки профиля</strong></p>
17+
<hr>
18+
<div style="width: 705px">
19+
<form action="" method="post">
20+
{% csrf_token %}
21+
{{ form|crispy }}
22+
<br>
23+
<div class="d-grid gap-2 col-6 mx-auto">
24+
<input type="submit" class="btn btn-success btn-lg" value="Обновить данные">
25+
</div>
26+
</form>
27+
</div>
28+
</div>
29+
</div>
30+
{% endblock %}

post/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
TagDetailView,
99
LoginView,
1010
RegistrationView,
11-
ProfileView
11+
ProfileView,
12+
EditProfileView,
1213
)
1314

1415
app_name = 'post'
@@ -20,4 +21,5 @@
2021
path('logout', LogoutView.as_view(next_page=reverse_lazy('post:base')), name='logout'),
2122
path('registration', RegistrationView.as_view(), name='registration'),
2223
path('profile/<slug:slug>', ProfileView.as_view(), name='profile'),
24+
path('profile/<slug:slug>/edit', EditProfileView.as_view(), name='edit_profile'),
2325
]

post/views.py

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
from django.shortcuts import render, redirect
22
from django.urls import reverse
33
from django.utils.text import slugify
4-
from django.views import View
5-
from django.views.generic.list import ListView
6-
from django.views.generic.detail import DetailView
4+
from django.views import View, generic
75
from django.contrib.auth import login, authenticate
6+
from django.contrib.auth.models import AnonymousUser, User
87
from django.contrib import messages
8+
from django.forms.models import model_to_dict
99

1010
from .models import Post, Tag, Profile
1111
from .mixins import DefaultContextMixin
12-
from .forms import LoginForm, RegistrationForm
12+
from .forms import LoginForm, RegistrationForm, EditProfileForm
1313

1414

15-
class BaseView(DefaultContextMixin, ListView):
15+
class BaseView(DefaultContextMixin, generic.ListView):
1616
"""Основная страница"""
1717
model = Post
1818
template_name = 'post/base.html'
@@ -22,15 +22,15 @@ def get_context_data(self, **kwargs):
2222
return super().get_context_data(self.request, **kwargs)
2323

2424

25-
class PostDetailView(DefaultContextMixin, DetailView):
25+
class PostDetailView(DefaultContextMixin, generic.DetailView):
2626
"""Отдельная статья"""
2727
model = Post
2828

2929
def get_context_data(self, **kwargs):
3030
return super().get_context_data(self.request, **kwargs)
3131

3232

33-
class TagDetailView(DefaultContextMixin, DetailView):
33+
class TagDetailView(DefaultContextMixin, generic.DetailView):
3434
"""Отдельный tag"""
3535
model = Tag
3636
context_object_name = 'main_tag'
@@ -106,13 +106,62 @@ def post(self, *args, **kwargs):
106106
return render(self.request, 'post/registration.html', context)
107107

108108

109-
class ProfileView(DetailView):
109+
class ProfileView(DefaultContextMixin, generic.DetailView):
110110
"""Подробная информация о пользователе"""
111111
model = Profile
112112
template_name_suffix = ''
113+
context_object_name = 'main_profile'
113114

114115
def get_context_data(self, **kwargs):
115-
context = super().get_context_data(**kwargs)
116+
context = super().get_context_data(self.request, **kwargs)
116117
context['user'] = self.request.user
117-
context['articles'] = Profile.objects.get(user=context['profile'].user).post_set.order_by('pub_date')
118+
context['articles'] = Profile.objects.get(user=context['main_profile'].user).post_set.order_by('pub_date')
118119
return context
120+
121+
122+
class EditProfileView(View):
123+
"""Настройки профиля"""
124+
def get(self, *args, **kwargs):
125+
if isinstance(self.request.user, AnonymousUser):
126+
messages.warning(self.request, 'У вас недостаточно прав!')
127+
return redirect(reverse('post:base'))
128+
elif Profile.objects.get(user=self.request.user) != Profile.objects.get(slug=kwargs['slug']):
129+
messages.warning(self.request, 'Вы можете редактировать только свой профиль!')
130+
return redirect(reverse('post:base'))
131+
profile = Profile.objects.get(slug=kwargs['slug'])
132+
data = model_to_dict(profile.user)
133+
data.update(bio=profile.bio)
134+
form = EditProfileForm(initial=data)
135+
context = {
136+
'profile': profile,
137+
'form': form,
138+
}
139+
return render(self.request, 'post/profile_settings.html', context)
140+
141+
def post(self, *args, **kwargs):
142+
profile = Profile.objects.get(slug=kwargs['slug'])
143+
user = profile.user
144+
form = EditProfileForm(self.request.POST, user=user)
145+
if form.is_valid():
146+
User.objects.filter(pk=user.pk).update(
147+
username=form.cleaned_data['username'],
148+
email=form.cleaned_data['email'],
149+
first_name=form.cleaned_data['first_name'].title(),
150+
last_name=form.cleaned_data['last_name'].title(),
151+
)
152+
user.set_password(form.cleaned_data['password'])
153+
user.save(update_fields=['password'])
154+
Profile.objects.filter(user=user).update(bio=form.cleaned_data['bio'])
155+
messages.success(
156+
self.request,
157+
f'Ваш профиль успешно обновлен с:'
158+
)
159+
user = authenticate(username=form.cleaned_data['username'], password=form.cleaned_data['password'])
160+
login(self.request, user)
161+
return redirect(reverse('post:base'))
162+
context = {
163+
'profile': profile,
164+
'form': form,
165+
}
166+
return render(self.request, 'post/profile_settings.html', context)
167+

0 commit comments

Comments
 (0)