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

lesson 51

parent a8300edd
......@@ -22,11 +22,17 @@ from web import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.MainPageRedirectView.as_view()),
path('articles/', views.index_view, name='main_page'),
path('articles/', views.ArticleIndexView.as_view(), name='main_page'),
path('articles/add/', views.ArticleCreateView.as_view(), name='articles-add'),
# /articles/1/ OR /articles/?id=1
# article_details_view(request, id)
path('articles/<int:id>/', views.ArticleDetailView.as_view(), name='articles-detail'),
path('articles/<int:id>/edit', views.ArticleUpdateView.as_view(), name='article_update'),
path('articles/<int:id>/delete', views.delete_article, name='delete_article')
path(
'articles/<int:article_id>/comments/',
views.ArticleCommentCreateView.as_view(),
name='article_comment_create'
),
path('articles/<int:id>/delete', views.ArticleDeleteView.as_view(), name='delete_article')
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
......@@ -2,7 +2,7 @@ from django import forms
from django.forms import widgets, ValidationError
from core.validators import at_least_5
from web.models import Article
from web.models import Article, Comment
class ArticleForm(forms.Form):
......@@ -30,3 +30,25 @@ class ArticleModelForm(forms.ModelForm):
raise ValidationError('Text of the article should not duplicate it\'s title')
return cleaned_data
class ArticleCommentModelForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['author', 'text']
widgets = {
'text': forms.TextInput(attrs={'class': 'form-control mb-3'}),
'author': forms.TextInput(attrs={'class': 'form-control mb-3'}),
}
class SearchForm(forms.Form):
search = forms.CharField(
max_length=100,
required=False,
label='Найти',
widget=forms.TextInput(attrs={
'class': 'form-control my-3',
'placeholder': 'enter search value'
})
)
from django.db import models
# article_1 - (comment_1, comment_2)
# comment_1 = comment_1.article
# comment_1 = comment_1.article_id
# article_1 = article_1.comment.all()
class Comment(models.Model):
# article - object
# article_id - id
article = models.ForeignKey(
'web.Article',
on_delete=models.CASCADE,
......
......@@ -26,5 +26,31 @@
<hr>
<a href="{% url 'article_update' article.pk %}" class="btn btn-primary mt-4 me-3">Edit</a>
<a href="{% url 'delete_article' article.pk %}" class="btn btn-danger mt-4">Delete</a>
<form action="{% url 'delete_article' article.pk %}" method="POST" onsubmit="confirm('Are you sure?')">
{% csrf_token %}
<button class="btn btn-danger mt-4">Delete</button>
</form>
<h3 class="mt-4">Comments:</h3>
<div class="comments-list">
<form action="{% url 'article_comment_create' article_id=article.id %}" method="POST">
{% csrf_token %}
{% include 'partial/form.html' with button_text='add' %}
</form>
{% for comment in comments %}
<div class="card my-3">
<div class="card-header">
{{ comment.author }}
</div>
<div class="card-body">
<blockquote class="blockquote mb-0">
<p>{{ comment.text }}</p>
<footer class="blockquote-footer"><cite title="Source Title">{{ comment.created_at }}</cite></footer>
</blockquote>
</div>
</div>
{% empty %}
<p>No comments yet.</p>
{% endfor %}
</div>
{% endblock %}
......@@ -3,20 +3,25 @@
{% block content %}
<h1>Articles</h1>
<a href="{% url 'articles-add' %}" class="btn btn-primary">Создать</a>
{% for article in articles %}
<br>
<hr>
<br>
<h2>{{ article.title }}</h2>
<p>
<a href="{% url 'articles-detail' id=article.id %}">
Подробнее
</a>
</p>
<br>
<hr>
<br>
{% endfor %}
{% endblock %}
\ No newline at end of file
<h1>Articles</h1>
<a href="{% url 'articles-add' %}" class="btn btn-primary">Создать</a>
{% include 'partial/search_form.html' %}
{% for article in articles %}
<br>
<hr>
<br>
<h2>{{ article.title }}</h2>
<p>
<a href="{% url 'articles-detail' id=article.id %}">
Подробнее
</a>
</p>
<br>
<hr>
<br>
{% endfor %}
{% if is_paginated %}
{% include 'partial/pagination.html' %}
{% endif %}
{% endblock %}
<div class="d-flex justify-content-center ">
<nav aria-label="...">
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?{% if query %}{{ query }}&{% 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 %}
<li class="
page-item
{% if page_obj.number == num %}
active
{% else %}
{% endif %}
">
<a class="page-link" href="?{% if query %}{{ query }}&{% endif %}page={{ num }}">
{{ num }}
</a>
</li>
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?{% if query %}{{ query }}&{% 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 action="" method="GET">
<label for="{{ form.search.id_for_label }}"></label>
{{ form.search }}
<button type="submit" class="btn btn-success">Submit</button>
{% for error in form.search.errors %}
<div class="alert alert-danger">{{ error }}</div>
{% endfor %}
</form>
\ No newline at end of file
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse
from django.views.generic import View, TemplateView, RedirectView, FormView
from web.forms import ArticleForm, ArticleModelForm
from web.models import Article, StatusChoices
def index_view(request):
return render(
request, 'index.html', context={
'articles': Article.objects.order_by('-created_at'),
'reverse': reverse('articles-detail', kwargs={'id': 1})
}
)
from urllib.parse import urlencode
from django.shortcuts import get_object_or_404
from django.urls import reverse, reverse_lazy
from django.db.models import Q
from django.views.generic import (
RedirectView,
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
from web.forms import ArticleModelForm, SearchForm, ArticleCommentModelForm
from web.models import Article, Comment
class ArticleIndexView(ListView):
template_name = 'index.html'
context_object_name = 'articles'
model = Article
ordering = ['-created_at']
paginate_by = 3
def dispatch(self, request, *args, **kwargs):
self.form = self.get_search_form()
self.search_value = self.get_search_value()
return super().dispatch(request, *args, **kwargs)
class MainPageRedirectView(RedirectView):
pattern_name = 'main_page'
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = self.form
if self.search_value:
context['query'] = urlencode({'search': self.search_value})
# Class-based views
class ArticleCreateView(View):
def get(self, request, *args, **kwargs):
form = ArticleModelForm()
return render(
self.request,
'article_create.html',
context={
'status_choices': StatusChoices.choices,
'form': form
}
)
return context
def post(self, request, *args, **kwargs):
errors = {}
data = request.POST
form = ArticleModelForm(data=data)
if form.is_valid():
article = form.save()
return redirect('articles-detail', id=article.id)
else:
return render(self.request, 'article_create.html', context={'form': form, 'status_choices': StatusChoices.choices})
def get_queryset(self):
qs = super().get_queryset()
if self.search_value:
query = Q(title__icontains=self.search_value) | Q(author__icontains=self.search_value)
qs = qs.filter(query)
return qs
# /articles/{id}
def article_detail_view(request, id: int):
article = get_object_or_404(Article, id=id)
return render(request, 'article_detail.html', context={'article': article})
def get_search_form(self):
return SearchForm(self.request.GET)
def get_search_value(self):
if self.form.is_valid():
return self.form.cleaned_data.get('search')
class ArticleDetailView(TemplateView):
template_name = 'article_detail.html'
def get_context_data(self, **kwargs):
article = get_object_or_404(Article, id=kwargs.get('id'))
return super().get_context_data(article=article)
class MainPageRedirectView(RedirectView):
pattern_name = 'main_page'
class ArticleUpdateView(FormView):
template_name = 'update.html'
class ArticleCreateView(CreateView):
template_name = 'article_create.html'
model = Article
form_class = ArticleModelForm
def dispatch(self, request, *args, **kwargs):
self.article = get_object_or_404(self.form_class.Meta.model, id=kwargs.get('id'))
return super().dispatch(request, *args, **kwargs)
def get_success_url(self):
return reverse('articles-detail', kwargs={'id': self.object.id})
def get_context_data(self, **kwargs):
return super().get_context_data(article=self.article, **kwargs)
def get_initial(self):
initial = self.article.__dict__
initial['tags'] = self.article.tags.all()
return initial
class ArticleCommentCreateView(CreateView):
model = Comment
form_class = ArticleCommentModelForm
def get_form_kwargs(self):
return super().get_form_kwargs() | {'instance': self.article}
def dispatch(self, request, *args, **kwargs):
self.article = get_object_or_404(Article, id=self.kwargs.get('article_id'))
return super().dispatch(request, *args, **kwargs)
def form_valid(self, form):
form.save()
form.instance.article = self.article
return super().form_valid(form)
def get_success_url(self):
return reverse('articles-detail', kwargs={'id': self.article.id})
def article_update_view(request, id):
article = get_object_or_404(Article, pk=id)
if request.method == 'GET':
form = ArticleForm(initial={
'title': article.title,
'status': article.status,
'author': article.author,
'text': article.text
})
return render(request, 'update.html', context={'article': article, 'form': form, 'status_choices': StatusChoices.choices})
elif request.method == 'POST':
form = ArticleForm(data=request.POST)
if form.is_valid():
article.title = request.POST.get('title')
article.author = request.POST.get('author')
article.text = request.POST.get('text')
article.status = request.POST.get('status')
article.save()
return redirect('articles-detail', id=article.pk)
else:
return render(request, 'update.html', context={'article': article, 'form': form, 'status_choices': StatusChoices.choices})
def delete_article(request, id):
article = get_object_or_404(Article, pk=id)
if request.method == 'GET':
return render(request, 'delete.html', context={'article': article})
elif request.method == 'POST':
article.delete()
return redirect('main_page')
class ArticleDetailView(DetailView):
template_name = 'article_detail.html'
model = Article
context_object_name = 'article'
pk_url_kwarg = 'id'
extra_context = {'form': ArticleCommentModelForm}
def get_context_data(self, **kwargs):
return super().get_context_data(
comments=self.object.comments.order_by('-created_at'),
**kwargs
)
class ArticleUpdateView(UpdateView):
model = Article
template_name = 'update.html'
form_class = ArticleModelForm
context_object_name = 'article'
pk_url_kwarg = 'id'
def get_success_url(self):
return reverse('articles-detail', kwargs={'id': self.object.id})
class ArticleDeleteView(DeleteView):
model = Article
template_name = 'delete.html'
context_object_name = 'article'
success_url = reverse_lazy('main_page')
pk_url_kwarg = 'id'
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