---
# System prepended metadata

title: Тема 11. Разрешения и авторизация. Комментарии
tags: [Python Web]

---

---
tags: Python Web
source: Django 2.0 для начинающих, Глава 13-15, с.310
---

# Тема 11. Разрешения и авторизация. Комментарии

https://github.com/roman-yatsenko/django-topics/tree/main/news

## Создание страницы

### `articles\views.py`

```python=
from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView, DeleteView, CreateView # update
from django.urls import reverse_lazy

from . import models

# new
class ArticleCreateView(CreateView): 
    model = models.Article
    template_name = 'article_new.html'
    fields = ['title', 'body', 'author']
```

### `articles\urls.py`

```python=5
urlpatterns = [
    path('', views.ArticleListView.as_view(), name='article_list'),
    path('<int:pk>/edit/',
         views.ArticleUpdateView.as_view(), name='article_edit'), 
    path('<int:pk>/',
         views.ArticleDetailView.as_view(), name='article_detail'), 
    path('<int:pk>/delete/',
         views.ArticleDeleteView.as_view(), name='article_delete'), 
    path('new/', views.ArticleCreateView.as_view(), name='article_new'), # new 
]
```

```shell
touch templates/article_new.html
```

### `templates\article_new.html`

```htmlmixed=
{% extends 'base.html' %}

{% block content %}
<h1>New article</h1>
<form action="" method="post">
  {% csrf_token %}
  {{ form.as_p }}
<button class="btn btn-success ml-2" type="submit">Save</button>
</form>
{% endblock %}
```

### `templates\base.html`

```htmlmixed=15
      <a class="navbar-brand" href="{% url 'home' %}">Newspaper</a>

      {% if user.is_authenticated %}
        <ul class="navbar-nav mr-auto">
          <li class="nav-item"><a href="{% url 'article_new' %}">+ New</a></li>
        </ul>
      {% endif %}
```

```shell
python manage.py runserver
```

:link: https://getbootstrap.com/docs/4.0/components/jumbotron/

### `templates\home.html`

```htmlmixed=5
{% block content %}
<div class="jumbotron">
  <h1 class="display-4">Newspaper app</h1>
  <p class="lead">A Newspaper website built with Django.</p>
  <p class="lead">
    <a class="btn btn-primary btn-lg" href="{% url 'article_list' %}" 
    role="button">View All Articles</a>
  </p>
</div>
{% endblock %}
```

## Улучшение CreateView

### `articles\views.py`

```python=8
class ArticleCreateView(CreateView):
    model = models.Article
    template_name = 'article_new.html'
    fields = ['title', 'body', ] # update

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)
```

## Авторизация

Log out and go to http://127.0.0.1:8000/articles/new/

### `articles\views.py`

```python=4
from django.contrib.auth.mixins import LoginRequiredMixin # new

from . import models


class ArticleCreateView(LoginRequiredMixin, CreateView): # update
```

:link: http://127.0.0.1:8000/articles/new/

```python=10
    model = models.Article
    template_name = 'article_new.html'
    fields = ['title', 'body', ] 
    login_url = 'login' # new
```

## Обновление views

### `articles\views.py`

```python=20
class ArticleListView(LoginRequiredMixin, ListView): # update
    model = models.Article
    template_name = 'article_list.html'
    login_url = 'login' # new


class ArticleDetailView(LoginRequiredMixin, DetailView): # update
    model = models.Article
    template_name = 'article_detail.html'
    login_url = 'login' # new


class ArticleUpdateView(LoginRequiredMixin, UpdateView): # update
    model = models.Article
    fields = ['title', 'body', ]
    template_name = 'article_edit.html'
    login_url = 'login' # new


class ArticleDeleteView(LoginRequiredMixin, DeleteView): # update
    model = models.Article
    template_name = 'article_delete.html'
    success_url = reverse_lazy('article_list')
    login_url = 'login' # new
```

## Комментарии

### `articles\models.py`

```python=22
class Comment(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE)
    comment = models.CharField(max_length=140)
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    
    def __str__(self):
        return self.comment
    
    def get_absolute_url(self):
        return reverse('article_list')
```

```shell
python manage.py makemigrations articles
python manage.py migrate
```

### `articles\admin.py`

```python=6
admin.site.register(models.Comment)
```

:link: http://127.0.0.1:8000/admin/

Add comment not from admin user

### `articles\admin.py`

```python=6
class CommentInline(admin.StackedInline): # new
    model = models.Comment


class ArticleAdmin(admin.ModelAdmin): # new
    inlines = [
        CommentInline,
    ]

admin.site.register(models.Article, ArticleAdmin) # update
```

Reload admin page for article with comment

```python=6
class CommentInline(admin.TabularInline): # update
```

## Шаблон для комментариев

### `articles\models.py`

```python=22
class Comment(models.Model):
    article = models.ForeignKey(
        Article, 
        on_delete=models.CASCADE,
        related_name='comments'
    )
```

```shell
python manage.py makemigrations articles
python manage.py migrate
python manage.py runserver
```

### `templates\article_list.html`

```htmlmixed=16
    <div class="card-body">
      <p>{{ article.body }}</p>
      <a href="{% url 'article_edit' article.pk %}">Edit</a> |
      <a href="{% url 'article_delete' article.pk %}">Delete</a>
    </div>
    <div class="card-footer">
      {% for comment in article.comments.all %}
        <p>
          <span class="font-weight-bold">{{ comment.author }} &middot; </span>
          {{ comment }}
        </p>
      {% endfor %}
    </div>
```

---

(c) Яценко Р.Н., 2021

[Учебный центр компьютерных технологий "Кит"](http://kit.kh.ua/)

<img src="https://i.imgur.com/Kh901c1.png" style="width: 150px; position: fixed; top: 100px; right: 10px; border: 0; box-shadow: none;">
