Skip to content

rachoni/BalkanPress

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

37 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

BalkanPress

BalkanPress Screenshot

BalkanPress is a production-ready news and blogging platform built with Django. It supports articles, categories, tags, comments, search functionality, user accounts, and a clean, scalable architecture.


Live Demo

Features

  • Article management (Create, Edit, Delete)
  • Category & Tag management (Full CRUD)
  • Category & Tag filtering
  • Full text search (title, summary, content, categories, tags)
  • Comment system (with moderation support)
  • User registration, login, logout, and profile management
  • Owner-managed CRUD permissions (author/staff)
  • User groups with permissions (Authors, Moderators)
  • Newsletter subscription
  • Asynchronous newsletter dispatch (Celery)
  • Pagination
  • Reading time calculation
  • Bootstrap 5 UI
  • DRY & scalable architecture
  • Production-grade class-based views
  • Reusable form mixins
  • Clean template structure
  • Optimised querysets (select_related, prefetch_related)
  • REST API (articles, categories, tags) with JWT authentication
  • Custom error pages (404, 500)

Architecture Overview

BalkanPress/
β”œβ”€β”€ BalkanPress/
β”‚   β”œβ”€β”€ articles/
β”‚   β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”œβ”€β”€ templatetags/
β”‚   β”‚   β”‚   └── article_extras.py
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ forms.py
β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”œβ”€β”€ tests.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   └── views.py
β”‚   β”œβ”€β”€ categories/
β”‚   β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ forms.py
β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”œβ”€β”€ tests.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   └── views.py
β”‚   β”œβ”€β”€ comments/
β”‚   β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ forms.py
β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”œβ”€β”€ tests.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   └── views.py
β”‚   β”œβ”€β”€ accounts/
β”‚   β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ forms.py
β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”œβ”€β”€ tests.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   └── views.py
β”‚   β”œβ”€β”€ common/
β”‚   β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ helpers.py
β”‚   β”‚   β”œβ”€β”€ forms.py
β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”œβ”€β”€ tests.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   β”œβ”€β”€ validators.py
β”‚   β”‚   └── views.py
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ permissions.py
β”‚   β”‚   β”œβ”€β”€ serializers.py
β”‚   β”‚   β”œβ”€β”€ tests.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   └── views.py
β”‚   β”œβ”€β”€ tags/
β”‚   β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ forms.py
β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”œβ”€β”€ tests.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   └── views.py
β”‚   β”œβ”€β”€ newsletter/
β”‚   β”‚   β”œβ”€β”€ migrations/
β”‚   β”‚   β”œβ”€β”€ admin.py
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ forms.py
β”‚   β”‚   β”œβ”€β”€ models.py
β”‚   β”‚   β”œβ”€β”€ tests.py
β”‚   β”‚   β”œβ”€β”€ urls.py
β”‚   β”‚   └── views.py
β”‚   β”œβ”€β”€ asgi.py
β”‚   β”œβ”€β”€ settings.py
β”‚   β”œβ”€β”€ urls.py
β”‚   └── wsgi.py
β”œβ”€β”€ media/
β”œβ”€β”€ staticfiles/
β”‚   β”œβ”€β”€ css/
β”‚   β”‚   └── styles.css
β”‚   └── images/
β”‚       β”œβ”€β”€ favicon.ico
β”‚       └── logo.png
β”œβ”€β”€ templates/
β”‚   β”œβ”€β”€ articles/
β”‚   β”‚   β”œβ”€β”€ article-create.html
β”‚   β”‚   β”œβ”€β”€ article-delete.html
β”‚   β”‚   β”œβ”€β”€ article-detail.html
β”‚   β”‚   β”œβ”€β”€ article-edit.html
β”‚   β”‚   β”œβ”€β”€ article-list.html
β”‚   β”‚   └── _sidebar.html
β”‚   β”œβ”€β”€ categories/
β”‚   β”‚   β”œβ”€β”€ category-create.html
β”‚   β”‚   β”œβ”€β”€ category-delete.html
β”‚   β”‚   β”œβ”€β”€ category-edit.html
β”‚   β”‚   └── category-list.html
β”‚   β”œβ”€β”€ tags/
β”‚   β”‚   β”œβ”€β”€ tag-create.html
β”‚   β”‚   β”œβ”€β”€ tag-delete.html
β”‚   β”‚   β”œβ”€β”€ tag-edit.html
β”‚   β”‚   └── tag-list.html
β”‚   β”œβ”€β”€ common/
β”‚   β”‚   β”œβ”€β”€ errors/
β”‚   β”‚   β”‚   └── 404.html
β”‚   β”‚   └── partials/
β”‚   β”‚       β”œβ”€β”€ _clock.html
β”‚   β”‚       β”œβ”€β”€ _weather.html
β”‚   β”‚       β”œβ”€β”€ footer.html
β”‚   β”‚       └── nav.html
β”‚   β”œβ”€β”€ about.html
β”‚   └── base.html
β”œβ”€β”€ .env.example
β”œβ”€β”€ .gitignore
β”œβ”€β”€ manage.py
β”œβ”€β”€ README.md
└── requirements.txt

Search System

Search is implemented using:

  • 'ArticleSearchForm'
  • 'ArticleSearchView'
  • Query filtering with Django 'Q' objects
  • Case-insensitive matching

Search covers:

  • Title
  • Summary
  • Content
  • Category names
  • Tag names

Tech Stack

  • Python 3.13
  • Django 6.0.2
  • Django REST Framework + JWT
  • Bootstrap 5
  • PostgreSQL
  • Celery + Redis
  • HTML/CSS
  • JavaScript (minimal)

Installation

Prerequisites

  • Python 3.13 or higher
  • PostgreSQL
  • Git

Step-by-Step Installation

  1. Clone the repository

    git clone https://github.com/rachoni/balkanpress.git
    cd balkanpress
  2. Create virtual environment

    python -m venv venv
    source venv/bin/activate # macOS / Linux
    venv\\Scripts\\activate # Windows
  3. Install dependencies

    pip install -r requirements.txt
  4. Database Setup

    createdb balkan_press_db

    Or using psql:

    CREATE DATABASE balkan_press_db;
  5. Environment Variables Create .env from the existing .env.example file:

    cp .env.example .env

    Then edit .env and set your real local values (especially SECRET_KEY and DB_PASSWORD).

  6. Apply migrations

    python manage.py migrate
  7. Create superuser

    python manage.py createsuperuser
  8. Collect static files

    python manage.py collectstatic
  9. Run server

    python manage.py runserver
  10. Access the application


Optional: MailHog (local email testing)

  1. Run MailHog in Docker

    docker run -d --name mailhog -p 1025:1025 -p 8025:8025 mailhog/mailhog
  2. Open MailHog UI


Optional: Celery (local async tasks)

  1. Run Redis in Docker

    docker run -d --name redis -p 6379:6379 redis
  2. Start Celery worker

    celery -A BalkanPress worker -l info

Environment Variables

Variable Description Default
SECRET_KEY Django secret key Required
DEBUG Debug mode False
DB_NAME Database name balkan_press_db
DB_USER Database user postgres
DB_PASSWORD Database password Required
DB_HOST Database host localhost
DB_PORT Database port 5432
ALLOWED_HOSTS Allowed hosts (comma list) Required
CSRF_TRUSTED_ORIGINS Trusted origins (comma list) Required
EMAIL_BACKEND Email backend SMTP
EMAIL_HOST SMTP host localhost
EMAIL_PORT SMTP port 1025
EMAIL_HOST_USER SMTP user empty
EMAIL_HOST_PASSWORD SMTP password empty
EMAIL_USE_TLS Use TLS False
DEFAULT_FROM_EMAIL Default sender required
CELERY_BROKER_URL Celery broker (Redis) redis://localhost:6379/0
CELERY_RESULT_BACKEND Celery backend (Redis) redis://localhost:6379/0

Existing .env.example

This project already includes an .env.example file. Keep only safe placeholder values there:

SECRET_KEY=
DEBUG=

DB_NAME=
DB_USER=
DB_PASSWORD=
DB_HOST=
DB_PORT=

ALLOWED_HOSTS=
CSRF_TRUSTED_ORIGINS=

EMAIL_BACKEND=
EMAIL_HOST=
EMAIL_PORT=
EMAIL_HOST_USER=
EMAIL_HOST_PASSWORD=
EMAIL_USE_TLS=
DEFAULT_FROM_EMAIL=

CELERY_BROKER_URL=
CELERY_RESULT_BACKEND=

Design Principles

  • DRY (Don't Repeat Yourself) - Reusable mixins and base classes
  • Separation of Concerns - Clear app boundaries
  • Reusable mixins - Common functionality extracted
  • Clean class-based views - Organized view logic
  • Scalable URL structure - Namespaced URL patterns
  • Template partials - Reusable template components
  • Bootstrap form integration - Consistent form styling
  • Production-oriented structure - Ready for deployment

Security Considerations

βœ… Implemented:

  • CSRF Protection: Enabled on all forms with '{% csrf_token %}'
  • SQL Injection Prevention: Django ORM with parameterized queries
  • XSS Protection: Automatic template escaping
  • Environment Variables: Sensitive data stored in .env file
  • Form Validation: Server-side validation with custom clean methods
  • JWT Authentication: API uses JWT tokens

⚠️ Partially Implemented / Configuration Required:

  • Client-side Validation: HTML5 attributes added to form fields
  • Production Settings: Set DEBUG=False in .env for production deployment

Best Practices Followed:

  • Secret key never committed to repository
  • Database credentials in environment variables
  • No sensitive data in source code

Guidelines

Contributing Guidelines

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Development Guidelines

  • Follow PEP 8 style guide
  • Write meaningful commit messages
  • Add tests for new features
  • Update documentation as needed
  • Ensure all tests pass before submitting PR

Known issues

  • Image upload path in Article model needs optimization
  • Search with special characters may need escaping
  • Mobile responsiveness needs improvement on some pages
  • Comment moderation lacks email notifications

Future Improvements

  • Add RSS feeds for articles
  • Implement related articles suggestions
  • Add social media sharing buttons
  • Create article view count tracking
  • Implement article bookmarking/saving
  • Add multi-language support
  • Create API endpoints with Django REST Framework
  • Implement caching for frequently accessed data
  • Add unit tests for all views and forms

License

MIT License


Contact

Radoslav Raychev - GitHub Project Link: https://github.com/rachoni/balkanpress

About

A news website for publishing articles, categories and comments, with a modern admin interface and easy navigation.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors