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

lesson 59

parent 34edf14d
from django.contrib import admin from django.contrib import admin
from accounts.models import User
# Register your models here.
admin.site.register(User)
...@@ -3,112 +3,139 @@ ...@@ -3,112 +3,139 @@
"model": "auth.group", "model": "auth.group",
"pk": 1, "pk": 1,
"fields": { "fields": {
"name": "moderators", "name": "Moderators",
"permissions": [ "permissions": [
[ [
"add_group", "change_article",
"auth", "webapp",
"group" "article"
], ],
[ [
"change_group", "view_article",
"auth", "webapp",
"group" "article"
], ],
[ [
"delete_group", "change_articletag",
"auth", "webapp",
"group" "articletag"
], ],
[ [
"view_group", "view_articletag",
"auth", "webapp",
"group" "articletag"
], ],
[ [
"add_permission", "change_comment",
"auth", "webapp",
"permission" "comment"
], ],
[ [
"change_permission", "view_comment",
"auth", "webapp",
"permission" "comment"
], ],
[ [
"delete_permission", "change_tag",
"auth", "webapp",
"permission" "tag"
],
[
"view_tag",
"webapp",
"tag"
] ]
] ]
} }
}, },
{ {
"model": "auth.user", "model": "accounts.user",
"pk": 1, "pk": 1,
"fields": { "fields": {
"password": "pbkdf2_sha256$260000$lq4ksTNG7r59t43pWudHUh$x7l77+SRwPzLJGjrmRiF7Q2f0ZoOsoa0M1jmnjaYOp4=", "password": "pbkdf2_sha256$260000$8UtRanhkO5mewMnDbwLFAG$I7SXHyc1AkRQ75IHXi7mCEs5rZ96WA/jtQPlwqPw4wU=",
"last_login": "2024-02-08T14:08:46.334Z", "last_login": "2024-02-26T14:40:30.384Z",
"is_superuser": true, "is_superuser": true,
"username": "admin", "username": "admin",
"first_name": "john", "first_name": "",
"last_name": "doe", "last_name": "",
"email": "admin@gmail.com", "email": "admin@gmail.com",
"is_staff": true, "is_staff": true,
"is_active": true, "is_active": true,
"date_joined": "2023-12-18T14:33:11Z", "date_joined": "2024-02-26T13:48:18Z",
"groups": [ "groups": [],
[
"moderators"
]
],
"user_permissions": [ "user_permissions": [
[ [
"add_logentry", "add_article",
"admin", "webapp",
"logentry" "article"
], ],
[ [
"change_logentry", "change_article",
"admin", "webapp",
"logentry" "article"
], ],
[ [
"delete_logentry", "delete_article",
"admin", "webapp",
"logentry" "article"
], ],
[ [
"view_logentry", "view_article",
"admin", "webapp",
"logentry" "article"
], ]
[ ]
"add_group", }
"auth", },
"group" {
], "model": "accounts.user",
[ "pk": 4,
"change_group", "fields": {
"auth", "password": "pbkdf2_sha256$260000$k60ituf6lev5ZiilBXiiOz$og/LlRwDzSHvn6NehUOb+mA4oySMvSHxnFahP3X+XVs=",
"group" "last_login": "2024-02-26T14:44:12.429Z",
], "is_superuser": false,
"username": "john",
"first_name": "john",
"last_name": "doe",
"email": "johndoe@gmail.com",
"is_staff": false,
"is_active": true,
"date_joined": "2024-02-26T14:07:22Z",
"groups": [
[ [
"delete_group", "Moderators"
"auth", ]
"group" ],
], "user_permissions": [
[ [
"view_group", "add_article",
"auth", "webapp",
"group" "article"
], ],
[ [
"add_permission", "delete_article",
"auth", "webapp",
"permission" "article"
] ]
] ]
} }
},
{
"model": "accounts.user",
"pk": 5,
"fields": {
"password": "pbkdf2_sha256$260000$TWe6vsT6TMp0WiTk2Y9iYp$8UztS9GRERsEgobGp04eXnH92vhPcEUqFc0MBKdWOEM=",
"last_login": "2024-02-26T14:47:09.814Z",
"is_superuser": false,
"username": "jane",
"first_name": "jane",
"last_name": "doe",
"email": "janedoe@gmail.com",
"is_staff": false,
"is_active": true,
"date_joined": "2024-02-26T14:07:36.807Z",
"groups": [],
"user_permissions": []
}
} }
] ]
...@@ -19,14 +19,19 @@ ...@@ -19,14 +19,19 @@
</ul> </ul>
<div class="d-flex"> <div class="d-flex">
<a href="{% url 'articles_update' id=article.id %}" class="btn btn-primary me-3">
Update {% if perms.webapp.change_article or article.author == user %}
</a> <a href="{% url 'articles_update' id=article.id %}" class="btn btn-primary me-3">
Update
<form action="{% url 'articles_delete' id=article.id %}" method="post" onsubmit="return confirm('Delete?')"> </a>
{% csrf_token %} {% endif %}
<button class="btn btn-danger">Delete</button>
</form> {% if perms.webapp.delete_article or article.author == user %}
<form action="{% url 'articles_delete' id=article.id %}" method="post" onsubmit="return confirm('Delete?')">
{% csrf_token %}
<button class="btn btn-danger">Delete</button>
</form>
{% endif %}
</div> </div>
<hr> <hr>
......
...@@ -18,10 +18,12 @@ ...@@ -18,10 +18,12 @@
</button> </button>
<div class="collapse navbar-collapse flex-grow-0" id="navbarNav"> <div class="collapse navbar-collapse flex-grow-0" id="navbarNav">
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item"> {% if perms.webapp.add_article %}
<a class="nav-link" aria-current="page" href="{% url 'articles_add' %}">Create</a> <li class="nav-item">
</li> <a class="nav-link" aria-current="page" href="{% url 'articles_add' %}">Create</a>
</li>
{% endif %}
<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">
......
...@@ -3,6 +3,7 @@ from webapp import models ...@@ -3,6 +3,7 @@ from webapp import models
admin.site.register(models.Comment) admin.site.register(models.Comment)
admin.site.register(models.Tag)
@admin.register(models.Article) @admin.register(models.Article)
......
...@@ -7,7 +7,7 @@ from webapp import models ...@@ -7,7 +7,7 @@ from webapp import models
class ArticleForm(forms.ModelForm): class ArticleForm(forms.ModelForm):
class Meta: class Meta:
model = models.Article model = models.Article
fields = ('title', 'text', 'author', 'tags') fields = ('title', 'text', 'tags')
widgets = { widgets = {
'title': widgets.TextInput(attrs={ 'title': widgets.TextInput(attrs={
...@@ -18,10 +18,6 @@ class ArticleForm(forms.ModelForm): ...@@ -18,10 +18,6 @@ class ArticleForm(forms.ModelForm):
'class': 'form-control mb-3', 'class': 'form-control mb-3',
'placeholder': 'Write some text', 'placeholder': 'Write some text',
}), }),
'author': widgets.TextInput(attrs={
'class': 'form-control mb-3',
'placeholder': 'Author',
}),
'tags': widgets.CheckboxSelectMultiple({ 'tags': widgets.CheckboxSelectMultiple({
'class': 'list-unstyled ps-0 mb-3', 'class': 'list-unstyled ps-0 mb-3',
}) })
...@@ -41,15 +37,11 @@ class SearchForm(forms.Form): ...@@ -41,15 +37,11 @@ class SearchForm(forms.Form):
class CommentForm(forms.ModelForm): class CommentForm(forms.ModelForm):
class Meta: class Meta:
model = models.Comment model = models.Comment
fields = ('text', 'author') fields = ('text',)
widgets = { widgets = {
'text': widgets.Textarea(attrs={ 'text': widgets.Textarea(attrs={
'class': 'form-control mb-3', 'class': 'form-control mb-3',
'placeholder': 'Write some text', 'placeholder': 'Write some text',
}), }),
'author': widgets.TextInput(attrs={
'class': 'form-control mb-3',
'placeholder': 'Author'
})
} }
# Generated by Django 3.2.19 on 2024-02-26 14:35
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('webapp', '0009_alter_article_title'),
]
operations = [
migrations.AlterField(
model_name='article',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='articles', to=settings.AUTH_USER_MODEL, verbose_name='Автор'),
),
]
# Generated by Django 3.2.19 on 2024-02-26 14:51
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('webapp', '0010_alter_article_author'),
]
operations = [
migrations.AlterModelOptions(
name='article',
options={'permissions': [('can_eat_pizza', 'Может съесть пиццу')], 'verbose_name': 'статья', 'verbose_name_plural': 'статьи'},
),
]
from django.db import models from django.db import models
from django.core.validators import MinLengthValidator from django.core.validators import MinLengthValidator
from django.contrib.auth import get_user_model
class Article(models.Model): class Article(models.Model):
title = models.CharField( title = models.CharField(
...@@ -11,9 +11,9 @@ class Article(models.Model): ...@@ -11,9 +11,9 @@ class Article(models.Model):
text = models.TextField( text = models.TextField(
null=False, blank=False, verbose_name='Текст', null=False, blank=False, verbose_name='Текст',
) )
author = models.CharField( author = models.ForeignKey(
max_length=40, null=False, blank=False, default='Неизвестный автор', get_user_model(), on_delete=models.CASCADE,
verbose_name='Автор', related_name='articles', verbose_name='Автор'
) )
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания') created_at = models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Дата обновления') updated_at = models.DateTimeField(auto_now=True, verbose_name='Дата обновления')
...@@ -24,6 +24,9 @@ class Article(models.Model): ...@@ -24,6 +24,9 @@ class Article(models.Model):
class Meta: class Meta:
verbose_name = 'статья' verbose_name = 'статья'
verbose_name_plural = 'статьи' verbose_name_plural = 'статьи'
permissions = [
('can_eat_pizza', 'Может съесть пиццу'),
]
def __str__(self): def __str__(self):
return f'{self.id} {self.title}' return f'{self.id} {self.title}'
......
...@@ -4,16 +4,18 @@ from django.http.response import HttpResponse as HttpResponse ...@@ -4,16 +4,18 @@ 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 django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin, UserPassesTestMixin
from django.core.exceptions import PermissionDenied
from webapp.forms import ArticleForm, CommentForm from webapp.forms import ArticleForm, CommentForm
from webapp.models import Article from webapp.models import Article
class ArticleDetailView(generic.DetailView): class ArticleDetailView(PermissionRequiredMixin, generic.DetailView):
pk_url_kwarg = 'id' pk_url_kwarg = 'id'
model = Article model = Article
template_name = 'articles/detail.html' template_name = 'articles/detail.html'
permission_required = 'webapp.can_eat_pizza'
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
comments = self.object.comments.order_by('-created_at') comments = self.object.comments.order_by('-created_at')
...@@ -24,71 +26,32 @@ class ArticleDetailView(generic.DetailView): ...@@ -24,71 +26,32 @@ class ArticleDetailView(generic.DetailView):
) )
class ArticleCreateView(LoginRequiredMixin, generic.CreateView): class ArticleCreateView(PermissionRequiredMixin, generic.CreateView):
model = Article model = Article
template_name = 'articles/article.html' template_name = 'articles/article.html'
form_class = ArticleForm form_class = ArticleForm
permission_required = 'webapp.add_article'
def get_success_url(self): permission_denied_message = 'У вас нет прав'
return reverse('articles_detail', kwargs={'id': self.object.id})
class UpdateView(generic.View):
template_name = None
model = None
form_class = None
context_object_name = None
pk_url_kwarg = None
success_url = None
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
form = self.form_class(instance=self.object)
return self.render_to_response(form=form)
def post(self, request, *args, **kwargs):
form = self.form_class(instance=self.object, data=request.POST)
if form.is_valid():
return self.form_valid(form)
return self.form_invalid(form)
def get_object(self):
return get_object_or_404(self.model, id=self.kwargs.get(self.pk_url_kwarg))
def get_context_data(self, **kwargs):
kwargs[self.context_object_name] = self.object
return kwargs
def get_success_url(self):
return self.success_url
def form_valid(self, form): def form_valid(self, form):
self.object = form.save() form.instance.author = self.request.user
return redirect(self.get_success_url()) return super().form_valid(form)
def form_invalid(self, form):
return self.render_to_response(form=form)
def render_to_response(self, **kwargs): def get_success_url(self):
return render( return reverse('articles_detail', kwargs={'id': self.object.id})
self.request,
self.template_name,
context=self.get_context_data(**kwargs),
)
class ArticleUpdateView(generic.UpdateView): class ArticleUpdateView(PermissionRequiredMixin, generic.UpdateView):
template_name = 'articles/article.html' template_name = 'articles/article.html'
model = Article model = Article
form_class = ArticleForm form_class = ArticleForm
context_object_name = 'article' context_object_name = 'article'
pk_url_kwarg = 'id' pk_url_kwarg = 'id'
extra_context = {'btn_text': 'Update'} extra_context = {'btn_text': 'Update'}
permission_required = 'webapp.change_article'
def has_permission(self) -> bool:
return super().has_permission() or self.get_object().author == self.request.user
def get_success_url(self): def get_success_url(self):
return reverse('articles_detail', kwargs={'id': self.object.id}) return reverse('articles_detail', kwargs={'id': self.object.id})
......
from django.shortcuts import redirect from django.shortcuts import redirect
from django.views import generic from django.views import generic
from django.urls import reverse from django.urls import reverse
from django.contrib.auth.mixins import LoginRequiredMixin
from webapp.models import Comment from webapp.models import Comment
from webapp.forms import CommentForm from webapp.forms import CommentForm
from webapp.views.articles import UpdateView, DeleteView
class CommentCreateView(generic.CreateView): class CommentCreateView(LoginRequiredMixin, generic.CreateView):
model = Comment model = Comment
template_name = 'comments/comment.html' template_name = 'comments/comment.html'
form_class = CommentForm form_class = CommentForm
...@@ -18,8 +18,9 @@ class CommentCreateView(generic.CreateView): ...@@ -18,8 +18,9 @@ class CommentCreateView(generic.CreateView):
comment = form.save(commit=False) comment = form.save(commit=False)
comment.article_id = article_id comment.article_id = article_id
comment.author = self.request.user
comment.save() comment.save()
return redirect('articles_detail', id=article_id) return redirect('articles_detail', id=article_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