asdfasdf

parent 101e26bc
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.shortcuts import render
# Create your views here.
from django.core.checks import Tags
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms.models import ModelForm from django.forms.models import ModelForm, ModelChoiceField
from django.forms import CharField, Form from django.forms import CharField, Form, ModelMultipleChoiceField
from articles.models import Article, Author, Comment from articles.models import Article, Author, Comment, Tag
def at_least_10(string): def at_least_10(string):
...@@ -24,10 +25,16 @@ class CommentForm(ModelForm): ...@@ -24,10 +25,16 @@ class CommentForm(ModelForm):
fields = ("text", "author") fields = ("text", "author")
class ArticleForm(ModelForm): class ArticleForm(Form):
class Meta: __model = Article
model = Article title = CharField()
fields = "__all__" body = CharField()
author = ModelChoiceField(queryset=Author.objects.all())
tags = ModelMultipleChoiceField(queryset=Tag.objects.all())
# class Meta:
# model = Article
# fields = "__all__"
class SearchForm(Form): class SearchForm(Form):
......
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
from django.views import View from django.views import View
from django.views.generic import TemplateView, ListView from django.views.generic import TemplateView
from django.views.generic.base import ContextMixin
from articles.forms import AuthorForm
class CustomFormView(View):
class ParamMixin:
form_class = None form_class = None
template_name = None template_name = None
redirect_url = '' redirect_url = ''
model = None
key_kwarg = 'pk'
context_object_name = 'objects'
object = None
kwargs = None
def get_object(self):
pk = self.kwargs.get(self.key_kwarg)
return get_object_or_404(self.model, pk=pk)
def get_redirect_url(self):
return self.redirect_url
class CustomFormView(View, ParamMixin):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
form = self.form_class() form = self.form_class()
...@@ -36,9 +51,7 @@ class CustomFormView(View): ...@@ -36,9 +51,7 @@ class CustomFormView(View):
return kwargs return kwargs
class ListView(TemplateView): class ListView(TemplateView, ParamMixin):
model = None
context_object_name = 'objects'
paginate_by = 5 paginate_by = 5
paginate_orphans = 0 paginate_orphans = 0
ordering = [] ordering = []
...@@ -66,10 +79,7 @@ class ListView(TemplateView): ...@@ -66,10 +79,7 @@ class ListView(TemplateView):
return self.model.objects.all() return self.model.objects.all()
class DetailView(TemplateView): class DetailView(TemplateView, ParamMixin):
context_object_name = 'objects'
model = None
key_kwarg = 'pk'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
...@@ -81,12 +91,7 @@ class DetailView(TemplateView): ...@@ -81,12 +91,7 @@ class DetailView(TemplateView):
return get_object_or_404(self.model, pk=pk) return get_object_or_404(self.model, pk=pk)
class CreateView(View): class CreateView(View, ParamMixin):
form_class = None
template_name = None
model = None
redirect_url = None
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
form = self.form_class() form = self.form_class()
context = {'form': form} context = {'form': form}
...@@ -94,6 +99,7 @@ class CreateView(View): ...@@ -94,6 +99,7 @@ class CreateView(View):
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.form_class(data=request.POST) form = self.form_class(data=request.POST)
if form.is_valid(): if form.is_valid():
return self.form_valid(form) return self.form_valid(form)
else: else:
...@@ -108,4 +114,63 @@ class CreateView(View): ...@@ -108,4 +114,63 @@ class CreateView(View):
return render(request=self.request, template_name=self.template_name, context=context) return render(request=self.request, template_name=self.template_name, context=context)
def get_redirect_url(self): def get_redirect_url(self):
return self.redirect_url return self.redirect_url
\ No newline at end of file
class UpdateView(View, ParamMixin):
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object)
context = self.get_context_data(form=form)
return render(request, self.template_name, context=context)
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(instance=self.object, data=request.POST)
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
self.object = form.save()
return redirect(self.get_redirect_url())
def form_invalid(self, form):
context = self.get_context_data(form=form)
return render(self.request, self.template_name, context=context)
def get_context_data(self, **kwargs):
context = self.kwargs.copy()
context[self.context_object_name] = self.object
context.update(kwargs)
return context
def get_object(self):
pk = self.kwargs.get(self.key_kwarg)
return get_object_or_404(self.model, pk=pk)
class DeleteView(View, ParamMixin):
confirm_deletion = True
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if self.confirm_deletion:
return render(request, self.template_name, self.get_context_data())
else:
self.perform_delete()
return redirect(self.get_redirect_url())
def post(self, request, *args, **kwargs):
self.object = self.get_object()
self.perform_delete()
return redirect(self.get_redirect_url())
def perform_delete(self):
self.object.delete()
def get_context_data(self, **kwargs):
return {
self.context_object_name: self.object
}
{% extends 'base.html' %}
{% block content %}
<div class="container">
<p>Действительно ли вы хотите удалить запись "{{ article.title }}"</p>
<form action="{% url 'article_delete' article.pk %}" method="post">
{% csrf_token %}
<input type="submit" value="Подтвердить">
</form>
</div>
{% endblock %}
\ No newline at end of file
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
<li>Автор: {{comment.author}} </li> <li>Автор: {{comment.author}} </li>
<li>Текст: {{comment.text}} </li> <li>Текст: {{comment.text}} </li>
<li>Дата создания: {{comment.created_at}} </li> <li>Дата создания: {{comment.created_at}} </li>
<li>
<a class="btn btn-info btn-sm" href="{% url 'update_comment' comment.pk %}">Изменить</a>
</li>
<hr> <hr>
{% endfor %} {% endfor %}
</ul> </ul>
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
<th scope="col">Title</th> <th scope="col">Title</th>
<th scope="col">Author</th> <th scope="col">Author</th>
<th scope="col">Date</th> <th scope="col">Date</th>
<th scope="col">Action</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
...@@ -22,6 +23,7 @@ ...@@ -22,6 +23,7 @@
<td><a href="{% url 'article_detail' article.pk %}">{{ article.title }}</a></td> <td><a href="{% url 'article_detail' article.pk %}">{{ article.title }}</a></td>
<td>{{ article.author.name }}</td> <td>{{ article.author.name }}</td>
<td>{{ article.created_at|date:"d M Y" }}</td> <td>{{ article.created_at|date:"d M Y" }}</td>
<td><a class="btn btn-danger btn-sm" href="{% url "article_delete" article.pk %}">Удалить</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
......
...@@ -4,26 +4,8 @@ ...@@ -4,26 +4,8 @@
<div class="container"> <div class="container">
<form action="{% url 'article_update' article.pk %}" method="POST"> <form action="{% url 'article_update' article.pk %}" method="POST">
{% csrf_token %} {% csrf_token %}
<div class="col-md-6">
<label for="title" class="form-label">Название: </label>
<input type="text" name="title" class="form-control" id="title">
</div>
<div class="col-md-6">
<label for="body" class="form-label">Тело статьи: </label>
<textarea name="body" id="body" cols="30" rows="20"></textarea>
</div>
<div class="col-md-6">
<label for="author" class="form-label">Автор: </label>
{{ form.author }}
</div>
<div class="col-md-6">
<label for="tags" class="form-label">Теги: </label>
<select name="tags" id="tags" multiple>
{{ form.tags }}
</select>
</div>
{{ form.as_p }} {{ form.as_p }}
<input type="submit" value="create"> <input type="submit" value="update">
</form> </form>
</div> </div>
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<form action="{% url 'author_create' %}" method="POST"> <form action="{% url 'author_create' %}" method="POST">
{% csrf_token %} {% csrf_token %}
<div class="mb-3"> <div class="mb-3">
{{ form.errors }}
<label for="formGroupExampleInput" class="form-label">{{ form.name.label }}</label> <label for="formGroupExampleInput" class="form-label">{{ form.name.label }}</label>
<input type="text" class="form-control" name="{{ form.name.name }}" id="formGroupExampleInput" placeholder="Введите имя автора"> <input type="text" class="form-control" name="{{ form.name.name }}" id="formGroupExampleInput" placeholder="Введите имя автора">
</div> </div>
......
{% load static %}
<!doctype html> <!doctype html>
<html lang="en"> <html lang="en">
<head> <head>
...@@ -6,6 +7,7 @@ ...@@ -6,6 +7,7 @@
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<link rel="stylesheet" href="{% static 'style.css' %}">
<title>Document</title> <title>Document</title>
</head> </head>
<body> <body>
......
{% extends 'base.html' %}
{% block content %}
<div class="container">
<form action="{% url 'update_comment' comment.id %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Edit">
</form>
</div>
{% endblock %}
\ No newline at end of file
<h1>Not Found</h1>
{{ message }}
\ No newline at end of file
from django.urls import path from django.urls import path
from .views import ( from .views.article_views import (
ArticleListView, ArticleDeleteView,
ArticleUpdateView,
ArticleCreateView,
ArticleDetailView, ArticleDetailView,
author_edit_view, author_delete_view, AuthorView, CreateArticleView, ArticleUpdateView, AuthorListView, ArticleListView
ArticleCommentCreateView
) )
urlpatterns = [ from .views.comment_views import (
CommentCreateView,
CommentUpdateView
)
from .views.author_views import (
AuthorUpdateView,
AuthorListView,
AuthorDeleteView,
AuthorCreateView
)
comments_routes = [
path('articles/<int:pk>/comment/add',
CommentCreateView.as_view(),
name='create_comment'
),
path('articles/<int:pk>/comment/update',
CommentUpdateView.as_view(),
name='update_comment'
),
]
articles_routes = [
path( path(
'', '',
ArticleListView.as_view(), ArticleListView.as_view(),
...@@ -17,13 +41,9 @@ urlpatterns = [ ...@@ -17,13 +41,9 @@ urlpatterns = [
ArticleDetailView.as_view(), ArticleDetailView.as_view(),
name="article_detail" name="article_detail"
), ),
path('articles/<int:pk>/comment/add',
ArticleCommentCreateView.as_view(),
name='create_comment'
),
path( path(
'article/create', 'article/create',
CreateArticleView.as_view(), ArticleCreateView.as_view(),
name='article_create' name='article_create'
), ),
path( path(
...@@ -31,11 +51,21 @@ urlpatterns = [ ...@@ -31,11 +51,21 @@ urlpatterns = [
ArticleUpdateView.as_view(), ArticleUpdateView.as_view(),
name='article_update' name='article_update'
), ),
path(
'article/<int:pk>/delete',
ArticleDeleteView.as_view(),
name='article_delete'
),
]
author_routes = [
path( path(
'create/', 'create/',
AuthorView.as_view(), AuthorCreateView.as_view(),
name="author_create" name="author_create"
), ),
path( path(
'authors/', 'authors/',
AuthorListView.as_view(), AuthorListView.as_view(),
...@@ -44,13 +74,17 @@ urlpatterns = [ ...@@ -44,13 +74,17 @@ urlpatterns = [
path( path(
'author/<int:pk>/update/', 'author/<int:pk>/update/',
author_edit_view, AuthorUpdateView.as_view(),
name="author_update" name="author_update"
), ),
path( path(
'author/<int:pk>/delete/', 'author/<int:pk>/delete/',
author_delete_view, AuthorDeleteView.as_view(),
name="author_delete" name="author_delete"
) )
] ]
urlpatterns = comments_routes
urlpatterns += author_routes
urlpatterns += articles_routes
from urllib.parse import urlencode
from django.db.models import Q from django.db.models import Q
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import get_object_or_404, render
from django.template.defaultfilters import urlencode
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.views import View from django.views.generic import FormView, DeleteView
from django.views.generic import FormView, DetailView
from .helpers.views import CustomFormView, ListView, CreateView
from articles.models import Article, Author, Comment from articles.forms import SearchForm, ArticleForm, CommentForm
from .forms import AuthorForm, CommentForm, ArticleForm, SearchForm from articles.helpers.views import ListView, CreateView, DetailView, UpdateView
from articles.models import Article
class ArticleListView(ListView): class ArticleListView(ListView):
...@@ -51,15 +50,7 @@ class ArticleListView(ListView): ...@@ -51,15 +50,7 @@ class ArticleListView(ListView):
return queryset return queryset
class AuthorListView(ListView): class ArticleCreateView(CreateView):
template_name = 'authors/list.html'
model = Author
context_object_name = 'authors'
ordering = ['name']
paginate_by = 5
class CreateArticleView(CreateView):
template_name = 'articles/create.html' template_name = 'articles/create.html'
form_class = ArticleForm form_class = ArticleForm
model = Article model = Article
...@@ -68,73 +59,16 @@ class CreateArticleView(CreateView): ...@@ -68,73 +59,16 @@ class CreateArticleView(CreateView):
return reverse('article_detail', kwargs={'pk': self.object.pk}) return reverse('article_detail', kwargs={'pk': self.object.pk})
class ArticleCommentCreateView(CreateView): class ArticleUpdateView(UpdateView):
model = Comment model = Article
form_class = CommentForm
template_name = 'articles/create.html'
def form_valid(self, form):
article = get_object_or_404(Article, pk=self.kwargs.get('pk'))
form.instance.article = article
return super().form_valid(form)
def get_redirect_url(self):
return reverse('article_detail', kwargs={'pk': self.object.article.pk})
class ArticleUpdateView(FormView):
template_name = "articles/update.html" template_name = "articles/update.html"
form_class = ArticleForm form_class = ArticleForm
context_object_name = 'article'
def dispatch(self, request, *args, **kwargs): def get_redirect_url(self):
self.article = self.get_object() return reverse('article_detail', kwargs={
return super().dispatch(request, *args, **kwargs) 'pk': self.object.pk
})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['article'] = self.article
return context
def get_initial(self):
initial = {}
for key in 'title', 'body', 'author', 'tags':
initial[key] = getattr(self.article, key)
initial['tags'] = self.article.tags.all()
return initial
def form_valid(self, form):
tags = form.cleaned_data.pop('tags')
for key, value in form.cleaned_data.items():
if value is not None:
setattr(self.article, key, value)
self.article.save()
self.article.tags.set(tags)
return super().form_valid(form=form)
def get_success_url(self):
return reverse('article_detail', kwargs={'pk': self.article.pk})
def get_object(self):
pk = self.kwargs.get('pk')
return get_object_or_404(Article, pk=pk)
class AuthorView(View):
url_pattern = 'authors/create.html'
def get(self, request, *args, **kwargs):
form = AuthorForm()
return render(
request,
self.url_pattern,
context={'form': form})
def post(self, request, *args, **kwargs):
form = AuthorForm(request.POST)
if form.is_valid():
form.save()
return redirect('author_list')
class ArticleDetailView(DetailView): class ArticleDetailView(DetailView):
...@@ -148,52 +82,12 @@ class ArticleDetailView(DetailView): ...@@ -148,52 +82,12 @@ class ArticleDetailView(DetailView):
return render(request=request, template_name=self.template_name, context=context) return render(request=request, template_name=self.template_name, context=context)
class CommentView(View): class ArticleDeleteView(DeleteView):
def post(self, request, *args, **kwargs): template_name = 'articles/delete.html'
form = CommentForm(request.POST) model = Article
article_pk = kwargs.get('article_pk') context_object_name = 'article'
if form.is_valid(): confirm_deletion = False
article = get_object_or_404(Article, pk=article_pk) success_url = reverse_lazy('article_list')
article.comments.create(
text=request.POST.get("text"), def get(self, request, *args, **kwargs):
author=request.POST.get("author") return self.delete(request, *args, **kwargs)
) \ No newline at end of file
return redirect('article_detail', article_pk)
def create_author_view(request):
if request.method == "GET":
form = AuthorForm()
return render(
request,
'authors/create.html',
context={'form': form})
if request.method == "POST":
form = AuthorForm(request.POST)
if form.is_valid():
form.save()
return redirect('author_list')
def author_edit_view(request, pk):
author = get_object_or_404(Author, pk=pk)
if request.method == "GET":
form = AuthorForm(instance=author)
return render(
request,
'authors/update.html',
context={'form': form, "pk": pk})
if request.method == "POST":
form = AuthorForm(request.POST)
if form.is_valid():
author.name = request.POST.get("name")
author.save(update_fields=['name', ])
return redirect('author_list')
def author_delete_view(request, pk):
if request.method == "GET":
author = get_object_or_404(Author, pk=pk)
author.delete()
return redirect('author_list')
from django.urls import reverse, reverse_lazy
from articles.forms import AuthorForm
from articles.helpers.views import ListView, CreateView, UpdateView, DeleteView
from articles.models import Author
class AuthorListView(ListView):
template_name = 'authors/list.html'
model = Author
context_object_name = 'authors'
ordering = ['name']
paginate_by = 5
class AuthorCreateView(CreateView):
template_name = 'authors/create.html'
model = Author
form_class = AuthorForm
redirect_url = reverse_lazy('author_list')
class AuthorUpdateView(UpdateView):
template_name = 'authors/update.html'
model = Author
form_class = AuthorForm
redirect_url = reverse_lazy('author_list')
class AuthorDeleteView(DeleteView):
model = Author
confirm_deletion = False
redirect_url = reverse_lazy('author_list')
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse
from django.views import View
from articles.forms import CommentForm
from articles.helpers.views import CreateView, UpdateView
from articles.models import Comment, Article
class CommentCreateView(CreateView):
model = Comment
form_class = CommentForm
template_name = 'articles/create.html'
def form_valid(self, form):
article = get_object_or_404(Article, pk=self.kwargs.get('pk'))
form.instance.article = article
return super().form_valid(form)
def get_redirect_url(self):
return reverse('article_detail', kwargs={'pk': self.object.article.pk})
class CommentDetailView(View):
def post(self, request, *args, **kwargs):
form = CommentForm(request.POST)
article_pk = kwargs.get('article_pk')
if form.is_valid():
article = get_object_or_404(Article, pk=article_pk)
article.comments.create(
text=request.POST.get("text"),
author=request.POST.get("author")
)
return redirect('article_detail', article_pk)
class CommentUpdateView(UpdateView):
model = Comment
template_name = 'comments/update.html'
form_class = CommentForm
context_object_name = 'comment'
def get_redirect_url(self):
return reverse('article_detail', kwargs={
'pk': self.object.article.pk
})
from django.shortcuts import render
def error_404(request, exception):
return render(
request=request,
template_name='errors/404.html',
context={'message': exception}
)
\ No newline at end of file
...@@ -9,7 +9,7 @@ https://docs.djangoproject.com/en/3.2/topics/settings/ ...@@ -9,7 +9,7 @@ https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/ https://docs.djangoproject.com/en/3.2/ref/settings/
""" """
import os
from pathlib import Path from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
...@@ -23,9 +23,9 @@ BASE_DIR = Path(__file__).resolve().parent.parent ...@@ -23,9 +23,9 @@ BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = 'django-insecure-wse7x-3t6%mo#l9t3r_c2_5ek_c$npk1lj31!*(lt9xtq!t5ea' SECRET_KEY = 'django-insecure-wse7x-3t6%mo#l9t3r_c2_5ek_c$npk1lj31!*(lt9xtq!t5ea'
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = False
ALLOWED_HOSTS = [] ALLOWED_HOSTS = ['*']
# Application definition # Application definition
...@@ -48,6 +48,7 @@ MIDDLEWARE = [ ...@@ -48,6 +48,7 @@ MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
] ]
ROOT_URLCONF = 'core.urls' ROOT_URLCONF = 'core.urls'
...@@ -120,6 +121,13 @@ USE_TZ = True ...@@ -120,6 +121,13 @@ USE_TZ = True
STATIC_URL = '/static/' STATIC_URL = '/static/'
if not DEBUG:
STATIC_ROOT = 'static'
else:
STATICFILES_DIRS = [
BASE_DIR / "static",
]
# Default primary key field type # Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
......
...@@ -15,6 +15,9 @@ Including another URLconf ...@@ -15,6 +15,9 @@ 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 core.error import error_404
handler404 = error_404
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
......
body {
background: aqua;
}
\ No newline at end of file
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