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

lesson 57 + web 28

parent 3e240412
db.sqlite3
\ No newline at end of file
def some_decorator(func):
def wrapper(*args, **kwargs):
result = func()
return result ** 2
return wrapper
def calculate():
return 1 + 1
print(calculate())
@some_decorator
def calculate():
return 1 + 1
print(calculate())
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.db import models
# Create your models here.
from django.test import TestCase
# Create your tests here.
from django.urls import path
from django.contrib.auth.views import LoginView, LogoutView
urlpatterns = [
path('login', LoginView.as_view(template_name='auth/login.html'), name='login'),
path('logout', LogoutView.as_view(), name='logout'),
]
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
# YAGNI - you ain't gonna need it
# KISS - keep it simple stupid
@login_required
def login_view(request):
context = {}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user:
login(request, user)
return redirect('index')
context['has_errors'] = True
return render(request, 'auth/login.html', context=context)
def logout_view(request):
logout(request)
return redirect('index')
...@@ -39,6 +39,7 @@ INSTALLED_APPS = [ ...@@ -39,6 +39,7 @@ INSTALLED_APPS = [
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'webapp', 'webapp',
'accounts',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
...@@ -121,7 +122,7 @@ USE_TZ = True ...@@ -121,7 +122,7 @@ USE_TZ = True
# https://docs.djangoproject.com/en/3.2/howto/static-files/ # https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/' STATIC_URL = '/static/'
STATICFILES_DIRS = [ STATICFILES_DIRS = [
BASE_DIR / 'static' BASE_DIR / 'static'
] ]
...@@ -130,3 +131,7 @@ STATICFILES_DIRS = [ ...@@ -130,3 +131,7 @@ STATICFILES_DIRS = [
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGIN_REDIRECT_URL = LOGOUT_REDIRECT_URL = 'index'
LOGIN_URL = 'login'
...@@ -14,7 +14,7 @@ Including another URLconf ...@@ -14,7 +14,7 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
""" """
from django.contrib import admin from django.contrib import admin
from django.urls import path from django.urls import path, include
from webapp import views from webapp import views
...@@ -37,4 +37,6 @@ urlpatterns = [ ...@@ -37,4 +37,6 @@ urlpatterns = [
views.CommentDeleteView.as_view(), views.CommentDeleteView.as_view(),
name='comments_delete', name='comments_delete',
), ),
path('accounts/', include('accounts.urls')),
] ]
[
{
"model": "auth.group",
"pk": 1,
"fields": {
"name": "moderators",
"permissions": [
[
"add_group",
"auth",
"group"
],
[
"change_group",
"auth",
"group"
],
[
"delete_group",
"auth",
"group"
],
[
"view_group",
"auth",
"group"
],
[
"add_permission",
"auth",
"permission"
],
[
"change_permission",
"auth",
"permission"
],
[
"delete_permission",
"auth",
"permission"
]
]
}
},
{
"model": "auth.user",
"pk": 1,
"fields": {
"password": "pbkdf2_sha256$260000$lq4ksTNG7r59t43pWudHUh$x7l77+SRwPzLJGjrmRiF7Q2f0ZoOsoa0M1jmnjaYOp4=",
"last_login": "2024-02-08T14:08:46.334Z",
"is_superuser": true,
"username": "admin",
"first_name": "john",
"last_name": "doe",
"email": "admin@gmail.com",
"is_staff": true,
"is_active": true,
"date_joined": "2023-12-18T14:33:11Z",
"groups": [
[
"moderators"
]
],
"user_permissions": [
[
"add_logentry",
"admin",
"logentry"
],
[
"change_logentry",
"admin",
"logentry"
],
[
"delete_logentry",
"admin",
"logentry"
],
[
"view_logentry",
"admin",
"logentry"
],
[
"add_group",
"auth",
"group"
],
[
"change_group",
"auth",
"group"
],
[
"delete_group",
"auth",
"group"
],
[
"view_group",
"auth",
"group"
],
[
"add_permission",
"auth",
"permission"
]
]
}
}
]
...@@ -18,28 +18,34 @@ ...@@ -18,28 +18,34 @@
</ul> </ul>
<a href="{% url 'articles_update' id=article.id %}" class="btn btn-primary"> <div class="d-flex">
Update <a href="{% url 'articles_update' id=article.id %}" class="btn btn-primary me-3">
</a> Update
</a>
<form action="{% url 'articles_delete' id=article.id %}" method="post" onsubmit="return confirm('Delete?')">
{% csrf_token %} <form action="{% url 'articles_delete' id=article.id %}" method="post" onsubmit="return confirm('Delete?')">
<button class="btn btn-danger">Delete</button> {% csrf_token %}
</form> <button class="btn btn-danger">Delete</button>
</form>
</div>
<hr> <hr>
<h3 class="mb-4">Comments</h3> <h3 class="mb-4">Comments</h3>
{% url 'comments_add' article_id=article.id as comments_action_url %} <div class="w-50">
{% include 'partial/form.html' with form=comments_form request_method='post' action_url=comments_action_url %} {% url 'comments_add' article_id=article.id as comments_action_url %}
{% include 'partial/form.html' with form=comments_form request_method='post' action_url=comments_action_url %}
</div>
{% for comment in comments %} {% for comment in comments %}
<div class="card my-4"> <div class="card my-4">
<div class="card-header d-flex justify-content-between align-items-center"> <div class="card-header d-flex justify-content-between align-items-center">
<div class="">{{ comment.author }}</div> <div class="">{{ comment.author }}</div>
<div class="d-flex"> <div class="d-flex">
<a href="{% url 'comments_update' article_id=article.id comment_id=comment.id %}" class="btn btn-warning me-4"> <a href="{% url 'comments_update' article_id=article.id comment_id=comment.id %}" class="btn btn-warning me-4">
Update Update
</a> </a>
...@@ -49,7 +55,7 @@ ...@@ -49,7 +55,7 @@
<button class="btn btn-danger">Delete</button> <button class="btn btn-danger">Delete</button>
</form> </form>
</div> </div>
</div> </div>
...@@ -67,7 +73,7 @@ ...@@ -67,7 +73,7 @@
{% empty %} {% empty %}
<h5>No comments yet.</h5> <h5 class="my-5">No comments yet.</h5>
{% endfor %} {% endfor %}
......
{% extends 'base.html' %}
{% block content %}
<h1>Вход</h1>
<div class="d-flex justify-content-center">
{% 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>
{% endblock %}
...@@ -23,21 +23,26 @@ ...@@ -23,21 +23,26 @@
<a class="nav-link" aria-current="page" href="{% url 'articles_add' %}">Create</a> <a class="nav-link" aria-current="page" href="{% url 'articles_add' %}">Create</a>
</li> </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>
<li class="nav-item">
<a class="nav-link" href="#">Disabled</a>
</li>
</ul>
<form class="d-flex"> <form class="d-flex">
<input class="form-control me-2" name="search" type="search" placeholder="Search" aria-label="Search"> <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> <button class="btn btn-outline-success" type="submit">Search</button>
</form> </form>
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}">Logout</a>
</li>
<li class="nav-item">
<span class="nav-link fw-bold">Hello, {{ user.username }}</span>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Login</a>
</li>
{% endif %}
</ul>
</div> </div>
</div> </div>
</nav> </nav>
......
from django import forms from django import forms
from django.forms import ValidationError from django.forms import ValidationError, widgets
from webapp import models from webapp import models
...@@ -8,6 +8,24 @@ class ArticleForm(forms.ModelForm): ...@@ -8,6 +8,24 @@ class ArticleForm(forms.ModelForm):
class Meta: class Meta:
model = models.Article model = models.Article
fields = ('title', 'text', 'author', 'tags') fields = ('title', 'text', 'author', 'tags')
widgets = {
'title': widgets.TextInput(attrs={
'class': 'form-control mb-3',
'placeholder': 'Author',
}),
'text': widgets.Textarea(attrs={
'class': 'form-control mb-3',
'placeholder': 'Write some text',
}),
'author': widgets.TextInput(attrs={
'class': 'form-control mb-3',
'placeholder': 'Author',
}),
'tags': widgets.CheckboxSelectMultiple({
'class': 'list-unstyled ps-0 mb-3',
})
}
def clean(self): def clean(self):
if self.data['title'] == self.data['text']: if self.data['title'] == self.data['text']:
...@@ -24,3 +42,14 @@ class CommentForm(forms.ModelForm): ...@@ -24,3 +42,14 @@ class CommentForm(forms.ModelForm):
class Meta: class Meta:
model = models.Comment model = models.Comment
fields = ('text', 'author') fields = ('text', 'author')
widgets = {
'text': widgets.Textarea(attrs={
'class': 'form-control mb-3',
'placeholder': 'Write some text',
}),
'author': widgets.TextInput(attrs={
'class': 'form-control mb-3',
'placeholder': 'Author'
})
}
...@@ -4,6 +4,7 @@ from django.http.response import HttpResponse as HttpResponse ...@@ -4,6 +4,7 @@ from django.http.response import HttpResponse as HttpResponse
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.views import generic from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from webapp.forms import ArticleForm, CommentForm from webapp.forms import ArticleForm, CommentForm
from webapp.models import Article from webapp.models import Article
...@@ -23,7 +24,7 @@ class ArticleDetailView(generic.DetailView): ...@@ -23,7 +24,7 @@ class ArticleDetailView(generic.DetailView):
) )
class ArticleCreateView(generic.CreateView): class ArticleCreateView(LoginRequiredMixin, generic.CreateView):
model = Article model = Article
template_name = 'articles/article.html' template_name = 'articles/article.html'
form_class = ArticleForm form_class = ArticleForm
......
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