---
# System prepended metadata

title: Создание полнофункционального сайта электронной доски объявлений на Django
tags: [Python Web]

---

---
tags: Python Web
source: Дронов В.А. Django 3.0. Практика создания веб-сайтов на Python (598 c.)
---

# Создание полнофункционального сайта электронной доски объявлений на Django

https://github.com/roman-yatsenko/bboard

## План веб-сайта

Наша электронная доска объявлений позволит зарегистрированным пользователям публиковать объявления о продаже чего-либо. Объявления будут разноситься по 
рубрикам, причем структура рубрик будет иметь два уровня иерархии: на первом уровне расположатся рубрики общего плана (’’недвижимость”, ’’транспорт” и пр.), 
а на втором — более конкретные (’’жилье”, ’’гаражи”, ’’дачи”, ’’легковой”, ’’грузовой”, ’’специальный”).

Для вывода списка объявлений мы применим пагинацию, т. к. объявлений может оказаться очень много, и страница, содержащая все объявления, будет слишком 
большой. Также мы предусмотрим возможность поиска объявлений по введенному посетителем слову.

Под любым объявлением (на странице сведений об объявлении) может быть оставлено произвольное количество комментариев. Оставлять комментарии будет позволено любому пользователю, в том числе и гостю.

В составе объявления пользователь может поместить основную графическую иллюстрацию, которая будет выводиться и в списке объявлений, и в составе сведений об объявлении, а также произвольное количество дополнительных иллюстраций, которые можно будет увидеть лишь на странице сведений об объявлении. И основная, и дополнительные иллюстрации не являются обязательными к размещению.

Процедура регистрации нового пользователя на сайте будет разбита на два этапа. На первом этапе посетитель вводит свои данные на странице регистрации, после 
чего на указанный им адрес электронной почты приходит письмо с гиперссылкой, ведущей на страницу активации. На втором этапе посетитель переходит по гиперссылке, полученной в письме, попадает на страницу активации и становится полноправным пользователем.

Сайт доски объявлений включит в себя следующие страницы:

- главная — показывающая десять последних опубликованных объявлений без разбиения их на рубрики;
- страница списка объявлений — показывающая (с использованием пагинации) объявления из определенной рубрики. Также она будет содержать форму для поиска объявления по введенному слову;
- страница сведений о выбранном объявлении — выведет еще все оставленные для него комментарии и форму для добавления нового комментария;
- страницы регистрации и активации нового пользователя;
- страницы входа и выхода;
- страница профиля зарегистрированного пользователя — выведет список объявлений, оставленных текущим пользователем;
- страницы добавления, правки, удаления объявлений;
- страницы изменения пароля, правки и удаления пользовательского профиля;
- страницы сведений о сайте, о правах его разработчика, пользовательского соглашения и пр.

## Подготовка проекта и приложения main

Создать проект на GitHub и клонировать его.

```shell=
pipenv install
pipenv shell
pipenv install django
django-admin startproject bboard .
```

### `bboard\settings.py`

```python=13
import os
```

```python=77
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'bboard.data'),
    }
}
```

```python=107
LANGUAGE_CODE = 'ru'
```

```shell
python manage.py startapp main
```

### `main\apps.py`

```python=5
class MainConfig(AppConfig):
    name = 'main'
    verbose_name = 'Доска объявлений'
```

### `bboard\settings.py`

```python=34
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'main.apps.MainConfig'
]
```

## Базовый шаблон

```shell
mkdir main/templates
mkdir main/templates/layout
mkdir main/static
mkdir main/static/main
pipenv install django-bootstrap4
```

```python=34
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'main.apps.MainConfig',
    'bootstrap4',
]
```

### `main\templates\layout\basic.html`

```htmlmixed=
{% load bootstrap4 %}
{% load static %}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
        content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <title>{% block title %}Главная{% endblock %} - Доска объявлений</title>
        {% bootstrap_css %}
        <link rel="stylesheet" type="text/css" href="{% static 'main/style.css' %}">
        {% bootstrap_javascript jquery='slim' %}
    </head>
    <body class="container-fluid">
        <header class="mb-4">
            <h1 class="display-1 text-center">Объявления</h1>
        </header>
        <div class="row">
            <ul class="col nav justify-content-end border">
                <li class="nav-item"><a class="nav-link"
                href="{% url 'main:register' %}">Регистрация</a></li>
                {% if user.is_authenticated %}
                <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" data-toggle="dropdown"
                    href="#" role="button" aria-haspopup="true"
                    aria-expanded="false">Профиль</a>
                    <div class="dropdown-menu">
                        <a class="dropdown-item" href="#">Мои объявления</a>
                        <a class="dropdown-item" href="#">Изменить личные данные</a>
                        <a class="dropdown-item" href="#">Изменить пароль</a>
                        <div class="dropdown-divider"></div>
                        <a class="dropdown-item" href="#">Выйти</a>
                        <div class="dropdown-divider"></div>
                        <a class="dropdown-item" href="#">Удалить</a>
                    </div>
                </li>
                {% else %}
                <li class="nav-item"><a class="nav-link" href="#">Вход</a></li>
                {% endif %}
            </ul>
        </div>
        <div class="row">
            <nav class="col-md-auto nav flex-column border">
                <a class="nav-link root" href="{% url 'main:index' %}">Главная</a>
                <span class="nav-link root font-weight-bold" href="#">Недвижимость</span>
                <a class="nav-link" href="#">Жилье</a>
                <a class="nav-link" href="#">Склады</a>
                <a class="nav-link" href="#">Гаражи</a>
                <span class="nav-link root font-weight-bold" href="#">Транспорт</span>
                <a class="nav-link" href="#">Легковой</a>
                <a class="nav-link" href="#">Грузовой</a>
            </nav>
            <section class="col border py-2">
                {% bootstrap_messages %}
                {% block content %}
                {% endblock %}
            </section>
        </div>
        <footer class="mt-3">
            <p class="text-right font-italic">&copy; читатели.</p>
        </footer>
    </body>
</html>
```

### `main\static\main\style.css`

```css=
header h1 {
    background: url("bg.jpg") left / auto 100% no-repeat, url("bg.jpg") right / auto 100% no-repeat;
}
.root {
    font-size: larger;
}
```
