Привет, ребята, сегодня я покажу вам, как создать простую новостную платформу. Конечно, это будет базовая новостная платформа, но, на мой взгляд, полезная и хорошо работающая.

Конечно, мы будем использовать django в качестве внутреннего фреймворка и CSS/HTML/JS для внешнего интерфейса — думаю, в этом нет ничего нового.

Итак, давайте быстро взглянем на нашу ссылку, на которой мы хотим сосредоточиться:

Наш референс выглядит хорошо из-за простоты — на мой взгляд. Людям нравятся простые и читаемые веб-сайты. По моему скромному мнению, я вижу это по адресу https://cryptopotato.com/ — так что сегодня мы будем создавать страницу как раз на сайте.

Хорошо, приступим — быстрая настройка или приложение django

Перед установкой любого приложения Django вам необходимо убедиться, что в вашей системе установлены Python и pip. Django и Django REST framework являются библиотеками Python, и их можно установить с помощью pip.

Вот шаги по установке Django, Django REST framework и вашего приложения Django.

  1. Установите Django и Django REST framework:

Откройте терминал и введите следующие команды:

создать виртуальную среду:

python3 -m venv env

после создания ENV:

cd env
cd scripts
./activate

а теперь установите djangorestframework и другие.

pip install djangorestframework
pip install ckeditor

2. Установите приложение Django:

Для установки приложения Django, такого как «kryptopigula», вы обычно клонируете репозиторий или загружаете файлы проекта из источника. Получив файлы проекта, перейдите в корневой каталог проекта (папка с файлом manage.py) и установите все перечисленные требования.

Если «kryptopigula» — это приложение Django, которое должно стать частью более крупного проекта Django, вы должны установить его, добавив в INSTALLED_APPS в файле настроек:

INSTALLED_APPS = [
    # other apps...
    'kryptopigula',
]

целиком:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'kryptopigula',
]

Обратите внимание, что вам может потребоваться заменить «kryptopigula» фактическим названием приложения, если оно отличается.

3. Настройте базу данных:

Django поставляется со встроенным уровнем абстракции базы данных, который может работать с базами данных SQL, такими как SQLite, PostgreSQL, MySQL и т. д. По умолчанию Django поставляется с SQLite.

Чтобы настроить базу данных, вам нужно будет обновить параметр DATABASES в файле настроек, а затем выполнить следующую команду, чтобы создать таблицы базы данных для всех установленных приложений:

python manage.py migrate

4. Запустите сервер:

Затем вы можете запустить сервер разработки Django с помощью:

python manage.py runserver

Затем вы можете открыть веб-браузер и посетить http://localhost:8000, чтобы просмотреть свое приложение.

Обратите внимание: вам может понадобиться использовать python3 и pip3 вместо python и pip, если вы используете Python 3. Вам также может потребоваться установить модуль виртуальной среды Python, venv, чтобы создать виртуальную среду перед установкой пакетов. Это считается лучшей практикой для разработки Python.

Давайте создадим общие компоненты

нижний колонтитул.html

<footer class="footer mt-auto py-3 bg-dark" style="background-color: #161E21 !important;">
    <div class="container">
      <div class="row">
        <div class="col">
          <h5 class="text-success">Column 1</h5>
          <ul class="list-unstyled text-small">
            <li><a class="text-muted" href="#">Cool stuff</a></li>
            <li><a class="text-muted" href="#">Random feature</a></li>
            <li><a class="text-muted" href="#">Team feature</a></li>
            <li><a class="text-muted" href="#">Stuff for developers</a></li>
            <li><a class="text-muted" href="#">Another one</a></li>
            <li><a class="text-muted" href="#">Last time</a></li>
          </ul>
        </div>
        <div class="col">
          <h5 class="text-success">Column 2</h5>
          <ul class="list-unstyled text-small">
            <li><a class="text-muted" href="#">Resource</a></li>
            <li><a class="text-muted" href="#">Resource name</a></li>
            <li><a class="text-muted" href="#">Another resource</a></li>
            <li><a class="text-muted" href="#">Final resource</a></li>
          </ul>
        </div>
        <div class="col">
          <h5 class="text-success">Column 3</h5>
          <ul class="list-unstyled text-small">
            <li><a class="text-muted" href="#">Business</a></li>
            <li><a class="text-muted" href="#">Education</a></li>
            <li><a class="text-muted" href="#">Government</a></li>
            <li><a class="text-muted" href="#">Gaming</a></li>
          </ul>
        </div>
        <div class="col">
          <h5 class="text-success">Column 4</h5>
          <ul class="list-unstyled text-small">
            <li><a class="text-muted" href="#">About</a></li>
            <li><a class="text-muted" href="#">Privacy</a></li>
            <li><a class="text-muted" href="#">Terms</a></li>
            <li><a class="text-muted" href="#">Support</a></li>
          </ul>
        </div>
      </div>
    </div>
  </footer>

Этот файл содержит HTML-код нижнего колонтитула веб-сайта. Нижний колонтитул состоит из четырех столбцов, каждый из которых содержит список ссылок. Этот раздел веб-сайта обычно предоставляет дополнительные возможности навигации или информацию о сайте.

а теперь создайте header.html

<nav class="navbar navbar-expand-lg navbar-dark bg-dark" style="background-color: #161E21 !important;">
    <div class="container-fluid">
        <a class="navbar-brand text-warning" href="/">KryptoPigula</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNavDropdown">
            <ul class="navbar-nav">
                <li class="nav-item">
                    <a class="nav-link active text-success" aria-current="page" href="#">Newsy</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link text-success" href="#">Artykuły</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link text-success" href="#">Poradniki</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link text-success" href="#">DeFi & NFT</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link text-success" href="#">Kryptowaluty</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link text-success" href="#">Sklep</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

<section id="sub-header">
    <div class="container">
        <ul class="nav justify-content-center">
            <li class="nav-item">
                <a class="nav-link" href="#">Market Updates</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">BTC Analysis</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">ETH Analysis</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">XRP Analysis</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Interviews</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#">Opinions</a>
            </li>
        </ul>
    </div>
</section>

Этот файл содержит HTML-код для шапки веб-сайта, включая главное меню навигации (панель навигации). Панель навигации сворачивается в меню-гамбургер на небольших экранах (как обрабатывается Bootstrap) и включает ссылки на такие разделы, как новости, статьи, руководства, DeFi и NFT, криптовалюты и магазин. Также есть раздел подзаголовка со ссылками на различные обновления рынка и анализы.

и не нужно переходить к base.html и добавлять код css и html.

base.html

<!DOCTYPE html>
<html>
    <head>
        <title>KryptoPigula</title>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
        <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css" rel="stylesheet">

    </head>
    
<body>
    {% include 'components/header.html' %}

    {% block content %}
    {% endblock %}

    {% include 'components/footer.html' %}

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>

<style>
    .zoom {
        transition: transform .2s;
    }

    .zoom:hover {
        transform: scale(1.02);
    }

    .card {
        margin: 0.2px;
    }

    .card-deck {
        display: flex;
        justify-content: space-between;
    }

    .card-deck .card {
        flex: 0.5 0 40%;
        margin-right: 2px;
        margin-bottom: 2px;
        margin-left: 2px;
    }

    .card-deck .d-flex {
        flex: 1;
        display: flex;
        flex-direction: column;
    }

    .card-deck .d-flex .card {
        flex: 1;
    }

    .card-image {
        height: 100px;
        object-fit: cover;
    }

    .card-content {
        height: 100px;
        overflow: hidden;
    }

    .container {
        max-width: 85%;
    }

    #sub-header {
        line-height: 25px;
    }
    #sub-header, #sub-header .widget-title {
        color: #3b3b3b;
        font-family: 'Arial', Arial, sans-serif;
        font-weight: 600;
        font-size: 14px;
        text-transform: capitalize;
        letter-spacing: 0.3px;
        line-height: 45px;
    }
    #sub-header {
        background-color: rgba(254, 211, 25, 1);
        background-position: top center;
        background-repeat: repeat-x;
        background-size: auto;
        background-attachment: scroll;
    }
    .nav-link {
        display: block;
        padding: .5rem 1rem;
        color: #3b3b3b !important; /* changed color */
      }
      
      a {
        color: #111; /* changed color */
        text-decoration: none;
        background-color: transparent;
        -webkit-text-decoration-skip: objects;
      }

      .small-card {
        width: 23%; /* Adjust the width here */
        margin: 0.5%; /* Add margin to prevent cards sticking together */
    }

    .small-card-image {
        height: 70px; /* Adjust the height here */
        object-fit: cover;
    }

    /* Reduce padding for 'Press Releases' section to have it closer to 'Join Our Community' */
    .row.pt-4 {
        padding-top: 2rem !important;
    }

    .card {
        margin: 0.1rem; /* Reduce the margin to bring cards closer */
        width: 100%;
    }
    
    .card-image {
        height: 70px;
        object-fit: cover;
    }
    .submitpr {
        color: #fff;
        margin-bottom: 0.5rem;
    }
    .border-right {
        border-right: 1px solid #ccc; /* Change the color to match your design */
    }

    .title-bar {
        border-bottom: 1px solid #ccc; /* Change the color to match your design */
        margin-bottom: 1.5rem;
        padding-bottom: 0.5rem;
    }

    .twitter-btn {
        background-color: #1DA1F2;
        color: white;
        margin-bottom: 0.5rem;
    }
    
    .telegram-btn {
        background-color: #0088cc;
        color: white;
        margin-bottom: 0.5rem;
    }
    
    .discord-btn {
        background-color: #7289DA;
        color: white;
        margin-bottom: 0.5rem;
    }
    
</style>

</html>

Это базовый шаблон для веб-сайта Django. Здесь определяются основные структурные элементы веб-сайта, такие как теги <!DOCTYPE html>, <html>, <head> и <body>. Файлы HTML, CSS и JS, а также любые внешние библиотеки, используемые на сайте, связаны здесь. Этот файл использует механизм шаблонов Django для включения HTML-компонентов верхнего и нижнего колонтитула и для определения блока контента, в который будет помещаться контент для конкретной страницы. Здесь также определяется пользовательский стиль CSS.

а теперь давайте создадим наш index.html

{% extends 'base.html' %}

{% load custom_range from range_tags %}

{% block content %}
    <div class="container mt-3">
        <div class="card-deck">
            <div class="card mb-4 shadow">
                <a href="#" class="stretched-link">
                    <img src="https://via.placeholder.com/350" class="card-img-top card-image zoom" alt="Sample news story">
                    <div class="card-body card-content">
                        <h5 class="card-title">Sample news story</h5>
                        <p class="card-text">This is a sample news story...</p>
                    </div>
                </a>
            </div>
            <div class="d-flex flex-column">
                <div class="card mb-4 shadow">
                    <a href="#" class="stretched-link">
                        <img src="https://via.placeholder.com/350" class="card-img-top card-image zoom" alt="Sample news story">
                        <div class="card-body card-content">
                            <h5 class="card-title">Sample news story</h5>
                            <p class="card-text">This is a sample news story...</p>
                        </div>
                    </a>
                </div>
                <div class="card mb-4 shadow">
                    <a href="#" class="stretched-link">
                        <img src="https://via.placeholder.com/350" class="card-img-top card-image zoom" alt="Sample news story">
                        <div class="card-body card-content">
                            <h5 class="card-title">Sample news story</h5>
                            <p class="card-text">This is a sample news story...</p>
                        </div>
                    </a>
                </div>
            </div>
        </div>

        <div class="row pt-4">
            <div class="col-lg-8 pb-4 border-right">
                <div class="title-bar">
                    <h5 class="titlehome">
                        <a href="/press-releases/">Komunikaty prasowe</a>
                    </h5>
                </div>
                <div class="row">
                    {% for press_release in press_releases %}
                    <div class="col-lg-3 col-md-6 col-sm-12">
                        <div class="card mb-4 shadow">
                            <a href="{{ press_release.get_absolute_url }}" class="stretched-link">
                                {% if press_release.thumbnail %}
                                <img src="{{ press_release.thumbnail.url }}" class="card-img-top card-image zoom" alt="{{ press_release.title }}">
                                {% else %}
                                <img src="https://via.placeholder.com/150" class="card-img-top card-image zoom" alt="Placeholder image">
                                {% endif %}
                                <div class="card-body card-content">
                                    <h5 class="card-title">{{ press_release.title }}</h5>
                                    <p class="card-text">{{ press_release.content|safe }}</p>
                                </div>
                            </a>
                        </div>
                    </div>
                    {% endfor %}
                </div>
            </div>
            <div class="col-lg-4">
                <div class="card">
                    <div class="card-body">
                        <h5 class="card-title titlehome">
                            Dołącz do naszej społeczności
                        </h5>
                        <div class="subpr">
                            <a class="btn btn-block submitpr twitter-btn" href="https://twitter.com/yourusername">
                                <i class="fab fa-twitter"></i> Twitter
                            </a>
                            <a class="btn btn-block submitpr telegram-btn" href="https://t.me/kryptopigula">
                                <i class="fab fa-telegram-plane"></i> Telegram
                            </a>
                            <a class="btn btn-block submitpr discord-btn" href="https://discord.gg/yourusername">
                                <i class="fab fa-discord"></i> Discord
                            </a>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- SECTION B -->
        <div class="row pt-4">
            <div class="col-lg-8 pb-4 border-right">
                <div class="title-bar">
                    <h5 class="titlehome">
                        <a href="/press-releases/">Crypto News</a>
                    </h5>
                </div>
                {% for _ in 20|custom_range %}
                <div class="card mb-4 shadow">
                    <a href="#" class="stretched-link">
                        <div class="row no-gutters">
                            <div class="col-lg-3">
                                <img src="https://via.placeholder.com/150" class="card-img" alt="Sample news story">
                            </div>
                            <div class="col-lg-9">
                                <div class="card-body">
                                    <h5 class="card-title">Sample news story</h5>
                                    <p class="card-text">This is a sample news story...</p>
                                </div>
                            </div>
                        </div>
                    </a>
                </div>
                <hr>
                {% endfor %}
                <div class="col-12 text-center mt-3">
                    <a href="/crypto-news/" class="btn btn-primary">Load more</a>
                </div>
            </div>
            <div class="col-lg-4">
                <div class="title-bar">
                    <h5 class="titlehome">Artykuły</h5>
                </div>
                {% for editorial in editorials %}
                <div class="card mb-4 shadow">
                    <a href="{{ editorial.get_absolute_url }}">
                        <div class="row no-gutters">
                            <div class="col-lg-4">
                                {% if editorial.thumbnail %}
                                <img src="{{ editorial.thumbnail.url }}" class="card-img" alt="{{ editorial.title }}">
                                {% else %}
                                <img src="https://via.placeholder.com/100" class="card-img" alt="{{ editorial.title }}">
                                {% endif %}
                            </div>
                            <div class="col-lg-8">
                                <div class="card-body py-2 px-3">
                                    <h6 class="card-title mb-0">{{ editorial.title }}</h6>
                                </div>
                            </div>
                        </div>
                    </a>
                    
                </div>
                {% endfor %}
            </div>
        </div>

<!-- SECTION C -->
<div class="row">
    <div class="col-lg-8 border-right">
        <div class="title-bar">
            <h5 class="titlehome">
                <a href="/press-releases/">Filmy</a>
            </h5>
        </div>
        <div class="row">
            {% for analysis in crypto_analyses %}
            <div class="col-lg-3 col-md-6 col-sm-12">
                <div class="card mb-4 shadow">
                    <a href="{{ analysis.link }}" class="stretched-link">
                        {% if analysis.image %}
                        <img src="{{ analysis.image.url }}" class="card-img-top card-image zoom" alt="{{ analysis.title }}">
                        {% else %}
                        <img src="https://via.placeholder.com/150" class="card-img-top card-image zoom" alt="Placeholder image">
                        {% endif %}
                        <div class="card-body card-content">
                            <h5 class="card-title">{{ analysis.title }}</h5>
                        </div>
                    </a>
                </div>
            </div>
            {% endfor %}
        </div>
    </div>
    
    <div class="col-lg-4">
        <div class="title-bar">
            <h5 class="titlehome">Reklamy</h5>
        </div>
        <!-- Wilki z Wiejskiej ad -->
        <div class="card mb-4 shadow">
            <a href="https://www.youtube.com/@wilkizwiejskiej/videos">
                <div class="row no-gutters">
                    <div class="col-lg-4">
                        <img src="https://scontent.fktw4-1.fna.fbcdn.net/v/t39.30808-6/338375981_4125619330996504_4735343678668732402_n.jpg?_nc_cat=107&ccb=1-7&_nc_sid=e3f864&_nc_ohc=Enhjk41r428AX8nynTv&_nc_ht=scontent.fktw4-1.fna&oh=00_AfDa1kmu_QOB-Y2cJgq7dsb71cohDRxB5eJxEaRuZxKbDw&oe=64AC9199" class="card-img" alt="Ad image">
                    </div>
                    <div class="col-lg-8">
                        <div class="card-body py-2 px-3">
                            <h6 class="card-title mb-0">Wilki z Wiejskiej</h6>
                            <p class="card-text">Kryptowaluty, edukacja, humor.</p>
                        </div>
                    </div>
                </div>
            </a>
        </div>
        <!-- Travilabs.com ad -->
        <div class="card mb-4 shadow">
            <a href="https://travilabs.com/">
                <div class="row no-gutters">
                    <div class="col-lg-4">
                        <img src="https://travilabs.com/img/travi.609f8865.png" class="card-img" alt="Ad image">
                    </div>
                    <div class="col-lg-8">
                        <div class="card-body py-2 px-3">
                            <h6 class="card-title mb-0">travilabs.com</h6>
                            <p class="card-text">Smart contracty, aplikacje, tokenizacja, strony internetowe, aplikacje mobilne, sklepy internetowe, automatyzacja, boty.</p>
                        </div>
                    </div>
                </div>
            </a>
        </div>
        <!-- Third ad - Domestico.pl duplicate -->
        <div class="card mb-4 shadow">
            <a href="#">
                <div class="row no-gutters">
                    <div class="col-lg-4">
                        <img src="https://domestico.pl/wp-content/uploads/2023/02/photo_2023-02-06_11-08-49-2.jpg.webp" class="card-img" alt="Ad image">
                    </div>
                    <div class="col-lg-8">
                        <div class="card-body py-2 px-3">
                            <h6 class="card-title mb-0">Domestico.pl</h6>
                            <p class="card-text">Oferujemy szeroki wybór profesjonalnej chemii gospodarczej oraz karm dla zwierząt.</p>
                        </div>
                    </div>
                </div>
            </a>
        </div>
    </div>
</div>


{% endblock %}

Этот файл «index.html» является главной целевой страницей веб-сайта, содержащей различные разделы с новостями, пресс-релизами, видеоконтентом и рекламными объявлениями. Эта страница основана на базовом шаблоне (base.html), который, вероятно, содержит общую структуру для всех страниц, такую как теги <head>, загрузку файлов CSS и JS, а также включение верхнего и нижнего колонтитула.

Уникальным аспектом этого файла является использование механизма шаблонов Django. Теги {% for %} и {% endfor %} используются для перебора данных, передаваемых в шаблон из представления Django. Например, {% for press_release in press_releases %} предполагает, что шаблон ожидает переменную с именем press_releases, которая, вероятно, является списком объектов пресс-релиза.

Точно так же теги {% block content %} и {% endblock %} обозначают блок контента, который можно переопределить в шаблонах, расширяющих этот блок. В этом случае любой HTML-код, размещенный внутри этого блока в index.html, заменит соответствующий блок в base.html.

Строка {% load custom_range from range_tags %} указывает на то, что пользовательский тег шаблона был создан в файле с именем range_tags.py, который загружается для использования в этом шаблоне. Пользовательские теги шаблонов можно использовать для добавления функций, не встроенных в язык шаблонов Django.

Помнить:

Представления — здесь, в этой папке, хранятся все html-файлы, такие как index.html, contact.html, privacypolicy.html и т. д. «Просмотры» означают одну страницу, например ванную, гостиную, кухню и т. д.

Компоненты — здесь в этой папке хранятся все html-файлы, такие как header.html, footer.html, card.html и так далее. Компоненты означают одну вещь, а не весь вид. Метафорически — кран, душ, кофеварка, дверь, окно.

Models.py

from django.db import models
from django.utils.text import slugify
from django.urls import reverse
from ckeditor.fields import RichTextField  # Import from ckeditor

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = RichTextField(null=True)  # Use RichTextField from ckeditor
    pub_date = models.DateTimeField('date published')
    image = models.ImageField(upload_to='images/', null=True, blank=True)

    def __str__(self):
        return self.title

class Editorial(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    thumbnail = models.ImageField(upload_to='images/', null=True, blank=True)
    content = RichTextField(null=True)  # Use RichTextField from ckeditor

    def save(self, *args, **kwargs):
        if not self.slug:
            potential_slug = slugify(self.title)
            if Editorial.objects.filter(slug=potential_slug).exists():
                i = 1
                while Editorial.objects.filter(slug=potential_slug + '-' + str(i)).exists():
                    i += 1
                self.slug = potential_slug + '-' + str(i)
            else:
                self.slug = potential_slug
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('editorial', args=[str(self.slug)])


    def __str__(self):
        return self.title


class CryptoAnalysis(models.Model):
    title = models.CharField(max_length=200)
    link = models.URLField()
    image = models.ImageField(upload_to='images/', null=True, blank=True)

    def __str__(self):
        return self.title

# models.py
class PressRelease(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    thumbnail = models.ImageField(upload_to='images/', null=True, blank=True)
    content = RichTextField(null=True)  # Use RichTextField from ckeditor

    def save(self, *args, **kwargs):
        if not self.slug:
            potential_slug = slugify(self.title)
            if PressRelease.objects.filter(slug=potential_slug).exists():
                i = 1
                while PressRelease.objects.filter(slug=potential_slug + '-' + str(i)).exists():
                    i += 1
                self.slug = potential_slug + '-' + str(i)
            else:
                self.slug = potential_slug
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('press-release', args=[str(self.slug)])

    def __str__(self):
        return self.title

Этот файл содержит модели для приложения Django. Модели определяют структуру таблиц базы данных:

  • Article: статья с заголовком, форматированным текстом, датой публикации и необязательным изображением.
  • Editorial: редакционная часть с заголовком, слагом для URL-адреса, необязательным миниатюрным изображением и форматированным текстовым содержимым. Слаг автоматически генерируется из заголовка, если он не указан.
  • CryptoAnalysis: Фрагмент анализа криптовалюты с заголовком, ссылкой на полный анализ и необязательным изображением.
  • PressRelease: пресс-релиз с заголовком, сокращенным URL-адресом, необязательной миниатюрой изображения и текстовым содержимым. Слаг автоматически генерируется из заголовка, если он не указан.

RichTextField происходит из пакета ckeditor и предоставляет расширенный интерфейс редактирования текста в админке Django.

Views.py

# views.py
from django.shortcuts import render, get_object_or_404
from .models import Editorial, CryptoAnalysis, PressRelease

def index(request):
    editorials = Editorial.objects.all()[:45]
    crypto_analyses = CryptoAnalysis.objects.all()
    press_releases = PressRelease.objects.all()[:4]  # Add this line
    context = {
        'editorials': editorials,
        'crypto_analyses': crypto_analyses,
        'press_releases': press_releases,  # Add this line
    }
    return render(request, 'index.html', context)


def editorial(request, slug):
    editorial = get_object_or_404(Editorial, slug=slug)
    return render(request, 'editorial.html', {'editorial': editorial})

def tutorials(request):
    tutorials = Editorial.objects.all()
    return render(request, 'tutorials.html', {'tutorials': tutorials})

# views.py
def press_release(request, slug):
    press_release = get_object_or_404(PressRelease, slug=slug)
    return render(request, 'press_release.html', {'press_release': press_release})

Этот файл содержит представления для приложения Django. Представления отвечают за обработку HTTP-запросов и возврат HTTP-ответов. Данные извлекаются из базы данных с использованием моделей и создается контекстный словарь. Затем контекст передается в шаблон (указанный строкой), и возвращается обработанный HTML.

  • index: извлекает редакционные статьи, криптоанализ и пресс-релизы из базы данных и отображает их с использованием шаблона index.html.
  • editorial: извлекает конкретную редакционную статью с помощью слага, переданного в URL-адресе, и отображает ее с использованием шаблона 'editorial.html'.
  • tutorials: извлекает все редакционные статьи и отображает их как учебные пособия с использованием шаблона tutorials.html.
  • press_release: извлекает конкретный пресс-релиз с помощью слага, переданного в URL-адресе, и отображает его с использованием шаблона «press_release.html».

urls.py

# urls.py
from django.contrib import admin
from django.urls import include, path
from . import views
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.index, name='index'),
    path('editorial/<slug:slug>/', views.editorial, name='editorial'),
    path('ckeditor/', include('ckeditor_uploader.urls')),  # Use ckeditor URLs
    path('tutorials/', views.tutorials, name='tutorials'),
    path('press-release/<slug:slug>/', views.press_release, name='press-release'),

] 

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Этот файл отвечает за маршрутизацию URL. Он сопоставляет URL-адреса с соответствующими представлениями:

  • Корневой URL-адрес ('') соответствует представлению index.
  • URL-адреса с шаблоном «редакционная/‹slug›» сопоставляются с представлением editorial, а слаг передается в качестве аргумента ключевого слова.
  • URL-адреса с шаблоном «ckeditor/» включают ckeditor_uploader.urls, которые обеспечивают функцию загрузки файлов для CKEditor.
  • URL-адреса с шаблоном «tutorials/» соответствуют представлению tutorials.
  • URL-адреса с шаблоном «пресс-релиз/‹слаг›» соответствуют представлению press_release, а слаг передается в качестве аргумента ключевого слова.

Если параметр DEBUG равен True, Django будет обслуживать медиафайлы во время разработки.

admin.py

from django.contrib import admin
from django.db import models  # Import models from django
from .models import Editorial, CryptoAnalysis, PressRelease
from ckeditor.widgets import CKEditorWidget  # Import from ckeditor

class EditorialAdmin(admin.ModelAdmin):  # Use the regular ModelAdmin
    formfield_overrides = {
        models.TextField: {'widget': CKEditorWidget},
    }

class PressReleaseAdmin(admin.ModelAdmin):  # Use the regular ModelAdmin
    formfield_overrides = {
        models.TextField: {'widget': CKEditorWidget},
    }

admin.site.register(Editorial, EditorialAdmin)
admin.site.register(CryptoAnalysis)
admin.site.register(PressRelease, PressReleaseAdmin)

Этот файл используется для определения административного интерфейса Django. В этом случае модели Editorial, CryptoAnalysis и PressRelease регистрируются у администратора. CKEditorWidget используется в классах EditorialAdmin и PressReleaseAdmin для переопределения виджета TextField по умолчанию в админке Django, что позволяет редактировать форматированный текст.

весь settings.py:

"""
Django settings for kryptopigula project.

Generated by 'django-admin startproject' using Django 4.2.2.

For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""

from pathlib import Path
import os
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '#'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'kryptopigula',
    'ckeditor',  # Use ckeditor

]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'kryptopigula.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'kryptopigula.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
CKEDITOR_UPLOAD_PATH = "uploads/"


STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

Это файл конфигурации Django, который содержит настройки для приложения Django. В настройки входят:

  • BASE_DIR: Объект pathlib.Path, указывающий на корневой каталог проекта Django.
  • SECRET_KEY: Секретный ключ для этой конкретной установки Django, используемый для обеспечения криптографической подписи.
  • DEBUG: логическое значение, которое включает/выключает режим отладки. Когда это правда, Django отобразит подробные страницы ошибок. Если это ложь, Django будет отображать простую страницу для любой ошибки.
  • ALLOWED_HOSTS: список строк, представляющих имена хостов/доменов, которые может обслуживать этот сайт Django.
  • INSTALLED_APPS: Список всех приложений Django, которые активированы в этом экземпляре Django.
  • MIDDLEWARE: список классов промежуточного ПО для использования.
  • ROOT_URLCONF: строка, представляющая путь импорта Python к вашей корневой конфигурации URL.
  • TEMPLATES: список, содержащий настройки всех механизмов шаблонов, которые будут использоваться с Django.
  • WSGI_APPLICATION: Путь импорта Python к объекту приложения WSGI, который будут использовать встроенные серверы Django.
  • DATABASES: словарь, содержащий настройки для всех баз данных, которые будут использоваться с Django.
  • AUTH_PASSWORD_VALIDATORS: Список валидаторов, которые используются для проверки надежности паролей.
  • LANGUAGE_CODE: строка, представляющая код языка для этой установки.
  • TIME_ZONE: строка, представляющая часовой пояс для этой установки.
  • STATIC_URL: URL-адрес для ссылки на статические файлы, расположенные в STATIC_ROOT.
  • CKEDITOR_UPLOAD_PATH: Путь для сохранения загруженных файлов ckeditor.
  • MEDIA_URL, MEDIA_ROOT, STATIC_ROOT: настройки для медиа (файлы, загруженные пользователем) и статические файлы.

От редакции.html

{% extends 'base.html' %}

{% block content %}
    <div class="container mt-3">
        <h1>{{ editorial.title }}</h1>
        {% if editorial.thumbnail %}
        <img src="{{ editorial.thumbnail.url }}" class="card-img-top card-image zoom" alt="{{ editorial.title }}">
        {% endif %}
            <p>{{ editorial.content|safe }}</p>
    </div>
{% endblock %}

Это шаблон Django, который расширяется от base.html. Строка {% extends 'base.html' %} указывает, что этот шаблон расширяет базовый шаблон. Содержимое тегов {% block content %} и {% endblock %} вставляется в блок content базового шаблона. Он создает контейнер с заголовком статьи, отображает миниатюру, если она существует, и отображает содержимое статьи.

press_release.html

{% extends 'base.html' %}

{% block content %}
    <div class="container mt-3">
        <h1>{{ press_release.title }}</h1>
        {% if press_release.thumbnail %}
        <img src="{{ press_release.thumbnail.url }}" class="card-img-top card-image zoom" alt="{{ press_release.title }}">
        {% endif %}
        <p>{{ press_release.content|safe }}</p>
    </div>
{% endblock %}

Это шаблон Django, очень похожий на editorial.html. Он также расширяется из base.html, создает контейнер с заголовком пресс-релиза, отображает миниатюру, если она существует, и отображает содержимое пресс-релиза. Основное отличие состоит в том, что в качестве переменной контекста используется press_release вместо editorial.

Range.tags.py

from django import template

register = template.Library()

@register.filter
def custom_range(value):
    return range(value)

Файл range_tags.py определяет пользовательский фильтр шаблонов для Django. Django позволяет создавать собственные фильтры шаблонов, чтобы расширить возможности языка шаблонов за пределы того, что включено по умолчанию.

Вот что делает этот конкретный код:

  1. from django import template: импортирует модуль шаблона Django, который позволяет создавать собственные теги и фильтры шаблонов.
  2. register = template.Library(): Эта строка создает новый экземпляр библиотеки, который вы можете использовать для регистрации собственных тегов и фильтров шаблона.
  3. @register.filter: это декоратор Python, который регистрирует функцию как пользовательский фильтр. Функция ниже будет использоваться в качестве фильтра в шаблонах Django.
  4. def custom_range(value): Это функция, которая будет использоваться в качестве фильтра. Он принимает значение в качестве аргумента.
  5. return range(value): Эта строка создает диапазон от 0 до значения, которое было передано функции. Это можно использовать в шаблоне, чтобы зациклить определенное количество раз.

Чтобы использовать этот пользовательский фильтр в шаблоне Django, вам сначала нужно загрузить его с помощью {% load range_tags %} в верхней части шаблона. Тогда вы можете использовать его так: {% for _ in 5|custom_range %}. Это создаст цикл, который выполняется 5 раз.

структура моего приложения:

Теперь давайте пропишем в терминале, когда у вас есть файл manage.py:

python manage.py makemigrations
python manage.py migrate

Теперь, когда вы мигрируете, давайте снова наберем:

python manage.py collectstatic

Эти команды необходимы для управления и развертывания проекта Django.

  1. python manage.py makemigrations: Эта команда указывает Django создавать новые миграции на основе изменений, которые вы внесли в свои модели. Миграции — это способ распространения изменений, которые вы вносите в свои модели (например, добавление поля, удаление модели и т. д.), в схему базы данных. По сути, он создает набор инструкций о том, как изменить вашу базу данных, чтобы она соответствовала вашим текущим моделям.
  2. python manage.py migrate: Эта команда применяет или отменяет миграцию. По сути, он выполняет инструкции, созданные командой makemigrations, изменяя схему вашей базы данных, чтобы она соответствовала вашим текущим моделям. Если миграция прошла успешно, схема вашей базы данных теперь будет соответствовать состоянию ваших моделей, и ваша база данных будет в состоянии, которое ожидает остальная часть вашего проекта Django.
  3. python manage.py collectstatic: Эта команда собирает все статические файлы в вашем проекте (CSS, JavaScript, изображения и т. д.) из каждого из ваших приложений (и любых других мест, которые вы укажете) в одно место, которое можно легко обслуживать. Место, куда он их собирает, определяется настройкой STATIC_ROOT в вашем файле настроек. Эта команда обычно запускается в рабочих настройках, чтобы получить все статические файлы в месте, где сервер может их эффективно обслуживать. Это важно для производительности вашего сайта, поскольку статические файлы упорядочиваются таким образом, что веб-сервер может обслуживать их отдельно от приложения Django.

а теперь давайте создадим суперпользователя

python manage.py createsuperuser

Команда python manage.py createsuperuser — это утилита командной строки Django, позволяющая создать учетную запись суперпользователя. Суперпользователь — это особый тип учетной записи пользователя со всеми разрешениями.

Как правило, суперпользователь имеет право делать все, что пожелает, в системе, на которой запущено приложение, например:

  • Создание, обновление и удаление других учетных записей пользователей.
  • Создание, обновление и удаление данных.
  • Доступ ко всем областям приложения, включая административные интерфейсы.

После запуска python manage.py createsuperuser вам будет предложено ввести имя пользователя, адрес электронной почты и пароль для учетной записи суперпользователя. Затем эту учетную запись можно использовать для входа в интерфейс администратора Django или для входа в приложение, если вы создали эту функциональность.

Не забудьте быть осторожным с тем, кто имеет доступ суперпользователя, потому что они, по сути, имеют полный контроль над приложением и данными.

Протестируйте приложение!

* Пресс-релиз:

CKEditor — это популярный редактор WYSIWYG (What You See Is What You Get) с открытым исходным кодом, который предоставляет общие функции текстового процессора непосредственно на ваши веб-страницы. Он предназначен для упрощения создания текстового контента за счет предоставления визуального интерфейса для разработки HTML-кода. Он поддерживает широкий спектр функций из коробки, таких как форматирование текста, загрузка и встраивание изображений, таблицы и многое другое.

Django CKEditor — это приложение Django, содержащее RichTextField и CKEditorWidget, использующее CKEditor с включенной поддержкой загрузки изображений и просмотра.

В своей статье на Medium — WYSIWYG-редактор Django CKEditor вы рассказали, как установить и использовать CKEditor в приложении Django. Вы включили инструкции по настройке CKEditor с функциями загрузки и просмотра изображений, что может быть сложной задачей, особенно для новичков в Django.

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

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

Это наш «Пресс-релиз», который мы добавили.

— Редакционные статьи:

— Криптографический анализ

Я оставляю остальное для вас. Я, конечно, оставляю это для вас, чтобы сделать дополнение к новостям. На данный момент для вас это будет просто формальностью — ведь не так уж и лень все делать за вас!

Это все братцы!

# немного саморекламы

Привет! Меня зовут Дориан, и я управляю небольшой компанией по разработке программного обеспечения. Мое предложение для вас.

— Интернет-магазины и сайты
— Веб и мобильные приложения
— Компьютерная графика
— Автоматизация процессов
— Боты, API и инфраструктура
— Брендинг
> — Внедрение искусственного интеллекта (ИИ)
— Плагины WordPress и PrestaShop и др.
— Смарт-контракты / Запуск собственной криптовалюты / NFT.
— Внедрение технологии WEB3 / Блокчейн в бизнесе.

Вы хотите создать свой собственный криптопроект на основе какого-либо приложения или просто хотите создать свою криптовалюту или NFT?
Хотите внедрить технологии WEB3 и блокчейн в свой бизнес?

— Веб-сайт: www.travilabs.com
Свяжитесь с нами:
Facebook: https://www.facebook.com/profile. php?id=100091601081883
Электронная почта: [email protected]