Commit 90c2d2d3 authored by Давид Ли's avatar Давид Ли

lesson 60

parent 97811be9
from django.contrib import admin from django.contrib import admin
from accounts.models import User from django.contrib.auth.admin import UserAdmin
from accounts import models
admin.site.register(User) # admin.site.register(User)
class ProfileInline(admin.StackedInline):
model = models.Profile
fields = ['birth_date', 'avatar']
class MyUserAdmin(UserAdmin):
inlines = [ProfileInline]
admin.site.register(models.User, MyUserAdmin)
# Generated by Django 3.2.19 on 2024-02-29 13:41
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('accounts', '0004_alter_user_is_active'),
]
operations = [
migrations.CreateModel(
name='Profile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('birth_date', models.DateField(null=True, verbose_name='Дата рождения')),
('avatar', models.ImageField(null=True, upload_to='avatars', verbose_name='Аватар')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Пользователь')),
],
options={
'verbose_name': 'Профиль',
'verbose_name_plural': 'Профили',
},
),
]
# Generated by Django 3.2.19 on 2024-02-29 14:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0005_profile'),
]
operations = [
migrations.AlterField(
model_name='profile',
name='avatar',
field=models.ImageField(default='avatars/no_image.jpeg', null=True, upload_to='avatars', verbose_name='Аватар'),
),
]
...@@ -18,3 +18,20 @@ class User(AbstractUser): ...@@ -18,3 +18,20 @@ class User(AbstractUser):
), ),
) )
password = models.CharField(max_length=128, verbose_name='password', null=True) password = models.CharField(max_length=128, verbose_name='password', null=True)
# Pillow
# sudo apt-get install libjpeg-dev zlib1g-dev
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name='Пользователь')
birth_date = models.DateField(null=True, verbose_name='Дата рождения')
avatar = models.ImageField(null=True, upload_to='avatars', verbose_name='Аватар', default='avatars/no_image.jpeg')
class Meta:
verbose_name = 'Профиль'
verbose_name_plural = 'Профили'
def __str__(self):
return self.user.get_full_name()
from accounts.views import RegisterView from accounts import views
from django.urls import path from django.urls import path
from django.contrib.auth.views import LoginView, LogoutView from django.contrib.auth.views import LoginView, LogoutView
...@@ -7,5 +7,6 @@ from django.contrib.auth.views import LoginView, LogoutView ...@@ -7,5 +7,6 @@ from django.contrib.auth.views import LoginView, LogoutView
urlpatterns = [ urlpatterns = [
path('login', LoginView.as_view(template_name='auth/login.html'), name='login'), path('login', LoginView.as_view(template_name='auth/login.html'), name='login'),
path('logout', LogoutView.as_view(), name='logout'), path('logout', LogoutView.as_view(), name='logout'),
path('register', RegisterView.as_view(), name='register'), path('register', views.RegisterView.as_view(), name='register'),
path('<int:id>/', views.UserDetailView.as_view(), name='profile'),
] ]
from django.http import HttpRequest
from django.urls import reverse from django.urls import reverse
from accounts import forms from accounts import forms, models
from django.views import generic from django.views import generic
from django.contrib.auth import login, get_user_model from django.contrib.auth import login, get_user_model, mixins
from django.shortcuts import redirect from django.shortcuts import redirect
from django.core import exceptions from django.core import exceptions
from django.core.paginator import Paginator
class RegisterView(generic.CreateView): class RegisterView(generic.CreateView):
...@@ -56,3 +58,33 @@ class RegisterView(generic.CreateView): ...@@ -56,3 +58,33 @@ class RegisterView(generic.CreateView):
'next', 'next',
self.request.GET.get('next', 'index') self.request.GET.get('next', 'index')
) )
class UserDetailView(mixins.LoginRequiredMixin, generic.DetailView):
model = get_user_model()
template_name = 'auth/user_detail.html'
context_object_name = 'user_obj'
pk_url_kwarg = 'id'
paginate_by = 3
paginate_orphans = 0
def __get_paginator(self):
articles = self.object.articles.order_by('-created_at')
return Paginator(articles, self.paginate_by, self.paginate_orphans)
def get_context_data(self, **kwargs):
# Проверяем, если профиль привязанный к нашему юзеру уже есть, то ничего не делать
# Если нет, то создать пустой профиль
models.Profile.objects.get_or_create(user=self.object)
paginator = self.__get_paginator()
page_number = self.request.GET.get('page', 1)
page = paginator.get_page(page_number)
return super().get_context_data(
**kwargs,
paginator=paginator,
page_obj=page,
is_paginated=page.has_other_pages(),
)
...@@ -137,3 +137,8 @@ LOGIN_REDIRECT_URL = LOGOUT_REDIRECT_URL = 'index' ...@@ -137,3 +137,8 @@ LOGIN_REDIRECT_URL = LOGOUT_REDIRECT_URL = 'index'
LOGIN_URL = 'login' LOGIN_URL = 'login'
AUTH_USER_MODEL = 'accounts.User' AUTH_USER_MODEL = 'accounts.User'
# MEDIA
MEDIA_ROOT = BASE_DIR / 'uploads'
MEDIA_URL = '/images/'
# localhost:1025/uploads/avatars/user_1.jpg
...@@ -15,6 +15,8 @@ Including another URLconf ...@@ -15,6 +15,8 @@ Including another URLconf
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import path, include from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
from webapp import views from webapp import views
...@@ -24,4 +26,5 @@ urlpatterns = [ ...@@ -24,4 +26,5 @@ urlpatterns = [
path('articles/', include('webapp.urls')), path('articles/', include('webapp.urls')),
path('accounts/', include('accounts.urls')), path('accounts/', include('accounts.urls')),
]
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
{% extends 'base.html' %}
{% block content %}
<h1>Личная страница пользователя {{ user_obj.get_full_name }}</h1>
{% if user_obj.profile.avatar %}
<img src="{{ user_obj.profile.avatar.url }}" width="250" height="250" class="object-fit-cover" alt="user_avatar">
{% endif %}
<p>Имя пользователя: {{ user_obj.username }}</p>
<p>Имя: {{ user_obj.first_name }}</p>
<p>Фамилия: {{ user_obj.last_name }}</p>
<p>Дата Рождения: {{ user_obj.profile.birth_date|date:'d.m.Y' }}</p>
<p>Почта: {{ user_obj.email }}</p>
<h2 class="text-center">Статьи</h2>
{{page_obj.has_other_pages}}
{% include 'partial/article_list.html' with articles=page_obj.object_list is_paginated=page_obj.has_other_pages %}
{% endblock %}
\ No newline at end of file
...@@ -35,7 +35,9 @@ ...@@ -35,7 +35,9 @@
<a class="nav-link" href="{% url 'logout' %}?next={{ request.get_full_path }}">Logout</a> <a class="nav-link" href="{% url 'logout' %}?next={{ request.get_full_path }}">Logout</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<span class="nav-link fw-bold">Hello, {{ user.username }}</span> <span class="nav-link fw-bold">
Hello, <a href="{% url 'profile' user.id %}" class="text-decoration-none text-secondary">{{ user.username }}</a>
</span>
</li> </li>
{% else %} {% else %}
......
...@@ -6,17 +6,7 @@ ...@@ -6,17 +6,7 @@
<p><a href="{% url 'articles_add' %}">Добавить</a></p> <p><a href="{% url 'articles_add' %}">Добавить</a></p>
{% for article in articles %} {% include 'partial/article_list.html' %}
<h2>{{ article.title }}</h2>
<a href="{% url 'articles_detail' id=article.id %}">Подробнее...</a>
<hr>
{% empty %}
<h2>no articles yet ...</h2>
{% endfor %}
</div> </div>
{% if is_paginated %}
{% include 'partial/pagination.html' %}
{% endif %}
{% endblock %} {% endblock %}
\ No newline at end of file
{% for article in articles %}
<h2>{{ article.title }}</h2>
<a href="{% url 'articles_detail' id=article.id %}">Подробнее...</a>
<hr>
{% empty %}
<h2>no articles yet ...</h2>
{% endfor %}
{% if is_paginated %}
{% include 'partial/pagination.html' %}
{% endif %}
<div class="d-flex justify-content-center"> <div class="d-flex justify-content-center mt-5">
<nav aria-label="..."> <nav aria-label="...">
<ul class="pagination"> <ul class="pagination">
{% if page_obj.has_previous %} {% if page_obj.has_previous %}
......
asgiref==3.7.2
Django==3.2.23 Django==3.2.23
pytz==2023.3.post1 Pillow==10.0.0
sqlparse==0.4.4
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment