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 = [
'django.contrib.staticfiles',
'django_extensions',
'web'
'web',
'accounts'
]
MIDDLEWARE = [
......@@ -138,3 +139,8 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
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
from django.contrib import admin
from django.urls import path
from web import views
from accounts import views as accounts_views
urlpatterns = [
path('admin/', admin.site.urls),
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/add/', views.ArticleCreateView.as_view(), name='articles-add'),
path('articles/<int:id>/', views.ArticleDetailView.as_view(), name='articles-detail'),
......@@ -30,7 +34,7 @@ urlpatterns = [
path('articles/<int:id>/delete', views.ArticleDeleteView.as_view(), name='delete_article'),
path(
'comments/add/',
'articles/article_id/comments/add/',
views.CommentCreateView.as_view(),
name='comment_create'
),
......@@ -43,5 +47,6 @@ urlpatterns = [
'comments/<int:id>/delete',
views.CommentDeleteView.as_view(),
name='comment_delete'
)
),
] + 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 @@
<hr>
<br>
<h2>{{ article.title }}</h2>
{% if user.is_authenticated %}
<p>
<a href="{% url 'articles-detail' id=article.id %}">
Подробнее
</a>
</p>
{% endif %}
<br>
<hr>
<br>
......
......@@ -6,33 +6,63 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.1/css/bootstrap.min.css"
integrity="sha512-Ez0cGzNzHR1tYAv56860NLspgUGuQw16GiOOp/I2LuTmpSK9xDXlgJz3XN4cnpXWDmkNBKXR/VDMTCnAaEooxA=="
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' %}">
<title>Title</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<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">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse flex-grow-0" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{% url 'articles-add' %}">
Create
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
</ul>
<div class="container">
<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">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse flex-grow-0" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{% url 'articles-add' %}">
Create
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
{% if user.is_authenticated %}
<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>
</nav>
<div class="container">
{% block title %}{% endblock %}
......@@ -40,6 +70,8 @@
{% block content %}{% endblock %}
</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>
</html>
\ No newline at end of file
......@@ -2,8 +2,8 @@ from urllib.parse import urlencode
from django.urls import reverse, reverse_lazy
from django.db.models import Q
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import (
RedirectView,
ListView,
DetailView,
CreateView,
......@@ -60,7 +60,8 @@ class ArticleCreateView(CreateView):
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'
model = Article
context_object_name = 'article'
......@@ -74,7 +75,7 @@ class ArticleDetailView(DetailView):
)
class ArticleUpdateView(UpdateView):
class ArticleUpdateView(LoginRequiredMixin, UpdateView):
model = Article
template_name = 'article/update.html'
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