Commit 3924716b authored by Давид Ли's avatar Давид Ли

Revert "complete registration and setup the project"

This reverts commit a480ffa9.
parent a480ffa9
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'
from django.contrib.auth import authenticate, get_user_model
from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm, AuthenticationForm
from django import forms
from django.db.models import Q
from django.forms import widgets
class RegisterForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = get_user_model()
fields = (
'username', 'email', 'avatar', 'password1', 'password2',
'first_name', 'last_name', 'phone', 'gender',
)
class UserUpdateForm(forms.ModelForm):
class Meta:
model = get_user_model()
fields = ('first_name', 'last_name', 'email')
widgets = {
'first_name': widgets.TextInput(attrs={
'class': 'form-control mb-3',
}),
'last_name': widgets.TextInput(attrs={
'class': 'form-control mb-3',
}),
'email': widgets.EmailInput(attrs={
'class': 'form-control mb-3',
}),
}
class ChangePasswordForm(PasswordChangeForm):
widgets = {
'new_password1': widgets.PasswordInput(attrs={
'class': 'form-control mb-3',
}),
'new_password2': widgets.PasswordInput(attrs={
'class': 'form-control mb-3',
}),
'old_password': widgets.PasswordInput(attrs={
'class': 'form-control mb-3',
}),
}
class AuthForm(AuthenticationForm):
def clean(self):
username = self.cleaned_data.get('username')
if username:
user = get_user_model().objects.get(
Q(email=username) | Q(username=username)
)
self.cleaned_data['username'] = user.username
return super().clean()
# Generated by Django 3.2.19 on 2024-03-27 15:13
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name='User',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('email', models.EmailField(max_length=254, verbose_name='email address')),
('avatar', models.ImageField(upload_to='avatars', verbose_name='avatar')),
('gender', models.CharField(blank=True, choices=[('M', 'M'), ('F', 'F'), ('U', 'Unknown')], max_length=10)),
('phone', models.CharField(blank=True, max_length=12)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'unique_together': {('email', 'username')},
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]
# Generated by Django 3.2.19 on 2024-03-27 15:15
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='user',
name='followers',
field=models.ManyToManyField(related_name='subscribers', to=settings.AUTH_USER_MODEL),
),
]
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth import get_user_model
class User(AbstractUser):
email = models.EmailField('email address', blank=False)
avatar = models.ImageField('avatar', upload_to='avatars')
gender = models.CharField(
max_length=10,
choices=(('M', 'M'), ('F', 'F'), ('U', 'Unknown')),
blank=True,
)
phone = models.CharField(max_length=12, blank=True)
followers = models.ManyToManyField('self', related_name='subscribers')
class Meta:
unique_together = ('email', 'username')
from django.test import TestCase
# Create your tests here.
from accounts import views, forms
from django.urls import path
from django.contrib.auth.views import LoginView, LogoutView
urlpatterns = [
path('login', LoginView.as_view(
template_name='auth/login.html', form_class=forms.AuthForm,
), name='login'),
path('logout', LogoutView.as_view(), name='logout'),
path('register', views.RegisterView.as_view(), name='register'),
path('change_password', views.ChangePasswordView.as_view(), name='change_password'),
path('update', views.UserUpdateView.as_view(), name='user_update'),
]
from django.db.models.base import Model as Model
from django.urls import reverse, reverse_lazy
from accounts import forms
from django.views import generic
from django.contrib.auth import get_user_model, mixins, views
from django.contrib.auth.mixins import LoginRequiredMixin
class RegisterView(generic.CreateView):
model = get_user_model()
template_name = 'auth/register.html'
form_class = forms.RegisterForm
def get_success_url(self):
return self.request.POST.get(
'next',
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
class UserUpdateView(LoginRequiredMixin, generic.UpdateView):
model = get_user_model()
form_class = forms.UserUpdateForm
template_name = 'auth/user_update.html'
context_object_name = 'user_obj'
pk_url_kwarg = 'id'
def get_context_data(self, **kwargs):
if 'profile_form' not in kwargs:
kwargs['profile_form'] = self.get_profile_form()
return super().get_context_data(**kwargs)
def get_profile_form(self):
kwargs = {'instance': self.object.profile}
if self.request.method == 'POST':
kwargs['data'] = self.request.POST
kwargs['files'] = self.request.FILES
return forms.ProfileUpdateForm(**kwargs)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
user_form = self.get_form()
profile_form = self.get_profile_form()
if user_form.is_valid() and profile_form.is_valid():
return self.form_valid(user_form, profile_form)
return self.form_invalid(user_form, profile_form)
def form_valid(self, user_form, profile_form):
response = super().form_valid(user_form)
profile_form.save()
return response
def form_invalid(self, user_form, profile_form):
context = self.get_context_data(form=user_form, profile_form=profile_form)
return self.render_to_response(context)
def get_success_url(self):
return reverse('profile', kwargs={'id': self.object.id})
def get_object(self, queryset=None):
return self.request.user
class ChangePasswordView(views.PasswordChangeView):
form_class = forms.ChangePasswordForm
template_name = 'auth/change_password.html'
def get_success_url(self):
return reverse_lazy('profile', kwargs={'id': self.request.user.id})
"""
ASGI config for app project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
application = get_asgi_application()
"""
Django settings for app project.
Generated by 'django-admin startproject' using Django 3.2.19.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-5+n2d0q)&ex4&=ie2mh9krn@^)e4nip#adqqk#gu3l907a^-)b'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'web',
'accounts',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'core.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'core.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIR / 'static',
]
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Media
MEDIA_URL = '/media/'
MEDIA_ROOT = 'uploads'
AUTH_USER_MODEL = 'accounts.User'
LOGIN_REDIRECT_URL = 'index'
\ No newline at end of file
"""app URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_core.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.conf.urls.static import static
from django.urls import path, include
from django.conf import settings
from web import views as web_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', web_views.IndexView.as_view(), name='index'),
path('accounts/', include('accounts.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
"""
WSGI config for app project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
application = get_wsgi_application()
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
This source diff could not be displayed because it is too large. You can view the blob instead.
body {
font-family: Arial, sans-serif;
margin: 0;
background-color: aqua;
}
.container {
margin: 0 auto;
width: 80%;
}
{% extends 'base.html' %}
{% block content %}
<h1 class="text-center">Смена пароля</h1>
<form action="" method="post">
{% csrf_token %}
{{ form.old_password.label }}
<input type="password" class="form-control mb-3" name="old_password">
{% if form.old_password.errors %}
{% for error in form.old_password.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
{% endif %}
{{ form.new_password1.label }}
<input type="password" class="form-control mb-3" name="new_password1">
{% if form.new_password1.errors %}
{% for error in form.new_password1.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
{% endif %}
{{ form.new_password2.label }}
<input type="password" class="form-control mb-3" name="new_password2">
{% if form.new_password2.errors %}
{% for error in form.new_password2.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
{% endif %}
<button class="btn btn-success">Submit</button>
</form>
{% endblock %}
\ No newline at end of file
{% extends 'base.html' %}
{% block content %}
<div class="d-flex justify-content-center flex-column align-items-center">
<h1 class="text-center mb-5">Вход</h1>
{% for error in form.non_field_errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
<form action="{% url 'login' %}" method="post" class="text-center">
{% csrf_token %}
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" aria-describedby="usernameHelp" name="username">
<div id="usernameHelp" class="form-text">We'll never share your username with anyone else.</div>
</div>
{% if form.username.errors %}
{% for error in form.username.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
{% endif %}
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
{% if form.password.errors %}
{% for error in form.password.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
{% endif %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div class="mt-5">
Don't have account?
<a class="" href="{% url 'register' %}?next={{ request.get_full_path }}">Register</a>
</div>
</div>
{% endblock %}
{% extends 'base.html' %}
{% block content %}
<h1 class="text-center">Registration</h1>
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{% include 'partial/form.html' with request_method='post' btn_text='Register' fields_only=True %}
</form>
{% endblock %}
{% 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>
{% if user_obj.is_moderator %}
<ul>
<li>Active: {{ user.is_active }}</li>
<li>Staff: {{ user.is_staff }}</li>
<li>Superuser: {{ user.is_superuser }}</li>
</ul>
{% endif %}
<a href="{% url 'user_update' %}" class="btn btn-warning mt-3">Обновить</a>
<a href="{% url 'change_password' %}" class="btn btn-primary mt-3">Сменить пароль</a>
<h2 class="text-center mb-5">Статьи</h2>
{% 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
{% extends 'base.html' %}
{% block content %}
<h1 class="text-center">Изменить личные данные</h1>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'partial/form.html' with fields_only=True %}
{% include 'partial/form.html' with form=profile_form fields_only=True %}
<button class="btn btn-success mt-5">Изменить</button>
</form>
{% endblock %}
\ No newline at end of file
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static "css/styles.css" %}">
<link rel="stylesheet" href="{% static "css/bootstrap.min.css" %}">
<title>Document</title>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container">
<a class="navbar-brand" href="{% url 'index' %}">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse flex-grow-0" id="navbarNav">
<ul class="navbar-nav">
<form class="d-flex">
<input class="form-control me-2" name="search" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}?next={{ request.get_full_path }}">Logout</a>
</li>
<li class="nav-item">
<span class="nav-link fw-bold">
Hello, <a href="" class="text-decoration-none text-secondary">{{ user.username }}</a>
</span>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}?next={{ request.get_full_path }}">Login</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<div class="container">
{% block content %}
{% endblock %}
</div>
<script>
let a = 1
</script>
</body>
</html>
\ No newline at end of file
{% extends 'base.html' %}
{% block content %}
<div class="text-center">
</div>
{% 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 %}
{% if not fields_only %}
<form method="{{ request_method|default:'get' }}" action="{{ action_url|default:'' }}">
{% csrf_token %}
{% endif %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
{% for field in form.visible_fields %}
<div class="my-4">
{{ field.label }}
{{ field }}
</div>
{% if field.errors %}
{% for error in field.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
{% endif %}
{% endfor %}
{% for field in form.hidden_fields %}
{{ field }}
{% endfor %}
{% if not fields_only %}
<button class="btn btn-success">{{ btn_text|default:'Submit' }}</button>
</form>
{% endif %}
\ No newline at end of file
<div class="d-flex justify-content-center mt-5">
<nav aria-label="...">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?{% if query_params %}{{ query_params }}{% endif %}&page={{ page_obj.previous_page_number }}">
Previous
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#">Previous</a>
</li>
{% endif %}
{% for num in paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active" aria-current="page">
<a class="page-link" href="?{% if query_params %}{{ query_params }}{% endif %}&page={{ num }}">{{ num }}</a>
</li>
{% else %}
<li class="page-item" aria-current="page">
<a class="page-link" href="?{% if query_params %}{{ query_params }}{% endif %}&page={{ num }}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?{% if query_params %}{{ query_params }}{% endif %}&page={{ page_obj.next_page_number }}">
Next
</a>
</li>
{% else %}
<li class="page-item disabled">
<a class="page-link" href="#">Next</a>
</li>
{% endif %}
</ul>
</nav>
</div>
\ No newline at end of file
<form class="text-center" action="" method="get">
<label for="{{ form.search.id_for_label }}">
{{ form.search.label }}:
</label>
{{ form.search }}
<button class="btn btn-submit">Search</button>
</form>
\ No newline at end of file
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class WebConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'web'
from django.db import models
# Create your models here.
from django.test import TestCase
# Create your tests here.
from django.shortcuts import render
from django.views import generic
class IndexView(generic.TemplateView):
template_name = 'index.html'
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