Commit 3dea0324 authored by Давид Ли's avatar Давид Ли

lesson 53

parent b2b362a5
{
"sqltools.connections": [
{
"previewLimit": 50,
"driver": "SQLite",
"database": "${workspaceFolder:ap-11_django}/db.sqlite3",
"name": "db"
}
],
"sqltools.useNodeRuntime": true
}
\ No newline at end of file
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'
from django import forms
from django.contrib.auth.forms import AuthenticationForm
class LoginForm(AuthenticationForm):
username = forms.CharField(
max_length=100,
widget=forms.TextInput(
attrs={
'class': 'form-control mb-3'
}
)
)
password = forms.CharField(
max_length=100,
widget=forms.PasswordInput(
attrs={
'class': 'form-control mb-3'
}
)
)
# Generated by Django 3.2.19 on 2023-07-24 10:29
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')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('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')),
('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={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
{% extends 'base.html' %}
{% block title %}
<h1 class="my-4 text-center">Login</h1>
{% endblock %}
{% block content %}
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
{% include 'partial/form.html' with button_text='Login' %}
</form>
{% endblock %}
from django.test import TestCase
# Create your tests here.
from django.urls import reverse_lazy
from django.contrib.auth import views
from accounts.forms import LoginForm
class LoginView(views.LoginView):
template_name = 'login.html'
form_class = LoginForm
class LogoutView(views.LogoutView):
pass
...@@ -39,7 +39,8 @@ INSTALLED_APPS = [ ...@@ -39,7 +39,8 @@ INSTALLED_APPS = [
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'django_extensions', 'django_extensions',
'web' 'web',
'accounts'
] ]
MIDDLEWARE = [ MIDDLEWARE = [
...@@ -138,3 +139,8 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' ...@@ -138,3 +139,8 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
SHELL_PLUS = "bpython" SHELL_PLUS = "bpython"
AUTH_USER_MODEL = 'accounts.User'
LOGIN_URL = 'login'
LOGIN_REDIRECT_URL = 'main_page'
LOGOUT_REDIRECT_URL = 'main_page'
...@@ -18,11 +18,15 @@ from django.conf.urls.static import static ...@@ -18,11 +18,15 @@ from django.conf.urls.static import static
from django.contrib import admin from django.contrib import admin
from django.urls import path from django.urls import path
from web import views from web import views
from accounts import views as accounts_views
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('', views.MainPageRedirectView.as_view()), path('', views.MainPageRedirectView.as_view()),
path('auth/login/', accounts_views.LoginView.as_view(), name='login'),
path('auth/logout/', accounts_views.LogoutView.as_view(), name='logout'),
path('articles/', views.ArticleIndexView.as_view(), name='main_page'), path('articles/', views.ArticleIndexView.as_view(), name='main_page'),
path('articles/add/', views.ArticleCreateView.as_view(), name='articles-add'), path('articles/add/', views.ArticleCreateView.as_view(), name='articles-add'),
path('articles/<int:id>/', views.ArticleDetailView.as_view(), name='articles-detail'), path('articles/<int:id>/', views.ArticleDetailView.as_view(), name='articles-detail'),
...@@ -30,7 +34,7 @@ urlpatterns = [ ...@@ -30,7 +34,7 @@ urlpatterns = [
path('articles/<int:id>/delete', views.ArticleDeleteView.as_view(), name='delete_article'), path('articles/<int:id>/delete', views.ArticleDeleteView.as_view(), name='delete_article'),
path( path(
'comments/add/', 'articles/article_id/comments/add/',
views.CommentCreateView.as_view(), views.CommentCreateView.as_view(),
name='comment_create' name='comment_create'
), ),
...@@ -43,5 +47,6 @@ urlpatterns = [ ...@@ -43,5 +47,6 @@ urlpatterns = [
'comments/<int:id>/delete', 'comments/<int:id>/delete',
views.CommentDeleteView.as_view(), views.CommentDeleteView.as_view(),
name='comment_delete' name='comment_delete'
) ),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# Generated by Django 3.2.19 on 2023-07-24 10:29
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('web', '0012_alter_article_title'),
]
operations = [
migrations.AlterField(
model_name='article',
name='title',
field=models.CharField(max_length=200, validators=[django.core.validators.MinLengthValidator(5)], verbose_name='Заголовок'),
),
]
...@@ -11,11 +11,14 @@ ...@@ -11,11 +11,14 @@
<hr> <hr>
<br> <br>
<h2>{{ article.title }}</h2> <h2>{{ article.title }}</h2>
{% if user.is_authenticated %}
<p> <p>
<a href="{% url 'articles-detail' id=article.id %}"> <a href="{% url 'articles-detail' id=article.id %}">
Подробнее Подробнее
</a> </a>
</p> </p>
{% endif %}
<br> <br>
<hr> <hr>
<br> <br>
......
...@@ -6,33 +6,63 @@ ...@@ -6,33 +6,63 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.1/css/bootstrap.min.css" <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.1/css/bootstrap.min.css"
integrity="sha512-Ez0cGzNzHR1tYAv56860NLspgUGuQw16GiOOp/I2LuTmpSK9xDXlgJz3XN4cnpXWDmkNBKXR/VDMTCnAaEooxA==" integrity="sha512-Ez0cGzNzHR1tYAv56860NLspgUGuQw16GiOOp/I2LuTmpSK9xDXlgJz3XN4cnpXWDmkNBKXR/VDMTCnAaEooxA=="
crossorigin="anonymous" referrerpolicy="no-referrer"/> crossorigin="anonymous" referrerpolicy="no-referrer"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw=="
crossorigin="anonymous" referrerpolicy="no-referrer"/>
<link rel="stylesheet" href="{% static 'css/styles.css' %}"> <link rel="stylesheet" href="{% static 'css/styles.css' %}">
<title>Title</title> <title>Title</title>
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container"> <div class="container">
<a class="navbar-brand" href="{% url 'main_page' %}">Articles</a> <a class="navbar-brand" href="{% url 'main_page' %}">Articles</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"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
<span class="navbar-toggler-icon"></span> aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
</button> <span class="navbar-toggler-icon"></span>
<div class="collapse navbar-collapse flex-grow-0" id="navbarNav"> </button>
<ul class="navbar-nav"> <div class="collapse navbar-collapse flex-grow-0" id="navbarNav">
<li class="nav-item"> <ul class="navbar-nav">
<a class="nav-link active" aria-current="page" href="{% url 'articles-add' %}"> <li class="nav-item">
Create <a class="nav-link active" aria-current="page" href="{% url 'articles-add' %}">
</a> Create
</li> </a>
<li class="nav-item"> </li>
<a class="nav-link" href="#">Features</a> <li class="nav-item">
</li> <a class="nav-link" href="#">Features</a>
<li class="nav-item"> </li>
<a class="nav-link" href="#">Pricing</a>
</li> {% if user.is_authenticated %}
</ul> <li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
{{ user.username }}
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li>
<form action="{% url 'logout' %}" method="post">
{% csrf_token %}
<label class="w-100">
<input class="dropdown-item text-danger" value="Logout" type="submit">
</label>
</form>
</li>
</ul>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Login</a>
</li>
{% endif %}
</ul>
</div>
</div> </div>
</div>
</nav> </nav>
<div class="container"> <div class="container">
{% block title %}{% endblock %} {% block title %}{% endblock %}
...@@ -40,6 +70,8 @@ ...@@ -40,6 +70,8 @@
{% block content %}{% endblock %} {% block content %}{% endblock %}
</div> </div>
{% block script %}{% endblock %} {#{% block script %}{% endblock %}#}
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.min.js" integrity="sha512-3dZ9wIrMMij8rOH7X3kLfXAzwtcHpuYpEgQg1OA4QAob1e81H8ntUQmQm3pBudqIoySO5j0tHN4ENzA6+n2r4w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.0/js/bootstrap.bundle.min.js" integrity="sha512-VK2zcvntEufaimc+efOYi622VN5ZacdnufnmX7zIhCPmjhKnOi9ZDMtg1/ug5l183f19gG1/cBstPO4D8N/Img==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</body> </body>
</html> </html>
\ No newline at end of file
...@@ -2,8 +2,8 @@ from urllib.parse import urlencode ...@@ -2,8 +2,8 @@ from urllib.parse import urlencode
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.db.models import Q from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ( from django.views.generic import (
RedirectView,
ListView, ListView,
DetailView, DetailView,
CreateView, CreateView,
...@@ -60,7 +60,8 @@ class ArticleCreateView(CreateView): ...@@ -60,7 +60,8 @@ class ArticleCreateView(CreateView):
return reverse('articles-detail', kwargs={'id': self.object.id}) return reverse('articles-detail', kwargs={'id': self.object.id})
class ArticleDetailView(DetailView): class ArticleDetailView(LoginRequiredMixin, DetailView):
raise_exception = True
template_name = 'article/article_detail.html' template_name = 'article/article_detail.html'
model = Article model = Article
context_object_name = 'article' context_object_name = 'article'
...@@ -74,7 +75,7 @@ class ArticleDetailView(DetailView): ...@@ -74,7 +75,7 @@ class ArticleDetailView(DetailView):
) )
class ArticleUpdateView(UpdateView): class ArticleUpdateView(LoginRequiredMixin, UpdateView):
model = Article model = Article
template_name = 'article/update.html' template_name = 'article/update.html'
form_class = ArticleModelForm form_class = ArticleModelForm
......
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