├── .github └── workflows │ └── bento.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTORS.md ├── Dockerfile ├── Procfile ├── README.md ├── generate-django.sh ├── manage.py ├── pyconbalkan ├── __init__.py ├── about │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20180604_1346.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ └── about.html │ ├── tests.py │ └── views.py ├── archive │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ └── archive.html │ ├── tests.py │ └── views.py ├── cfp │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── const.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20180604_1346.py │ │ ├── 0003_auto_20180611_1803.py │ │ ├── 0004_auto_20180611_1814.py │ │ ├── 0005_auto_20180629_1257.py │ │ ├── 0006_auto_20180807_0944.py │ │ ├── 0007_cfprating_comment.py │ │ ├── 0008_auto_20180809_1350.py │ │ ├── 0009_auto_20180810_1859.py │ │ ├── 0010_cfp_active.py │ │ ├── 0011_auto_20181018_1949.py │ │ ├── 0012_cfp_conference.py │ │ ├── 0013_cfp_speaker.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ ├── cfp_detail.html │ │ ├── cfp_form.html │ │ └── cfp_list.html │ ├── tests.py │ └── views.py ├── coc │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_response_guide.py │ │ ├── 0003_response_guide_slug.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ ├── coc.html │ │ └── response_guide.html │ ├── tests.py │ └── views.py ├── conference │ ├── __init__.py │ ├── abstractions.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── context.py │ ├── context_processors.py │ ├── middleware.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_mission_statement.py │ │ ├── 0003_auto_20180710_1214.py │ │ ├── 0004_auto_20180802_2008.py │ │ ├── 0005_auto_20180804_2148.py │ │ ├── 0006_conference_timetable_pdf.py │ │ ├── 0007_auto_20190227_0738.py │ │ ├── 0008_auto_20190303_1800.py │ │ ├── 0009_remove_conference_timetable_pdf.py │ │ ├── 0010_conference_conference_logo.py │ │ ├── 0011_conference_workshop_application_embed_code.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── static │ │ └── js │ │ │ └── search_people.js │ ├── templates │ │ └── home.html │ ├── tests.py │ └── views.py ├── contact │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── decorators.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ └── contact_form │ │ │ ├── contact.html │ │ │ └── success.html │ ├── tests.py │ └── views.py ├── core │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── loaders.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── routers.py │ ├── static │ │ ├── css │ │ │ ├── _fonts.css │ │ │ ├── components │ │ │ │ ├── button.css │ │ │ │ ├── card.css │ │ │ │ ├── countdown.css │ │ │ │ ├── datepicker.css │ │ │ │ ├── event-sidebar.css │ │ │ │ ├── faq-accordion.css │ │ │ │ ├── featured-letter.css │ │ │ │ ├── flag.css │ │ │ │ ├── form.css │ │ │ │ ├── line.css │ │ │ │ ├── long-text.css │ │ │ │ ├── menu.css │ │ │ │ ├── page.css │ │ │ │ ├── person.css │ │ │ │ ├── post.css │ │ │ │ ├── sponsors.css │ │ │ │ ├── timetable.css │ │ │ │ ├── title.css │ │ │ │ ├── tooltip.css │ │ │ │ └── volunteer.css │ │ │ ├── helpers │ │ │ │ └── spacing.css │ │ │ └── main.css │ │ ├── img │ │ │ ├── belgrade_1.jpg │ │ │ ├── belgrade_2.jpg │ │ │ ├── belgrade_3.jpg │ │ │ ├── belgrade_4.JPG │ │ │ ├── burger-menu.png │ │ │ ├── burger-menu.svg │ │ │ ├── clock.svg │ │ │ ├── close.png │ │ │ ├── close.svg │ │ │ ├── django-logo.png │ │ │ ├── email-dark.svg │ │ │ ├── email.svg │ │ │ ├── euro-python-society.png │ │ │ ├── facebook-dark.svg │ │ │ ├── facebook.svg │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── front-light-pyConBlkn-2.png │ │ │ ├── github.svg │ │ │ ├── hilton.jpg │ │ │ ├── instagram-dark.svg │ │ │ ├── instagram.svg │ │ │ ├── linkedin.svg │ │ │ ├── pfs-logo.png │ │ │ ├── pycon-logo.png │ │ │ ├── pycon-logo.svg │ │ │ ├── pycon-sig-logo.png │ │ │ ├── pycon_logo.png │ │ │ ├── python-bullet.png │ │ │ ├── python-bullet.svg │ │ │ ├── sidebar-bg.png │ │ │ ├── sidebar-bg.svg │ │ │ ├── snake.png │ │ │ ├── travel_1.jpg │ │ │ ├── twitter-dark.svg │ │ │ ├── twitter.svg │ │ │ ├── venue_1.jpg │ │ │ ├── venue_2.jpg │ │ │ ├── venue_3.jpg │ │ │ └── website.svg │ │ ├── js │ │ │ ├── accordion.js │ │ │ ├── go_to_top.js │ │ │ ├── menu.js │ │ │ ├── timer.js │ │ │ ├── timetable.js │ │ │ └── volunteer.js │ │ ├── organizers │ │ │ └── volunteer │ │ │ │ └── profile_picture │ │ │ │ └── 1528646012025.jpg │ │ ├── pdf │ │ │ ├── coc_pyconbalkan.pdf │ │ │ ├── pycon-balkan-2018-timetable.pdf │ │ │ ├── pycon-sponsors-brochure-2019.pdf │ │ │ └── pycon_brochure.pdf │ │ ├── sponsors │ │ │ └── logo │ │ │ │ └── 1553191407426.jpg │ │ └── video │ │ │ └── pycon-bg-2019-loop.mp4 │ ├── storage.py │ ├── templates │ │ ├── base.html │ │ ├── includes │ │ │ ├── event_sidebar.html │ │ │ └── header.html │ │ ├── registration │ │ │ └── login.html │ │ └── robots.txt │ ├── templatetags │ │ ├── __init__.py │ │ └── startswith.py │ ├── tests.py │ └── views.py ├── faq │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20190227_0738.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ └── faq.html │ ├── tests.py │ └── views.py ├── info │ └── __init__.py ├── news │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20180603_1257.py │ │ ├── 0003_auto_20180604_1346.py │ │ ├── 0004_post_slug.py │ │ ├── 0005_auto_20180611_1958.py │ │ ├── 0006_post_keywords.py │ │ ├── 0007_auto_20180801_2233.py │ │ ├── 0008_post_conference.py │ │ ├── 0009_remove_post_conference.py │ │ ├── 0010_auto_20190328_2253.py │ │ ├── 0011_post_front_page.py │ │ ├── 0012_auto_20190921_2009.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ ├── news.html │ │ └── post.html │ ├── tests.py │ └── views.py ├── ngo │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ └── views.py ├── onsite │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── templates │ │ ├── lightningtalks.html │ │ ├── openspaces.html │ │ └── workshops.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── organizers │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_remove_volunteer_email.py │ │ ├── 0003_auto_20180603_1156.py │ │ ├── 0004_volunteer_slug.py │ │ ├── 0005_auto_20180610_1608.py │ │ ├── 0006_volunteer_description.py │ │ ├── 0007_volunteer_weight.py │ │ ├── 0008_auto_20180611_2147.py │ │ ├── 0009_auto_20180613_1701.py │ │ ├── 0010_person_email.py │ │ ├── 0011_auto_20180801_2233.py │ │ ├── 0012_auto_20180801_2318.py │ │ ├── 0013_volunteer_country.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ ├── organizer.html │ │ ├── organizers.html │ │ └── volunteers_create.html │ ├── tests.py │ └── views.py ├── pera.json ├── settings.py ├── speaker │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20180506_1828.py │ │ ├── 0003_auto_20180603_1156.py │ │ ├── 0004_auto_20180610_1053.py │ │ ├── 0005_speaker_slug.py │ │ ├── 0006_auto_20180610_1608.py │ │ ├── 0007_speaker_github.py │ │ ├── 0008_person_email.py │ │ ├── 0009_auto_20180801_2318.py │ │ ├── 0010_speaker_country.py │ │ ├── 0011_speaker_conference.py │ │ ├── 0012_auto_20190827_1257.py │ │ ├── 0013_remove_speaker_keynote.py │ │ ├── 0014_youtubelink.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ ├── speaker.html │ │ └── speakers.html │ ├── tests.py │ └── views.py ├── sponsors │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20180603_1156.py │ │ ├── 0003_auto_20180604_1346.py │ │ ├── 0004_sponsoring.py │ │ ├── 0005_auto_20180804_2052.py │ │ ├── 0006_sponsoring_organization_type.py │ │ ├── 0007_sponsoring_level.py │ │ ├── 0008_auto_20180811_1903.py │ │ ├── 0009_auto_20190303_1426.py │ │ ├── 0010_sponsor_conference.py │ │ ├── 0011_auto_20190321_2214.py │ │ ├── 0012_auto_20190321_2148.py │ │ ├── 0013_auto_20190322_1457.py │ │ ├── 0014_sponsor_active.py │ │ ├── 0015_auto_20190827_1159.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ ├── sponsor.html │ │ ├── sponsoring.html │ │ └── sponsors.html │ ├── tests.py │ └── views.py ├── sponsorship │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ └── sponsorship.html │ ├── tests.py │ └── views.py ├── timetable │ ├── __init__.py │ ├── admin.py │ ├── api_urls.py │ ├── apps.py │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ └── load_timetable.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20180604_1346.py │ │ ├── 0003_auto_20180803_1820.py │ │ ├── 0004_presentation_conference.py │ │ ├── 0005_auto_20190827_1355.py │ │ ├── 0006_auto_20190827_2044.py │ │ ├── 0007_auto_20190827_2247.py │ │ ├── 0008_auto_20190912_1847.py │ │ └── __init__.py │ ├── models.py │ ├── serializers.py │ ├── templates │ │ ├── timetable.html │ │ └── timetable_sessionize.html │ ├── tests.py │ └── views.py ├── urls.py ├── venue │ ├── __init__.py │ ├── templates │ │ └── venue.html │ └── views.py └── wsgi.py ├── requirements-dev.txt ├── requirements.in ├── requirements.txt ├── run_migrate.sh └── runtime.txt /.github/workflows/bento.yml: -------------------------------------------------------------------------------- 1 | name: bento 2 | on: [pull_request] 3 | jobs: 4 | bento: 5 | runs-on: ubuntu-latest 6 | name: check 7 | steps: 8 | - uses: actions/checkout@v1 9 | - name: bento check 10 | id: bento 11 | uses: returntocorp/bento-action@v1 12 | with: 13 | acceptTermsWithEmail: website@pyconbalkan.com 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | # file for python-decouple 3 | .env 4 | # virtual env 5 | .venv/ 6 | .idea 7 | *.sqlite3 8 | *.py[cod] 9 | *.svg 10 | __pycache__ 11 | .mypy_cache 12 | html_report 13 | .vscode 14 | 15 | /staticfiles/ 16 | 17 | # TODO: We should have static files at some remote location with settings. 18 | /pyconbalkan/core/static/* 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - '3.6' 4 | services: 5 | - postgresql 6 | addons: 7 | postgresql: '9.6' 8 | branches: 9 | only: 10 | - master 11 | install: 12 | - pip install -r requirements.txt 13 | - pip install model_mommy 14 | script: 15 | - python manage.py test 16 | env: 17 | - DATABASE_URL=postgres://postgres:@localhost/test 18 | deploy: 19 | provider: heroku 20 | app: pyconbalkan 21 | api_key: 22 | secure: eZx87paHEYM3HzEDFXLjhKPJHblZ2ptt73yuuXcQBgMrClJ/nz2uOre813TYb5VNMACO7vLtuAhAsT+934Dtqi1zf9Tg9BR8U2jVazoUdauX4eH9xt7podOL2cJ796/nkc+DkEZyPgF3Saxd9d4PIWvkXYvpLXkMaGI41H2Iss52aNgqvG+HmDRmk3u7Pr7ZJbKkjP3QI/P5qM2ISfCS7XDK3FqvZ8hMcEvcxZHm6A0mjiim1c6dhtvtCRJPMfBkP/cZ8RdyxHsZfKJ7mY0I+9q+UDUW4nhfGFQ0zqaWhISL0764CtLR5oaR05bTMgjzKtXipj/Iy7V2f/lonJoQkv48R+RvUO5zn4ifsuAIkW2WQHozK8spctodjmn+cba5V2D2nPz68nSGKoQPJzt9fAzWrW3EcMteRmVQEhpXSPs2Y1za1NDVQ2O3nt8+ImClow46nWQn/oA6YvQ/dE0c15YAD+RBemm+l6elS0kBvV8LBhDxWullTchBlZ6uzsVM5UfiYH/eA9Mqb9GkpPgJ2cUB9auvJe66+Mph8JGtw8wVIDwj5N/c2hXnmi9ajWm5V3Ku0DOhrK/8tryHnsawbJ6VDpm4Ye2RgofZcmaobhgJXqrS+C+zqLxIvqeVBlJ9U6ugqCD6G2JRujg/o7CBa5nwyH/Dt6ZRd6VvkwOSN5k= 23 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | PyconBalkan Website contributors 2 | ============================================ 3 | 4 | * **[Bojan Jovanovic](https://github.com/virogenesis)** 5 | * **[Katia Nakamura](https://github.com/kolebre)** 6 | * **[Konstantin Krbacevic](https://github.com/nadaj)** 7 | * **[Vishvajit Pathak](https://github.com/VishvajitP)** 8 | * **[Nada Jankovic](https://github.com/nadaj)** 9 | * **[Ülgen Sarıkavak](https://github.com/ulgens)** 10 | * **[Midhat Sibonjic](https://github.com/midhatstam)** 11 | * **[Thiago Rossener](https://github.com/thiagorossener)** 12 | * **[Milos Mrdakovic](https://github.com/mrdaak)** 13 | * **[Viktor Kerkez](https://github.com/alefnula)** 14 | * **[Halit Guvenilir](https://github.com/halitguvenilir)** 15 | * **[Jacques Laroche](https://github.com/jlar0che)** 16 | * **[Mario Hunka](https://github.com/maroshmka)** 17 | * **[Bojan Pavlovic](https://github.com/BojPav)** 18 | * **[Milovan Minic](https://github.com/milovan-minic)** 19 | * **[Milos Trifunovic](https://github.com/MaliRobot)** 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.6 2 | 3 | WORKDIR /app 4 | COPY . /app 5 | 6 | 7 | RUN apt-get -y update 8 | RUN apt-get -y install --no-install-recommends binutils 9 | RUN pip install -r /app/requirements.txt 10 | 11 | RUN ./generate-django.sh 12 | 13 | 14 | CMD ./run_migrate.sh -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | release: python manage.py migrate 2 | web: gunicorn pyconbalkan.wsgi --log-file - 3 | -------------------------------------------------------------------------------- /generate-django.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function django_secret() { python -c "import random,string;print('SECRET_KEY='+''.join([random.SystemRandom().choice(\"{}{}{}\".format(string.ascii_letters, string.digits, string.punctuation)) for i in range(63)]).replace('\\'','\\'\"\\'\"\\''))"; } 4 | echo "DEBUG=True" > .env 5 | django_secret >> .env 6 | 7 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pyconbalkan.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError: 10 | # The above import may fail for some other reason. Ensure that the 11 | # issue is really that Django is missing to avoid masking other 12 | # exceptions on Python 2. 13 | try: 14 | import django 15 | except ImportError: 16 | raise ImportError( 17 | "Couldn't import Django. Are you sure it's installed and " 18 | "available on your PYTHONPATH environment variable? Did you " 19 | "forget to activate a virtual environment?" 20 | ) 21 | raise 22 | execute_from_command_line(sys.argv) 23 | -------------------------------------------------------------------------------- /pyconbalkan/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/about/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/about/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/about/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from markdownx.admin import MarkdownxModelAdmin 3 | 4 | from .models import About 5 | 6 | 7 | class AboutAdmin(MarkdownxModelAdmin): 8 | class Meta: 9 | model = About 10 | 11 | admin.site.register(About, AboutAdmin) 12 | -------------------------------------------------------------------------------- /pyconbalkan/about/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | 3 | from pyconbalkan.about.views import AboutViewSet 4 | 5 | router = routers.DefaultRouter() 6 | router.register(r'about', AboutViewSet) -------------------------------------------------------------------------------- /pyconbalkan/about/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AboutConfig(AppConfig): 5 | name = 'about' 6 | -------------------------------------------------------------------------------- /pyconbalkan/about/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-05-09 17:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='About', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('active', models.BooleanField(default=False)), 19 | ('title', models.CharField(blank=True, max_length=100, null=True)), 20 | ('description', models.TextField(blank=True, null=True)), 21 | ], 22 | options={ 23 | 'abstract': False, 24 | }, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /pyconbalkan/about/migrations/0002_auto_20180604_1346.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-04 13:46 2 | 3 | from django.db import migrations 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('about', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='about', 16 | name='description', 17 | field=markdownx.models.MarkdownxField(blank=True, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/about/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/about/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/about/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from markdownx.models import MarkdownxField 3 | 4 | from pyconbalkan.core.models import SingleActiveModel 5 | 6 | 7 | class About(SingleActiveModel): 8 | title = models.CharField(null=True, blank=True, max_length=100) 9 | description = MarkdownxField(null=True, blank=True) 10 | 11 | def __str__(self): 12 | return self.title -------------------------------------------------------------------------------- /pyconbalkan/about/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from pyconbalkan.about.models import About 4 | 5 | 6 | class AboutSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = About 9 | fields = '__all__' 10 | -------------------------------------------------------------------------------- /pyconbalkan/about/templates/about.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% load static %} 4 | 5 | {% block main_content %} 6 | 7 | {# About #} 8 | 9 |

About Us

10 | {% if about %} 11 |
12 |

13 | {{ about.description|safe }} 14 |

15 |
16 | {% else %} 17 |

18 | Coming Soon 19 |

20 | {% endif %} 21 | 22 | 23 | {% if response_guide %} 24 | 25 |

{{ response_guide.title|safe }}

26 |
27 | {% endif %} 28 | 29 | {% endblock %} 30 | -------------------------------------------------------------------------------- /pyconbalkan/about/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/about/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from rest_framework import viewsets 3 | 4 | from pyconbalkan.about.models import About 5 | from pyconbalkan.about.serializers import AboutSerializer 6 | from pyconbalkan.coc.views import coc_view 7 | from pyconbalkan.organizers.views import organizers_list 8 | 9 | 10 | class AboutViewSet(viewsets.ModelViewSet): 11 | queryset = About.objects.all() 12 | serializer_class = AboutSerializer 13 | 14 | 15 | def about_view(request): 16 | about = About.objects.filter(active=True) 17 | context = { 18 | 'about': about.first() if about else None, 19 | } 20 | return render(request, 'about.html', context) 21 | -------------------------------------------------------------------------------- /pyconbalkan/archive/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/archive/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/archive/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/archive/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ArchiveConfig(AppConfig): 5 | name = 'archive' 6 | -------------------------------------------------------------------------------- /pyconbalkan/archive/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/archive/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/archive/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/archive/templates/archive.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 |

Year {{ conference.year }} in a nutshell

6 | 7 | 8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /pyconbalkan/archive/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/archive/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, get_object_or_404 2 | 3 | 4 | # Create your views here. 5 | from pyconbalkan.conference.models import Conference 6 | 7 | 8 | def archive_detail(request, year): 9 | request.conference = get_object_or_404(Conference, year=year) 10 | return render(request, 'archive.html') 11 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/cfp/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/cfp/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from pyconbalkan.cfp.models import Cfp, CFPRating 4 | 5 | 6 | @admin.register(Cfp) 7 | class CfpAdmin(admin.ModelAdmin): 8 | list_filter = ( 9 | "conference__year", 10 | "active" 11 | ) 12 | autocomplete_fields = ("speaker",) 13 | list_display = ("name", "title", "speaker", "duration", "active",) 14 | list_editable = ("active",) 15 | 16 | 17 | admin.site.register(CFPRating) 18 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | from pyconbalkan.cfp.views import CfpViewSet 3 | 4 | router = routers.DefaultRouter() 5 | router.register(r'cfp', CfpViewSet) 6 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CfpConfig(AppConfig): 5 | name = 'cfp' 6 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/const.py: -------------------------------------------------------------------------------- 1 | TALK = 1 2 | WORKSHOP = 2 3 | TYPE_CFP = ( 4 | (TALK, 'Talk'), 5 | (WORKSHOP, 'Workshop'), 6 | ) -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-05-23 21:44 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Cfp', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=256)), 19 | ('company', models.CharField(blank=True, max_length=100, null=True)), 20 | ('email', models.EmailField(max_length=254)), 21 | ('personal_website', models.URLField(blank=True, null=True)), 22 | ('linkedin', models.URLField(blank=True, null=True)), 23 | ('title', models.CharField(max_length=1024)), 24 | ('description', models.TextField()), 25 | ], 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0002_auto_20180604_1346.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-04 13:46 2 | 3 | from django.db import migrations 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cfp', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='cfp', 16 | name='description', 17 | field=markdownx.models.MarkdownxField(), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0003_auto_20180611_1803.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-11 18:03 2 | import random 3 | import string 4 | 5 | from django.db import migrations, models 6 | from slugify import slugify 7 | 8 | 9 | def create_slug_in_cfp(apps, schema_editor): 10 | # Create slug in Cfp 11 | Cfp = apps.get_model("cfp", "Cfp") 12 | for cfp in Cfp.objects.all(): 13 | cfp.slug = '{}-{}'.format(slugify(cfp.title), ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))) 14 | cfp.accepted = False 15 | cfp.save() 16 | 17 | def remove_slug(apps, schema_editor): 18 | pass 19 | 20 | 21 | class Migration(migrations.Migration): 22 | 23 | dependencies = [ 24 | ('cfp', '0002_auto_20180604_1346'), 25 | ] 26 | 27 | operations = [ 28 | migrations.AddField( 29 | model_name='cfp', 30 | name='accepted', 31 | field=models.BooleanField(default=False), 32 | ), 33 | migrations.AddField( 34 | model_name='cfp', 35 | name='slug', 36 | field=models.CharField(blank=True, max_length=100), 37 | ), 38 | migrations.RunPython(create_slug_in_cfp, remove_slug) 39 | ] 40 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0004_auto_20180611_1814.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-11 18:14 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cfp', '0003_auto_20180611_1803'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='cfp', 15 | name='slug', 16 | field=models.CharField(blank=True, max_length=100, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0005_auto_20180629_1257.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-29 12:57 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cfp', '0004_auto_20180611_1814'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='cfp', 15 | name='duration', 16 | field=models.CharField(max_length=100, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='cfp', 20 | name='type', 21 | field=models.IntegerField(choices=[(1, 'Talk'), (2, 'Workshop')], default=1), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0006_auto_20180807_0944.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-07 09:44 2 | 3 | from django.conf import settings 4 | import django.core.validators 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | import taggit.managers 8 | 9 | 10 | class Migration(migrations.Migration): 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ('taggit', '0002_auto_20150616_2121'), 15 | ('cfp', '0005_auto_20180629_1257'), 16 | ] 17 | 18 | operations = [ 19 | migrations.CreateModel( 20 | name='CFPRating', 21 | fields=[ 22 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 23 | ('mark', models.IntegerField(validators=[django.core.validators.MaxValueValidator(10, 'Maximum rating is 10'), django.core.validators.MinValueValidator(0, 'Minimum Rating is 10')])), 24 | ('cfp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ratings', to='cfp.Cfp')), 25 | ('tags', taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), 26 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 27 | ], 28 | ), 29 | migrations.AlterUniqueTogether( 30 | name='cfprating', 31 | unique_together={('user', 'cfp')}, 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0007_cfprating_comment.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-09 12:58 2 | 3 | from django.db import migrations 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cfp', '0006_auto_20180807_0944'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='cfprating', 16 | name='comment', 17 | field=markdownx.models.MarkdownxField(blank=True, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0008_auto_20180809_1350.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-09 13:50 2 | 3 | import django.core.validators 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cfp', '0007_cfprating_comment'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='cfprating', 16 | name='mark', 17 | field=models.IntegerField(validators=[django.core.validators.MaxValueValidator(10, 'Maximum rating is 10'), django.core.validators.MinValueValidator(1, 'Minimum Rating is 1')]), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0009_auto_20180810_1859.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-10 18:59 2 | 3 | from django.db import migrations 4 | import taggit.managers 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('cfp', '0008_auto_20180809_1350'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='cfprating', 16 | name='tags', 17 | field=taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0010_cfp_active.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-12 18:39 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cfp', '0009_auto_20180810_1859'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='cfp', 15 | name='active', 16 | field=models.BooleanField(default=True), 17 | preserve_default=False 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0011_auto_20181018_1949.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-10-18 19:49 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('cfp', '0010_cfp_active'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='cfp', 15 | name='active', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0012_cfp_conference.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-03 22:09 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import pyconbalkan.conference.models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('conference', '0008_auto_20190303_1800'), 12 | ('cfp', '0011_auto_20181018_1949'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='cfp', 18 | name='conference', 19 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/0013_cfp_speaker.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-27 12:37 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('speaker', '0011_speaker_conference'), 11 | ('cfp', '0012_cfp_conference'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='cfp', 17 | name='speaker', 18 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='speaker.Speaker'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/cfp/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/cfp/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from pyconbalkan.cfp.models import Cfp 4 | 5 | 6 | class CfpSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = Cfp 9 | fields = '__all__' 10 | -------------------------------------------------------------------------------- /pyconbalkan/cfp/templates/cfp_list.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 | {# CFP list #} 6 | 7 | {% if cfps %} 8 |
9 | 18 |
19 | {% endif %} 20 | 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /pyconbalkan/coc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/coc/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/coc/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from markdownx.admin import MarkdownxModelAdmin 3 | from .models import CodeOfConduct, ResponseGuide 4 | 5 | 6 | class CodeOfConductAdmin(MarkdownxModelAdmin): 7 | class Meta: 8 | model = CodeOfConduct 9 | 10 | 11 | class ResponseGuideAdmin(MarkdownxModelAdmin): 12 | class Meta: 13 | model = ResponseGuide 14 | 15 | 16 | admin.site.register(CodeOfConduct, CodeOfConductAdmin) 17 | admin.site.register(ResponseGuide, ResponseGuideAdmin) 18 | -------------------------------------------------------------------------------- /pyconbalkan/coc/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | from .views import CodeOfConductViewSet 3 | 4 | router = routers.DefaultRouter() 5 | router.register(r'coc', CodeOfConductViewSet) 6 | -------------------------------------------------------------------------------- /pyconbalkan/coc/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CodeOfConductConfig(AppConfig): 5 | name = 'coc' 6 | -------------------------------------------------------------------------------- /pyconbalkan/coc/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-22 13:54 2 | 3 | from django.db import migrations, models 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='CodeOfConduct', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('active', models.BooleanField(default=False)), 20 | ('title', models.CharField(blank=True, max_length=100, null=True)), 21 | ('description', markdownx.models.MarkdownxField(blank=True, null=True)), 22 | ], 23 | options={ 24 | 'abstract': False, 25 | }, 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /pyconbalkan/coc/migrations/0002_response_guide.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-22 15:29 2 | 3 | from django.db import migrations, models 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('coc', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='ResponseGuide', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('active', models.BooleanField(default=False)), 19 | ('title', models.CharField(blank=True, max_length=100, null=True)), 20 | ('description', markdownx.models.MarkdownxField(blank=True, null=True)), 21 | ], 22 | options={ 23 | 'abstract': False, 24 | }, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /pyconbalkan/coc/migrations/0003_response_guide_slug.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-22 15:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('coc', '0002_response_guide'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='responseguide', 15 | name='slug', 16 | field=models.CharField(blank=True, max_length=100, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/coc/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/coc/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/coc/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from markdownx.models import MarkdownxField 3 | from pyconbalkan.core.models import SingleActiveModel 4 | from django.utils.text import slugify 5 | 6 | 7 | class CodeOfConduct(SingleActiveModel): 8 | title = models.CharField(null=True, blank=True, max_length=100) 9 | description = MarkdownxField(null=True, blank=True) 10 | 11 | def __str__(self): 12 | return self.title 13 | 14 | 15 | class ResponseGuide(SingleActiveModel): 16 | title = models.CharField(null=True, blank=True, max_length=100) 17 | description = MarkdownxField(null=True, blank=True) 18 | slug = models.CharField(unique=True, blank=True, max_length=100) 19 | 20 | def save(self, *args, **kwargs): 21 | if not self.slug: 22 | self.slug = slugify(self.title) 23 | super(ResponseGuide, self).save(*args, **kwargs) 24 | 25 | def __str__(self): 26 | return self.title 27 | -------------------------------------------------------------------------------- /pyconbalkan/coc/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from .models import CodeOfConduct, ResponseGuide 3 | 4 | 5 | class CodeOfConductSerializer(serializers.ModelSerializer): 6 | class Meta: 7 | model = CodeOfConduct 8 | fields = '__all__' 9 | 10 | 11 | class ResponseGuideSerializer(serializers.ModelSerializer): 12 | class Meta: 13 | model = ResponseGuide 14 | fields = '__all__' 15 | -------------------------------------------------------------------------------- /pyconbalkan/coc/templates/coc.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 | {# Code of Conduct #} 6 |

{% if coc %}{{ coc.title|safe }}{% else %}Code Of Conduct{% endif %}

7 | 8 | {% if coc %} 9 | 10 |
11 | {{ coc.description|safe }} 12 |
13 | {% else %} 14 |

15 | Coming Soon 16 |

17 | {% endif %} 18 | 19 | 20 | {% if response_guide %} 21 | 22 |

{{ response_guide.title|safe }}

23 |
24 | {% endif %} 25 | 26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /pyconbalkan/coc/templates/response_guide.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 | {# Response guide #} 6 | 7 | {% if response_guide %} 8 |

{{ response_guide.title|safe }}

9 | 10 |
11 | {{ response_guide.description|safe }} 12 |
13 | {% else %} 14 |

15 | Coming Soon

16 | {% endif %} 17 | 18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /pyconbalkan/coc/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/coc/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, get_object_or_404 2 | from rest_framework import viewsets 3 | 4 | from .models import CodeOfConduct, ResponseGuide 5 | from .serializers import CodeOfConductSerializer 6 | 7 | 8 | class CodeOfConductViewSet(viewsets.ModelViewSet): 9 | queryset = CodeOfConduct.objects.all() 10 | serializer_class = CodeOfConductSerializer 11 | 12 | 13 | def coc_view(request): 14 | coc = CodeOfConduct.objects.filter(active=True) 15 | r_guide = ResponseGuide.objects.filter(active=True) 16 | context = { 17 | 'coc': coc.first() if coc else None, 18 | 'response_guide': r_guide.first() if r_guide else None, 19 | } 20 | return render(request, 'coc.html', context) 21 | 22 | 23 | def response_guide(request, slug): 24 | r_guide = get_object_or_404(ResponseGuide, active=True, slug=slug) 25 | context = { 26 | 'response_guide': r_guide 27 | } 28 | return render(request, 'response_guide.html', context) 29 | -------------------------------------------------------------------------------- /pyconbalkan/conference/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/conference/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/conference/abstractions.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.utils.translation import ugettext_lazy as _ 3 | 4 | from pyconbalkan.conference.models import Conference 5 | 6 | 7 | class ConferenceFilter(admin.SimpleListFilter): 8 | title = _("Conference year") 9 | parameter_name = "conference" 10 | 11 | def choices(self, changelist): 12 | for lookup, title in self.lookup_choices: 13 | yield { 14 | "selected": self.value() is lookup or self.value() == str(lookup), 15 | "query_string": changelist.get_query_string( 16 | {self.parameter_name: lookup} 17 | ), 18 | "display": title, 19 | } 20 | 21 | def lookups(self, request, model_admin): 22 | choices = [] 23 | for _ in Conference.objects.all(): 24 | if _ == request.conference: 25 | choices.append((None, "{} Current".format(_))) 26 | else: 27 | choices.append((_.id, str(_))) 28 | return choices 29 | 30 | def queryset(self, request, queryset): 31 | return queryset.filter(conference=self.value() or request.conference.pk) 32 | 33 | 34 | class ConferenceAbstractAdmin(admin.ModelAdmin): 35 | list_filter = (ConferenceFilter,) 36 | -------------------------------------------------------------------------------- /pyconbalkan/conference/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from pyconbalkan.conference.abstractions import ConferenceAbstractAdmin 4 | from pyconbalkan.conference.models import Conference, CountDown, MissionStatement 5 | from markdownx.admin import MarkdownxModelAdmin 6 | 7 | 8 | class ConferenceAdmin(admin.ModelAdmin): 9 | class Meta: 10 | model = Conference 11 | 12 | 13 | class CountDownAdmin(ConferenceAbstractAdmin): 14 | class Meta: 15 | model = CountDown 16 | 17 | 18 | class MissionStatementAdmin(ConferenceAbstractAdmin, MarkdownxModelAdmin): 19 | class Meta: 20 | model = MissionStatement 21 | 22 | 23 | admin.site.register(Conference, ConferenceAdmin) 24 | admin.site.register(CountDown, CountDownAdmin) 25 | admin.site.register(MissionStatement, MissionStatementAdmin) -------------------------------------------------------------------------------- /pyconbalkan/conference/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | 3 | from pyconbalkan.conference.views import ConferenceViewSet 4 | 5 | router = routers.DefaultRouter() 6 | router.register(r'conference', ConferenceViewSet) -------------------------------------------------------------------------------- /pyconbalkan/conference/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ConferenceConfig(AppConfig): 5 | name = 'conference' 6 | -------------------------------------------------------------------------------- /pyconbalkan/conference/context.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | singleton = threading.local() 4 | -------------------------------------------------------------------------------- /pyconbalkan/conference/context_processors.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from django import forms 4 | from django.forms import ModelMultipleChoiceField, ChoiceField 5 | from django_select2.forms import Select2Widget, ModelSelect2Widget 6 | 7 | from pyconbalkan.conference.models import Conference 8 | from pyconbalkan.speaker.models import Speaker 9 | from pyconbalkan.sponsors.models import Sponsor 10 | 11 | 12 | class SpeakerForm(forms.Form): 13 | pk = forms.ChoiceField( 14 | label="", 15 | widget=ModelSelect2Widget( 16 | model=Speaker, 17 | search_fields=['full_name__icontains'], 18 | max_results=15 19 | ) 20 | ) 21 | 22 | class Media: 23 | js = ( 24 | 'js/search_people.js', 25 | ) 26 | 27 | 28 | def previous_conferences(request): 29 | return { 30 | 'sidebar_sponsors': Sponsor.objects.filter(sidebar=True, active=True), 31 | 'current_conferences': Conference.objects.filter(year__lte=datetime.datetime.now().year), 32 | 'previous_conferences': Conference.objects.filter(year__lt=datetime.datetime.now().year), 33 | 'search_speakers': SpeakerForm() 34 | } -------------------------------------------------------------------------------- /pyconbalkan/conference/middleware.py: -------------------------------------------------------------------------------- 1 | from pyconbalkan.conference.models import Conference 2 | 3 | 4 | class ConferenceSelectionMiddleware: 5 | def __init__(self, get_response): 6 | self.get_response = get_response 7 | 8 | 9 | def __call__(self, request): 10 | try: 11 | request.conference = Conference.objects.get(active=True) 12 | except Conference.DoesNotExist: 13 | pass 14 | 15 | return self.get_response(request) 16 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0002_mission_statement.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-21 15:07 2 | 3 | from django.db import migrations, models 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('conference', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='MissionStatement', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('active', models.BooleanField(default=False)), 19 | ('content', markdownx.models.MarkdownxField(blank=True, null=True)), 20 | ], 21 | options={ 22 | 'abstract': False, 23 | }, 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0003_auto_20180710_1214.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-07-10 12:14 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('conference', '0002_mission_statement'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='conference', 15 | name='meta_author', 16 | field=models.CharField(blank=True, max_length=200, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='conference', 20 | name='meta_description', 21 | field=models.CharField(blank=True, max_length=200, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0004_auto_20180802_2008.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-02 20:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('conference', '0003_auto_20180710_1214'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='conference', 15 | name='meta_author', 16 | ), 17 | migrations.RemoveField( 18 | model_name='conference', 19 | name='meta_description', 20 | ), 21 | migrations.AddField( 22 | model_name='conference', 23 | name='facebook', 24 | field=models.URLField(blank=True, null=True), 25 | ), 26 | migrations.AddField( 27 | model_name='conference', 28 | name='instagram', 29 | field=models.URLField(blank=True, null=True), 30 | ), 31 | migrations.AddField( 32 | model_name='conference', 33 | name='tickets', 34 | field=models.URLField(blank=True, null=True), 35 | ), 36 | migrations.AddField( 37 | model_name='conference', 38 | name='twitter', 39 | field=models.URLField(blank=True, null=True), 40 | ), 41 | ] 42 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0005_auto_20180804_2148.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-04 21:48 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('conference', '0004_auto_20180802_2008'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='conference', 15 | name='contact_email', 16 | field=models.EmailField(blank=True, max_length=254, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='conference', 20 | name='sponsor_email', 21 | field=models.EmailField(blank=True, max_length=254, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0006_conference_timetable_pdf.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.2 on 2018-11-11 18:11 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('conference', '0005_auto_20180804_2148'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='conference', 15 | name='timetable_pdf', 16 | field=models.FileField(blank=True, null=True, upload_to=''), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0007_auto_20190227_0738.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-02-27 07:38 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('conference', '0006_conference_timetable_pdf'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='conference', 15 | name='year', 16 | field=models.PositiveIntegerField(unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0008_auto_20190303_1800.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.2 on 2019-03-03 18:00 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import pyconbalkan.conference.models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('conference', '0007_auto_20190227_0738'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='countdown', 17 | name='conference', 18 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 19 | ), 20 | migrations.AddField( 21 | model_name='missionstatement', 22 | name='conference', 23 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0009_remove_conference_timetable_pdf.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-09-08 12:28 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('conference', '0008_auto_20190303_1800'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='conference', 15 | name='timetable_pdf', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0010_conference_conference_logo.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-09-21 20:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('conference', '0009_remove_conference_timetable_pdf'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='conference', 15 | name='conference_logo', 16 | field=models.ImageField(blank=True, null=True, upload_to=''), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/0011_conference_workshop_application_embed_code.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-09-22 19:03 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('conference', '0010_conference_conference_logo'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='conference', 15 | name='workshop_application_embed_code', 16 | field=models.TextField(blank=True, null=True, verbose_name='Embed code that is usually an iframe from google docs'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/conference/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/conference/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/conference/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from pyconbalkan.conference.models import Conference 4 | 5 | 6 | class ConferenceSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = Conference 9 | fields = '__all__' 10 | -------------------------------------------------------------------------------- /pyconbalkan/conference/static/js/search_people.js: -------------------------------------------------------------------------------- 1 | $('#menu__search__speakers select').change(function(){ 2 | $('#menu__search__speakers').submit(); 3 | }); -------------------------------------------------------------------------------- /pyconbalkan/conference/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/conference/views.py: -------------------------------------------------------------------------------- 1 | from rest_framework import viewsets 2 | 3 | from pyconbalkan.conference.models import Conference 4 | from pyconbalkan.conference.serializers import ConferenceSerializer 5 | 6 | 7 | class ConferenceViewSet(viewsets.ModelViewSet): 8 | queryset = Conference.objects.all() 9 | serializer_class = ConferenceSerializer 10 | -------------------------------------------------------------------------------- /pyconbalkan/contact/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/contact/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/contact/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import Contact 3 | 4 | 5 | class ContactAdmin(admin.ModelAdmin): 6 | class Meta: 7 | model = Contact 8 | 9 | 10 | admin.site.register(Contact, ContactAdmin) 11 | -------------------------------------------------------------------------------- /pyconbalkan/contact/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | from pyconbalkan.contact.views import ContactViewSet 3 | 4 | 5 | router = routers.DefaultRouter() 6 | router.register(r'contact', ContactViewSet) 7 | -------------------------------------------------------------------------------- /pyconbalkan/contact/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ContactConfig(AppConfig): 5 | name = 'contact' 6 | -------------------------------------------------------------------------------- /pyconbalkan/contact/decorators.py: -------------------------------------------------------------------------------- 1 | from functools import wraps 2 | 3 | from django.conf import settings 4 | from django.contrib import messages 5 | 6 | import requests 7 | 8 | 9 | def check_recaptcha(view_func): 10 | @wraps(view_func) 11 | def _wrapped_view(request, *args, **kwargs): 12 | request.recaptcha_is_valid = None 13 | if request.method == 'POST': 14 | recaptcha_response = request.POST.get('g-recaptcha-response') 15 | data = { 16 | 'secret': settings.RECAPTCHA_SECRET_KEY, 17 | 'response': recaptcha_response 18 | } 19 | r = requests.post('https://www.google.com/recaptcha/api/siteverify', data=data) 20 | result = r.json() 21 | if result['success']: 22 | request.recaptcha_is_valid = True 23 | else: 24 | request.recaptcha_is_valid = False 25 | messages.error(request, 'Invalid reCAPTCHA. Please try again.') 26 | return view_func(request, *args, **kwargs) 27 | return _wrapped_view 28 | -------------------------------------------------------------------------------- /pyconbalkan/contact/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.forms import ModelForm 3 | 4 | from pyconbalkan.contact.models import Contact 5 | 6 | 7 | class ContactForm(ModelForm): 8 | name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Name', 'class': 'form-control'}), 9 | max_length=256, error_messages={'required': 'Please, enter your name.'}, label='') 10 | company = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Company', 'class': 'form-control'}), 11 | max_length=100, required=False, label='') 12 | email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'Email', 'class': 'form-control'}), 13 | error_messages={'required': 'Please, enter a valid email address.', 14 | 'invalid': 'Please enter a valid email address.'}, label='') 15 | message = forms.CharField(widget=forms.Textarea(attrs={'placeholder': 'Message', 'class': 'form-control'}), 16 | error_messages={'required': 'Please, enter your message.'}, label='') 17 | 18 | class Meta: 19 | model = Contact 20 | fields = '__all__' -------------------------------------------------------------------------------- /pyconbalkan/contact/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-05-19 14:11 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Contact', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=256)), 19 | ('company', models.CharField(blank=True, max_length=100, null=True)), 20 | ('email', models.EmailField(max_length=254)), 21 | ('message', models.TextField()), 22 | ], 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /pyconbalkan/contact/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/contact/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/contact/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | 4 | class Contact(models.Model): 5 | name = models.CharField(max_length=256) 6 | company = models.CharField(max_length=100, null=True, blank=True) 7 | email = models.EmailField() 8 | message = models.TextField() 9 | 10 | def __str__(self): 11 | contact_str = '{} | {}'.format(self.name, self.email) 12 | if self.company: 13 | return '{} | {}'.format(contact_str, self.company) 14 | return contact_str 15 | 16 | -------------------------------------------------------------------------------- /pyconbalkan/contact/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from pyconbalkan.contact.models import Contact 3 | 4 | 5 | class ContactSerializer(serializers.ModelSerializer): 6 | class Meta: 7 | model = Contact 8 | fields = '__all__' 9 | -------------------------------------------------------------------------------- /pyconbalkan/contact/templates/contact_form/contact.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 | {# Contact #} 6 | 7 |

Contact Us!

8 | 9 |

We'd love to hear from you!
10 | If you have any questions, feel free to contact us.

11 | 12 |
13 |
14 | {% csrf_token %} 15 | {{ form.as_p }} 16 | 17 |
18 | 19 |
20 |
21 | 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /pyconbalkan/contact/templates/contact_form/success.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 | {# Contact #} 6 | 7 |

Contact Us!

8 |

Your message was sent successfully!
9 |

10 | Thank you for contacting us, we will get back to you as soon as possible. 11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /pyconbalkan/contact/tests.py: -------------------------------------------------------------------------------- 1 | from model_mommy import mommy 2 | from rest_framework.test import APITestCase 3 | from rest_framework import status 4 | from pyconbalkan.contact.models import Contact 5 | 6 | 7 | class ContactTests(APITestCase): 8 | def setUp(self): 9 | self.conference = mommy.make('conference.Conference', active=True) 10 | 11 | def test_contact_valid(self): 12 | number_existing_contacts = Contact.objects.count() 13 | data = {'name': 'client_name', 'company': '', 'email': 'client@client.com', 'message': 'Hi.....'} 14 | response = self.client.post('/api/contact/', data, format='json') 15 | self.assertEqual(response.status_code, status.HTTP_201_CREATED) 16 | self.assertEqual(Contact.objects.count(), number_existing_contacts + 1) 17 | 18 | def test_contact_invalid(self): 19 | data = {'name': 'client_name', 'company': '', 'email': 'clientlient.com', 'message': 'Hi.....'} 20 | response = self.client.post('/api/contact/', data, format='json') 21 | self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) 22 | -------------------------------------------------------------------------------- /pyconbalkan/contact/views.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.core.mail import EmailMessage 3 | from django.http import HttpResponseRedirect 4 | from django.shortcuts import render 5 | from django.urls import reverse 6 | from rest_framework import viewsets 7 | from rest_framework.permissions import AllowAny 8 | 9 | from pyconbalkan.contact.decorators import check_recaptcha 10 | from pyconbalkan.contact.models import Contact 11 | from pyconbalkan.contact.serializers import ContactSerializer 12 | from .forms import ContactForm 13 | 14 | 15 | class ContactViewSet(viewsets.ModelViewSet): 16 | queryset = Contact.objects.all() 17 | serializer_class = ContactSerializer 18 | permission_classes = [AllowAny] 19 | 20 | 21 | @check_recaptcha 22 | def contact_view(request): 23 | form = ContactForm() 24 | if request.method == 'POST': 25 | form = ContactForm(request.POST) 26 | if form.is_valid() and request.recaptcha_is_valid: 27 | contact = form.save() 28 | # Send Email to info@pyconbalkan.com 29 | EmailMessage( 30 | subject='Contact Us: {}'.format(contact.name), 31 | body=str(contact.message), 32 | from_email='website@pyconbalkan.com', 33 | to=['info@pyconbalkan.com'], 34 | reply_to=[contact.email], 35 | ).send() 36 | return HttpResponseRedirect(reverse("contact_success")) 37 | 38 | context = { 39 | 'form': form, 40 | "RECAPTCHA_SITE_KEY": settings.RECAPTCHA_SITE_KEY, 41 | } 42 | return render(request, "contact_form/contact.html", context) 43 | -------------------------------------------------------------------------------- /pyconbalkan/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/core/admin.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoreConfig(AppConfig): 5 | name = 'core' 6 | 7 | -------------------------------------------------------------------------------- /pyconbalkan/core/api_urls.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/api_urls.py -------------------------------------------------------------------------------- /pyconbalkan/core/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoreConfig(AppConfig): 5 | name = 'core' 6 | -------------------------------------------------------------------------------- /pyconbalkan/core/loaders.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | 3 | from django.template import TemplateDoesNotExist 4 | from django.template.loaders.app_directories import Loader 5 | 6 | from pyconbalkan.conference.context import singleton 7 | 8 | 9 | class PyconLoader(Loader): 10 | def get_template(self, template_name, skip=None): 11 | if not hasattr(singleton, "conference"): 12 | raise TemplateDoesNotExist( 13 | "Conference object not be found in context, skipping." 14 | ) 15 | template_basename = "{:d}_{}".format( 16 | singleton.conference.year, path.basename(template_name) 17 | ) 18 | template_name = path.join(path.dirname(template_name), template_basename) 19 | 20 | return super(PyconLoader, self).get_template(template_name, skip=None) 21 | -------------------------------------------------------------------------------- /pyconbalkan/core/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/core/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django_countries.fields import CountryField 3 | from markdownx.models import MarkdownxField 4 | from slugify import slugify 5 | 6 | 7 | class Person(models.Model): 8 | full_name = models.CharField(max_length=256, null=True) 9 | name = models.CharField(max_length=256, blank=True, null=True) 10 | 11 | date_of_birth = models.DateField(blank=True, null=True) 12 | job = models.CharField(max_length=100, blank=True, null=True) 13 | company = models.CharField(max_length=100, blank=True, null=True) 14 | personal_website = models.URLField(blank=True, null=True) 15 | github = models.URLField(blank=True, null=True) 16 | linkedin = models.URLField(blank=True, null=True) 17 | facebook = models.URLField(blank=True, null=True) 18 | twitter = models.URLField(blank=True, null=True) 19 | slug = models.CharField(unique=True, blank=True, max_length=100) 20 | description = MarkdownxField(blank=True, default='') 21 | email = models.EmailField(blank=True, null=True) 22 | country = CountryField(null=True, blank=True) 23 | 24 | def save(self, *args, **kwargs): 25 | if not self.slug: 26 | self.slug = slugify(self.full_name) 27 | super(Person, self).save(*args, **kwargs) 28 | 29 | class Meta: 30 | abstract = True 31 | 32 | def __str__(self): 33 | return self.name if self.name else str(self.id) 34 | 35 | 36 | class ActiveModel(models.Model): 37 | active = models.BooleanField(default=False) 38 | 39 | class Meta: 40 | abstract = True 41 | 42 | 43 | class SingleActiveModel(ActiveModel): 44 | 45 | class Meta: 46 | abstract = True 47 | 48 | def save(self, *args, **kwargs): 49 | if self.active: 50 | # select all other active items 51 | qs = type(self).objects.filter(active=True) 52 | # except self (if self already exists) 53 | if self.pk: 54 | qs = qs.exclude(pk=self.pk) 55 | # and deactive them 56 | qs.update(active=False) 57 | 58 | super(SingleActiveModel, self).save(*args, **kwargs) 59 | 60 | -------------------------------------------------------------------------------- /pyconbalkan/core/routers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | 3 | 4 | class DefaultRouter(routers.DefaultRouter): 5 | """ 6 | Extends `DefaultRouter` class to add a method for extending url routes from another router. 7 | """ 8 | def extend(self, router): 9 | """ 10 | Extend the routes with url routes of the passed in router. 11 | 12 | Args: 13 | router: SimpleRouter instance containing route definitions. 14 | """ 15 | self.registry.extend(router.registry) -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/_fonts.css: -------------------------------------------------------------------------------- 1 | /* Fonts */ 2 | 3 | @import url('https://fonts.googleapis.com/css?family=Montserrat:400,700'); 4 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/button.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Button 3 | */ 4 | 5 | .button { 6 | display: inline-block; 7 | font-family: "Montserrat", sans-serif; 8 | font-size: 1.4rem; 9 | font-weight: 400; 10 | width: auto; 11 | line-height: 40px; 12 | padding: 0 20px; 13 | border: 0; 14 | border-radius: 4px; 15 | background-color: transparent; 16 | color: white; 17 | text-decoration: none; 18 | cursor: pointer; 19 | } 20 | 21 | .button:hover { 22 | background-color: #28AAE1; 23 | color: #fff; 24 | } 25 | 26 | .button i { 27 | color: white; 28 | } 29 | 30 | .button i.fas, 31 | .button i.far { 32 | border-right: 1px solid rgba(255,255,255,.3) 33 | } 34 | 35 | /* Modifiers */ 36 | 37 | .button--push { 38 | float: right; 39 | } 40 | 41 | .button--fullwidth { 42 | width: 100%; 43 | } 44 | 45 | .button--yellow { 46 | color: #000; 47 | background-color: #F3D66C !important; 48 | } 49 | 50 | .button--blue { 51 | background-color: #28AAE1; 52 | } 53 | 54 | .button-yellow:hover, 55 | .button--blue:hover { 56 | color: white; 57 | background-color: #343C3E !important; 58 | } 59 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/countdown.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Countdown 3 | * Timer in the home page. 4 | */ 5 | 6 | h1.countdownTitle { 7 | padding-bottom: 10px; 8 | } 9 | 10 | .countdown { 11 | display: flex; 12 | padding-top: 10px; 13 | padding-bottom: 20px; 14 | } 15 | @media (max-width: 768px) { 16 | .countdown { 17 | flex-direction: column; 18 | } 19 | 20 | .countdown__time { 21 | padding-top: 3em; 22 | } 23 | } 24 | 25 | .countdown__days { 26 | font-family: 'Montserrat', sans-serif; 27 | font-weight: 700; 28 | font-size: 4rem; 29 | color: #28AAE1; 30 | margin-right: 20px; 31 | } 32 | 33 | .countdown__days__number { 34 | padding: 10px 20px; 35 | border-radius: 5px; 36 | background-color: #2BAAE1; 37 | color: white; 38 | } 39 | 40 | .countdown__time { 41 | flex: 1; 42 | display: flex; 43 | width: 300px; 44 | } 45 | 46 | .countdown__time__digit { 47 | text-align: center; 48 | } 49 | 50 | .countdown__time__number { 51 | min-width: 35px; 52 | display: block; 53 | font-size: 2.9rem; 54 | color: #2BAAE1; 55 | } 56 | 57 | .countdown__time__dots { 58 | display: block; 59 | font-size: 2.9rem; 60 | color: #2BAAE1; 61 | } 62 | 63 | .countdown__time__text { 64 | display: block; 65 | color: #2BAAE1; 66 | } 67 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/datepicker.css: -------------------------------------------------------------------------------- 1 | .ui-datepicker { 2 | background-color: #32383A; 3 | border: 1px solid #66AFE9; 4 | border-radius: 4px; 5 | box-shadow: 0 0 8px rgba(102,175,233,.6); 6 | display: none; 7 | margin-top: 4px; 8 | padding: 10px; 9 | width: 240px; 10 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/event-sidebar.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Event Sidebar 3 | * Website left sidebar with the event info. 4 | */ 5 | 6 | .event-sidebar { 7 | grid-area: sidebar; 8 | } 9 | 10 | @media (max-width: 1280px) { 11 | .event-sidebar { 12 | padding: 0 20px; 13 | } 14 | } 15 | 16 | .event-sidebar__title > h1, 17 | .event-sidebar__title > h2, 18 | .event-sidebar__title > h3 { 19 | font-family: 'Montserrat', sans-serif; 20 | } 21 | 22 | .event-sidebar__text { 23 | margin: 0 0 10px 0; 24 | } 25 | 26 | .event-sidebar__text:last-of-type { 27 | margin-bottom: 40px; 28 | } 29 | 30 | @media (max-width: 1280px) { 31 | .event-sidebar__text { 32 | margin: 10px auto 20px auto; 33 | } 34 | } 35 | 36 | .event-sidebar__icon { 37 | width: 20px; 38 | color: #666; 39 | } 40 | 41 | .event-button__wrapper { 42 | 43 | } 44 | 45 | @media (max-width: 1280px) { 46 | .event-button__wrapper { 47 | margin: 10px auto 20px auto; 48 | } 49 | } 50 | 51 | .supported-by { 52 | padding-top: 20px; 53 | border-top: 1px solid rgba(0,0,0,.1); 54 | margin-bottom: 20px; 55 | } 56 | 57 | .supported-by-img { 58 | display: flex; 59 | align-items: center; 60 | height: 100px; 61 | } 62 | 63 | .supported-by-img img{ 64 | width: 180px; 65 | height: auto; 66 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/faq-accordion.css: -------------------------------------------------------------------------------- 1 | .accordion { 2 | background-color: #eee; 3 | color: #444; 4 | cursor: pointer; 5 | padding: 18px; 6 | width: 100%; 7 | border: none; 8 | text-align: left; 9 | outline: none; 10 | font-size: 15px; 11 | transition: 0.4s; 12 | } 13 | 14 | .accordion:hover { 15 | background-color: #ccc; 16 | } 17 | 18 | .accordion:after { 19 | content: "\25BA"; /* "play" icon */ 20 | float: right; 21 | color: #454444; 22 | font-size: 18px; 23 | line-height: 22px; 24 | /* rotate "play" icon from > (right arrow) to down arrow */ 25 | -webkit-transform: rotate(90deg); 26 | -moz-transform: rotate(90deg); 27 | -ms-transform: rotate(90deg); 28 | -o-transform: rotate(90deg); 29 | transform: rotate(90deg); 30 | } 31 | 32 | .active:after { 33 | /* rotate "play" icon from > (right arrow) to ^ (up arrow) */ 34 | -webkit-transform: rotate(-90deg); 35 | -moz-transform: rotate(-90deg); 36 | -ms-transform: rotate(-90deg); 37 | -o-transform: rotate(-90deg); 38 | transform: rotate(-90deg); 39 | color: #F58723; 40 | } 41 | 42 | .panel { 43 | padding: 0 18px; 44 | background-color: #dde1e2; 45 | max-height: 0; 46 | overflow: hidden; 47 | transition: max-height 0.2s ease-out; 48 | } 49 | 50 | /* p { 51 | margin: 20px; 52 | } */ -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/featured-letter.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Featured Letter 3 | * Colored letter on titles. 4 | */ 5 | 6 | .featured-letter { 7 | } 8 | 9 | /* Modifiers */ 10 | 11 | .featured-letter--blue { 12 | color: #28AAE1; 13 | } 14 | 15 | .featured-letter--yellow { 16 | color: #F3D66C; 17 | } 18 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/flag.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Flag 3 | * Usually
elements representing a line. 4 | */ 5 | 6 | i.flag { 7 | width: 30px; 8 | height: 20px; 9 | padding-right: 20px; 10 | border-right: 1px solid rgba(0,0,0,.1); 11 | margin-right: 10px; 12 | background-size: 20px auto; 13 | background-position: left center; 14 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/line.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Line 3 | * Usually
elements representing a line. 4 | */ 5 | 6 | .line { 7 | width: 40px; 8 | height: 2px; 9 | margin: 20px 0 40px 0; 10 | border: 0; 11 | background-color: #28AAE1; 12 | } 13 | 14 | .long { 15 | width: 100%; 16 | margin: 40px 0; 17 | background-color: rgba(255,255,255,.3); 18 | } 19 | 20 | .line__centered { 21 | margin: 40px auto; 22 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/long-text.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Long Text 3 | * Container for texts like the one in the about page. 4 | */ 5 | 6 | .long-text { 7 | color: #666; 8 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/sponsors.css: -------------------------------------------------------------------------------- 1 | .catch { 2 | color: white; 3 | margin: 30px 0 40px 0; 4 | } 5 | 6 | .catch p { 7 | padding: 0 180px; 8 | } 9 | 10 | @media (max-width: 1280px) { 11 | .catch p { 12 | padding: 0px; 13 | } 14 | } 15 | 16 | .keynote-list { 17 | display: flex; 18 | flex-flow: row wrap; 19 | justify-content: flex-start; 20 | } 21 | 22 | .keynote-item { 23 | position: relative; 24 | } 25 | 26 | .sponsor-list { 27 | display: flex; 28 | flex-flow: row wrap; 29 | justify-content: center; 30 | border-bottom: 2px solid white; 31 | padding-bottom: 30px; 32 | } 33 | 34 | .sponsor { 35 | color: #F3D66C; 36 | } 37 | 38 | .sponsor img { 39 | display: block; 40 | object-fit: cover; 41 | } 42 | 43 | .card__info { 44 | display: inline-block; 45 | position: relative; 46 | top: -60px; 47 | padding: 20px; 48 | } 49 | 50 | .cfp__description { 51 | margin-bottom: 20px; 52 | } 53 | 54 | .cfp__comment { 55 | margin-bottom: 0; 56 | } 57 | 58 | @media (max-width: 767px) { 59 | .card__info { 60 | top: -170px; 61 | left: 160px; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/title.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Title 3 | * Heading components. 4 | */ 5 | 6 | h1, 7 | h2, 8 | h3, 9 | h4 { 10 | display: flex; 11 | align-items: center; 12 | line-height: initial; 13 | text-align: left; 14 | text-decoration: none; 15 | } 16 | 17 | h1 { 18 | font-size: 2.4rem; 19 | font-weight: 700; 20 | margin: 0 0 20px 0; 21 | color: #343C3E; 22 | } 23 | 24 | h2 { 25 | font-size: 2rem; 26 | font-weight: 700; 27 | padding-top: 20px; 28 | margin: 0 0 20px 0; 29 | color: #666; 30 | } 31 | 32 | h3 { 33 | font-size: 1.8rem; 34 | font-weight: 600; 35 | padding-top: 20px; 36 | margin: 0 0 10px 0; 37 | color: #28aae1; 38 | } 39 | 40 | h4 { 41 | font-size: 1.6rem; 42 | font-weight: 400; 43 | margin: 0 0 10px 0; 44 | color: #b4b4b4; 45 | } 46 | 47 | .fas, 48 | .far { 49 | font-size: 14px; 50 | margin-right: 10px; 51 | border-right: 1px solid rgba(0,0,0,.1); 52 | padding-right: 10px; 53 | box-sizing: content-box; 54 | color: #28AAE1; 55 | } 56 | 57 | .fa-star { 58 | color: #FFD64F; 59 | } 60 | 61 | .centered { 62 | text-align: center; 63 | } 64 | 65 | .sponsors, 66 | .keystone, 67 | .platinum, 68 | .gold, 69 | .silver, 70 | .partner, 71 | .mediapartner { 72 | position: absolute; 73 | top: 0; 74 | right: 0; 75 | display: inline-block; 76 | font-size: 1.2rem; 77 | font-weight: 700; 78 | padding: 2px 8px; 79 | color: #666; 80 | } 81 | 82 | .keystone { 83 | background-color: #343C3E; 84 | color: white; 85 | font-size: 1.4rem; 86 | } 87 | 88 | .platinum { 89 | background-color: lightgray; 90 | } 91 | 92 | .gold { 93 | background-color: gold; 94 | } 95 | 96 | .silver { 97 | background-color: silver; 98 | color: white; 99 | } 100 | 101 | .partner { 102 | background-color: #28AAE1; 103 | color: white; 104 | } 105 | 106 | .mediapartner { 107 | background-color: plum; 108 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/tooltip.css: -------------------------------------------------------------------------------- 1 | .tooltip { 2 | position: relative; 3 | display: inline-block; 4 | border-bottom: 1px dotted black; 5 | } 6 | 7 | .tooltip .tooltiptext { 8 | visibility: hidden; 9 | width: 120px; 10 | background-color: #555; 11 | color: #fff; 12 | text-align: center; 13 | border-radius: 6px; 14 | padding: 5px 0; 15 | position: absolute; 16 | z-index: 1; 17 | bottom: 125%; 18 | left: 50%; 19 | margin-left: -60px; 20 | opacity: 0; 21 | transition: opacity 0.3s; 22 | } 23 | 24 | .tooltip .tooltiptext::after { 25 | content: ""; 26 | position: absolute; 27 | top: 100%; 28 | left: 50%; 29 | margin-left: -5px; 30 | border-width: 5px; 31 | border-style: solid; 32 | border-color: #555 transparent transparent transparent; 33 | } 34 | 35 | .tooltip:hover .tooltiptext { 36 | visibility: visible; 37 | opacity: 1; 38 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/components/volunteer.css: -------------------------------------------------------------------------------- 1 | #id_country { 2 | height: 40px; 3 | } 4 | 5 | #id_profile_picture{ 6 | color: white; 7 | } 8 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/css/helpers/spacing.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Padding and margin helpers. 3 | */ 4 | 5 | /* Margin top */ 6 | 7 | .mt-xs-20 { 8 | margin-top: 20px; 9 | } 10 | 11 | .mt-xs-40 { 12 | margin-top: 40px; 13 | } 14 | 15 | /* Margin bottom */ 16 | 17 | .mb-xs-20 { 18 | margin-bottom: 20px; 19 | } 20 | 21 | .mb-xs-40 { 22 | margin-bottom: 40px; 23 | } 24 | 25 | .mb-xs-80 { 26 | margin-bottom: 80px; 27 | } 28 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/belgrade_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/belgrade_1.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/belgrade_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/belgrade_2.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/belgrade_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/belgrade_3.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/belgrade_4.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/belgrade_4.JPG -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/burger-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/burger-menu.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/burger-menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/clock.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/close.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 10 | 12 | 13 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/django-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/django-logo.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/email-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | Mail.Ru icon 3 | 4 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/email.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Mail.Ru icon 9 | 14 | 15 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/euro-python-society.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/euro-python-society.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/facebook-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/facebook.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/favicon-16x16.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/favicon-32x32.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/front-light-pyConBlkn-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/front-light-pyConBlkn-2.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/hilton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/hilton.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/instagram-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 11 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/instagram.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 11 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/linkedin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/pfs-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/pfs-logo.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/pycon-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/pycon-logo.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/pycon-sig-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/pycon-sig-logo.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/pycon_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/pycon_logo.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/python-bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/python-bullet.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/python-bullet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 9 | 10 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/sidebar-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/sidebar-bg.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/sidebar-bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/snake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/snake.png -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/travel_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/travel_1.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/twitter-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/twitter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/venue_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/venue_1.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/venue_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/venue_2.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/venue_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/img/venue_3.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/img/website.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/js/accordion.js: -------------------------------------------------------------------------------- 1 | var acc = document.getElementsByClassName("accordion"); 2 | var i; 3 | 4 | for (i = 0; i < acc.length; i++) { 5 | acc[i].addEventListener("click", function() { 6 | this.classList.toggle("active"); 7 | var panel = this.nextElementSibling; 8 | if (panel.style.maxHeight){ 9 | panel.style.maxHeight = null; 10 | } else { 11 | panel.style.maxHeight = panel.scrollHeight + "px"; 12 | } 13 | }); 14 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/js/go_to_top.js: -------------------------------------------------------------------------------- 1 | function topFunction() { 2 | document.body.scrollTop = 0; 3 | document.documentElement.scrollTop = 0; 4 | } -------------------------------------------------------------------------------- /pyconbalkan/core/static/js/menu.js: -------------------------------------------------------------------------------- 1 | $('div.mobile-button').click(function(e) { 2 | e.preventDefault(); 3 | $('nav.menu').toggleClass('active'); 4 | }); 5 | 6 | $('.dropdown').click(function(e) { 7 | $('.dropdown').not(this).removeClass('active'); 8 | $(this).toggleClass('active'); 9 | }); 10 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/js/timer.js: -------------------------------------------------------------------------------- 1 | // Update the count down every 1 second 2 | var x = setInterval(function() { 3 | 4 | if (document.getElementById("days")) { 5 | // Get today's date and time 6 | var now = new Date().getTime(); 7 | 8 | // Find the distance between now an the count down date 9 | var distance = countDownDate - now; 10 | 11 | // Time calculations for days, hours, minutes and seconds 12 | var days = Math.floor(distance / (1000 * 60 * 60 * 24)); 13 | var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); 14 | var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); 15 | var seconds = Math.floor((distance % (1000 * 60)) / 1000); 16 | 17 | // Output the result in an element with id="demo" 18 | document.getElementById("days").innerHTML = days; 19 | document.getElementById("hours").innerHTML = hours; 20 | document.getElementById("minutes").innerHTML = minutes; 21 | document.getElementById("seconds").innerHTML = seconds; 22 | 23 | // If the count down is over, write some text 24 | if (distance < 0) { 25 | clearInterval(x); 26 | document.getElementById("days").innerHTML = "0"; 27 | document.getElementById("hours").innerHTML = "0"; 28 | document.getElementById("minutes").innerHTML = "0"; 29 | document.getElementById("seconds").innerHTML = "0"; 30 | } 31 | } 32 | }, 1000); 33 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/js/timetable.js: -------------------------------------------------------------------------------- 1 | $(".btn-room").click(function() { 2 | let roomNumber = this.innerHTML; 3 | $(".btn-room").removeClass('button--yellow'); 4 | $(".presentations").addClass('hidden'); 5 | $("." + roomNumber).removeClass('hidden'); 6 | $(".btn-" + roomNumber).addClass('button--yellow'); 7 | }); -------------------------------------------------------------------------------- /pyconbalkan/core/static/js/volunteer.js: -------------------------------------------------------------------------------- 1 | $( ".datepicker" ).datepicker({ 2 | changeMonth: true, 3 | changeYear: true, 4 | yearRange: "1900:2018" 5 | }); 6 | 7 | $("#id_description").addClass("form-control"); 8 | -------------------------------------------------------------------------------- /pyconbalkan/core/static/organizers/volunteer/profile_picture/1528646012025.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/organizers/volunteer/profile_picture/1528646012025.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/pdf/coc_pyconbalkan.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/pdf/coc_pyconbalkan.pdf -------------------------------------------------------------------------------- /pyconbalkan/core/static/pdf/pycon-balkan-2018-timetable.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/pdf/pycon-balkan-2018-timetable.pdf -------------------------------------------------------------------------------- /pyconbalkan/core/static/pdf/pycon-sponsors-brochure-2019.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/pdf/pycon-sponsors-brochure-2019.pdf -------------------------------------------------------------------------------- /pyconbalkan/core/static/pdf/pycon_brochure.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/pdf/pycon_brochure.pdf -------------------------------------------------------------------------------- /pyconbalkan/core/static/sponsors/logo/1553191407426.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/sponsors/logo/1553191407426.jpg -------------------------------------------------------------------------------- /pyconbalkan/core/static/video/pycon-bg-2019-loop.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/static/video/pycon-bg-2019-loop.mp4 -------------------------------------------------------------------------------- /pyconbalkan/core/storage.py: -------------------------------------------------------------------------------- 1 | import os 2 | from time import time 3 | 4 | from django.conf import settings 5 | from django.core.files.storage import FileSystemStorage 6 | from storages.backends.s3boto3 import S3Boto3Storage 7 | 8 | 9 | class UniqueNameMixin(object): 10 | def get_timestamped_name(self, name, max_length=None): 11 | """ 12 | Return a filename that's free on the target storage system and 13 | available for new content to be written to. 14 | """ 15 | milisecond = str(int(round(time() * 1000))) 16 | extension = name.split('.')[-1].strip().lower() if '.' in name else 'none' 17 | 18 | return '{}.{}'.format(milisecond, extension) 19 | 20 | def generate_filename(self, filename): 21 | """ 22 | Validate the filename by calling get_valid_name() and return a filename 23 | to be passed to the save() method. 24 | """ 25 | # `filename` may include a path as returned by FileField.upload_to. 26 | dirname, filename = os.path.split(filename) 27 | return os.path.normpath(os.path.join(dirname, self.get_timestamped_name(filename))) 28 | 29 | 30 | class S3Storage(UniqueNameMixin, S3Boto3Storage): 31 | bucket_name = settings.AWS_S3_BUCKET_NAME 32 | 33 | 34 | class LocalStorage(UniqueNameMixin, FileSystemStorage): 35 | def generate_filename(self, filename): 36 | filename = os.path.join("static", filename) 37 | return super().generate_filename(filename) 38 | 39 | -------------------------------------------------------------------------------- /pyconbalkan/core/templates/includes/event_sidebar.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 38 | -------------------------------------------------------------------------------- /pyconbalkan/core/templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 | {% if form.errors %} 6 |

Your username and password didn't match. Please try again.

7 | {% endif %} 8 | 9 | {% if next %} 10 | {% if user.is_authenticated %} 11 |

Your account doesn't have access to this page. To proceed, 12 | please login with an account that has access.

13 | {% else %} 14 |

Please login to see this page.

15 | {% endif %} 16 | {% endif %} 17 | 18 |
19 | {% csrf_token %} 20 | 21 |
22 | {{ form.username.label_tag }} 23 | {{ form.username }} 24 |
25 |
26 | {{ form.password.label_tag }} 27 | {{ form.password }} 28 |
29 | 30 |
31 | 32 | 33 |
34 |
35 | 36 | {# Assumes you setup the password_reset view in your URLconf #} 37 |

Lost password?

38 | 39 | {% endblock %} -------------------------------------------------------------------------------- /pyconbalkan/core/templates/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: /timetable 3 | Disallow: /info 4 | Disallow: /admin -------------------------------------------------------------------------------- /pyconbalkan/core/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/core/templatetags/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/core/templatetags/startswith.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | 6 | @register.filter('startswith') 7 | def startswith(text, starts): 8 | if isinstance(text, str): 9 | return text.startswith(starts) 10 | return False -------------------------------------------------------------------------------- /pyconbalkan/core/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/core/views.py: -------------------------------------------------------------------------------- 1 | from django.db.models import Q 2 | from django.shortcuts import render 3 | 4 | from pyconbalkan.conference.models import CountDown, MissionStatement 5 | from pyconbalkan.news.models import Post 6 | from pyconbalkan.speaker.models import Speaker 7 | from pyconbalkan.sponsors.models import Sponsor, SponsorshipLevel 8 | from pyconbalkan.timetable.models import Presentation 9 | 10 | 11 | def home(request): 12 | count_down = CountDown.objects.filter(active=True) 13 | keynotes = Speaker.objects.filter( 14 | presentations__active=True, 15 | presentations__type=Presentation.KEYNOTE, 16 | presentations__conference__active=True 17 | ).order_by("full_name") 18 | 19 | keystone_sponsors = Sponsor.objects.filter(level=SponsorshipLevel.keystone, active=True, conference__active=True) 20 | platinum_sponsors = Sponsor.objects.filter(level=SponsorshipLevel.platinum, active=True, conference__active=True) 21 | gold_sponsors = Sponsor.objects.filter(level=SponsorshipLevel.gold, active=True, conference__active=True) 22 | silver_sponsors = Sponsor.objects.filter(level=SponsorshipLevel.silver, active=True, conference__active=True) 23 | partners = Sponsor.objects.filter(level=SponsorshipLevel.partner, active=True) 24 | mission_statement = MissionStatement.objects.filter(active=True) 25 | 26 | context = { 27 | "keynotes": keynotes, 28 | "keystone_sponsors": keystone_sponsors, 29 | "platinum_sponsors": platinum_sponsors, 30 | "gold_sponsors": gold_sponsors, 31 | "silver_sponsors": silver_sponsors, 32 | "partners": partners, 33 | "count_down": count_down.first() if count_down else None, 34 | "mission_statement": mission_statement.first() if mission_statement else None, 35 | "meta": request.conference.as_meta(), 36 | "promoted_news": Post.objects.filter(front_page=True), 37 | } 38 | return render(request, "home.html", context) 39 | -------------------------------------------------------------------------------- /pyconbalkan/faq/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/faq/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/faq/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Faq 4 | 5 | 6 | class FaqAdmin(admin.ModelAdmin): 7 | class Meta: 8 | model = Faq 9 | 10 | 11 | admin.site.register(Faq, FaqAdmin) 12 | 13 | -------------------------------------------------------------------------------- /pyconbalkan/faq/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | 3 | from pyconbalkan.faq.views import FaqViewSet 4 | 5 | router = routers.DefaultRouter() 6 | router.register(r'faq', FaqViewSet) 7 | -------------------------------------------------------------------------------- /pyconbalkan/faq/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class FaqConfig(AppConfig): 5 | name = 'faq' 6 | -------------------------------------------------------------------------------- /pyconbalkan/faq/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-10-19 20:12 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Faq', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('active', models.BooleanField(default=False)), 19 | ('question', models.CharField(blank=True, max_length=100, null=True)), 20 | ('answer', models.TextField(blank=True, null=True)), 21 | ], 22 | options={ 23 | 'abstract': False, 24 | }, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /pyconbalkan/faq/migrations/0002_auto_20190227_0738.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-02-27 07:38 2 | 3 | from django.db import migrations 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('faq', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='faq', 16 | name='answer', 17 | field=markdownx.models.MarkdownxField(blank=True, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/faq/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/faq/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/faq/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from markdownx.models import MarkdownxField 3 | 4 | from pyconbalkan.core.models import ActiveModel 5 | 6 | 7 | class Faq(ActiveModel): 8 | question = models.CharField(null=True, blank=True, max_length=100) 9 | answer = MarkdownxField(null=True, blank=True) 10 | 11 | def __str__(self): 12 | return self.question 13 | -------------------------------------------------------------------------------- /pyconbalkan/faq/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from pyconbalkan.faq.models import Faq 4 | 5 | 6 | class FaqSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = Faq 9 | fields = '__all__' 10 | -------------------------------------------------------------------------------- /pyconbalkan/faq/templates/faq.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% load static %} 4 | {% load markdownify %} 5 | 6 | {% block main_content %} 7 | 8 | {# Faq #} 9 | 10 |

F.A.Q - Frequently Asked Questions

11 | 12 | {% if faq %} 13 |
14 |
15 | {% for item in faq %} 16 | 18 |
19 |

{{ item.answer | markdownify}}

20 |
21 | {% endfor %} 22 |
23 |
24 | {% else %} 25 |

26 | Coming Soon 27 |

28 | {% endif %} 29 | 30 | 31 | {% if response_guide %} 32 | 33 |

{{ response_guide.title|safe }}

34 |
35 | {% endif %} 36 | 37 | {% endblock %} 38 | 39 | {% block scripts %} 40 | 41 | {% endblock %} 42 | -------------------------------------------------------------------------------- /pyconbalkan/faq/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/faq/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from rest_framework import viewsets 3 | 4 | from pyconbalkan.faq.models import Faq 5 | from pyconbalkan.faq.serializers import FaqSerializer 6 | 7 | 8 | class FaqViewSet(viewsets.ModelViewSet): 9 | queryset = Faq.objects.all() 10 | serializer_class = FaqSerializer 11 | 12 | 13 | def faq_view(request): 14 | faq = Faq.objects.filter(active=True) 15 | context = { 16 | 'faq': faq, 17 | } 18 | return render(request, 'faq.html', context) 19 | -------------------------------------------------------------------------------- /pyconbalkan/info/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/info/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/news/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/news/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/news/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from markdownx.admin import MarkdownxModelAdmin 3 | 4 | from pyconbalkan.news.models import Post 5 | 6 | 7 | class PostAdmin(MarkdownxModelAdmin): 8 | class Meta: 9 | model = Post 10 | 11 | 12 | admin.site.register(Post, PostAdmin) 13 | -------------------------------------------------------------------------------- /pyconbalkan/news/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | from pyconbalkan.news.views import PostViewSet 3 | 4 | router = routers.DefaultRouter() 5 | router.register(r'news', PostViewSet) 6 | -------------------------------------------------------------------------------- /pyconbalkan/news/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class NewsConfig(AppConfig): 5 | name = 'news' 6 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-05-24 19:53 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | import django.utils.timezone 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name='Post', 20 | fields=[ 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('active', models.BooleanField(default=False)), 23 | ('title', models.CharField(max_length=200)), 24 | ('text', models.TextField()), 25 | ('created_date', models.DateTimeField(default=django.utils.timezone.now)), 26 | ('published_date', models.DateTimeField(blank=True, null=True)), 27 | ('image', models.ImageField(blank=True, null=True, upload_to='static/img/news')), 28 | ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 29 | ], 30 | options={ 31 | 'abstract': False, 32 | }, 33 | ), 34 | ] 35 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0002_auto_20180603_1257.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-03 12:57 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('news', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='post', 15 | name='image', 16 | field=models.ImageField(upload_to='posts/image'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0003_auto_20180604_1346.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-04 13:46 2 | 3 | from django.db import migrations 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('news', '0002_auto_20180603_1257'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='post', 16 | name='text', 17 | field=markdownx.models.MarkdownxField(), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0004_post_slug.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-11 19:54 2 | import random 3 | import string 4 | 5 | from django.db import migrations, models 6 | from slugify import slugify 7 | 8 | 9 | def create_slug_in_post(apps, schema_editor): 10 | # We get the model from the versioned app registry; 11 | # if we directly import it, it'll be the wrong version 12 | Post = apps.get_model("news", "Post") 13 | for post in Post.objects.all(): 14 | post.slug = slugify(post.title) 15 | post.save() 16 | 17 | 18 | def remove_slug(apps, schema_editor): 19 | pass 20 | 21 | 22 | class Migration(migrations.Migration): 23 | 24 | dependencies = [ 25 | ('news', '0003_auto_20180604_1346'), 26 | ] 27 | 28 | operations = [ 29 | migrations.AddField( 30 | model_name='post', 31 | name='slug', 32 | field=models.CharField(blank=True, max_length=100), 33 | ), 34 | migrations.RunPython(create_slug_in_post, remove_slug) 35 | ] 36 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0005_auto_20180611_1958.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-11 19:58 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('news', '0004_post_slug'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='post', 15 | name='slug', 16 | field=models.CharField(blank=True, max_length=100, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0006_post_keywords.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-07-27 18:13 2 | 3 | from django.db import migrations 4 | import taggit.managers 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('taggit', '0002_auto_20150616_2121'), 11 | ('news', '0005_auto_20180611_1958'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='post', 17 | name='keywords', 18 | field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0007_auto_20180801_2233.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-01 22:33 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('news', '0006_post_keywords'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name='post', 15 | options={'ordering': ('-published_date',)}, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0008_post_conference.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-03 16:55 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import pyconbalkan.conference.abstractions 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('conference', '0007_auto_20190227_0738'), 12 | ('news', '0007_auto_20180801_2233'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='post', 18 | name='conference', 19 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0009_remove_post_conference.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-21 17:30 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('news', '0008_post_conference'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='post', 15 | name='conference', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0010_auto_20190328_2253.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-28 21:53 2 | 3 | import ckeditor.fields 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('news', '0009_remove_post_conference'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='post', 16 | name='text', 17 | field=ckeditor.fields.RichTextField(), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0011_post_front_page.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-09-21 16:12 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('news', '0010_auto_20190328_2253'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='post', 15 | name='front_page', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/0012_auto_20190921_2009.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-09-21 20:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('news', '0011_post_front_page'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='post', 15 | name='front_page', 16 | field=models.BooleanField(default=False, verbose_name='Promote news article to frontpage'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/news/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/news/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/news/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.utils import timezone 3 | from ckeditor.fields import RichTextField 4 | from taggit.managers import TaggableManager 5 | from django.utils.text import slugify 6 | 7 | from pyconbalkan.core.models import ActiveModel 8 | 9 | 10 | class Post(ActiveModel): 11 | author = models.ForeignKey('auth.User', on_delete=models.CASCADE) 12 | title = models.CharField(max_length=200) 13 | text = RichTextField() 14 | keywords = TaggableManager() 15 | created_date = models.DateTimeField(default=timezone.now) 16 | published_date = models.DateTimeField(blank=True, null=True) 17 | image = models.ImageField(upload_to='posts/image') 18 | slug = models.CharField(unique=True, blank=True, max_length=100) 19 | front_page = models.BooleanField("Promote news article to frontpage", default=False) 20 | 21 | def save(self, *args, **kwargs): 22 | if not self.slug: 23 | self.slug = slugify(self.title) 24 | super(Post, self).save(*args, **kwargs) 25 | 26 | def publish(self): 27 | self.published_date = timezone.now() 28 | self.save() 29 | 30 | def __str__(self): 31 | return '{} by {}'.format(self.title, self.author.username) 32 | 33 | class Meta: 34 | ordering = ("-published_date",) 35 | -------------------------------------------------------------------------------- /pyconbalkan/news/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from pyconbalkan.news.models import Post 3 | 4 | 5 | class PostSerializer(serializers.ModelSerializer): 6 | class Meta: 7 | model = Post 8 | fields = '__all__' 9 | -------------------------------------------------------------------------------- /pyconbalkan/news/templates/news.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load markdownify %} 3 | 4 | {% block main_content %} 5 | 6 | {# News #} 7 | 8 |

News

9 | 10 | {% if news %} 11 |
12 | {% for post in news %} 13 |
14 |
15 | 16 | 17 | 18 |
19 |
20 |

21 | 22 | {{ post.title|safe }} 23 | 24 |

25 | 28 |

29 | {{ post.text|safe|truncatewords:20 }} 30 |

31 |
32 |
33 | {% endfor %} 34 |
35 | {% else %} 36 |

37 | Coming Soon 38 |

39 | {% endif %} 40 | 41 | 42 | 43 | {% endblock %} 44 | -------------------------------------------------------------------------------- /pyconbalkan/news/templates/post.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 |
5 | 12 | 13 | 14 | {# Post #} 15 | 16 |
17 |
18 | 19 |
20 |
21 |

{{ post.title }}

22 |

23 | {{ post.text|safe }} 24 |

25 |

Posted by {{ post.author.first_name }} {{ post.author.last_name }}

26 | 27 |
28 |
29 |
30 | 31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /pyconbalkan/news/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/news/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, get_object_or_404 2 | from django.utils import timezone 3 | from django.utils.html import strip_tags 4 | from meta.views import Meta 5 | from rest_framework import viewsets 6 | 7 | from pyconbalkan.news.models import Post 8 | from pyconbalkan.news.serializers import PostSerializer 9 | 10 | 11 | class PostViewSet(viewsets.ModelViewSet): 12 | queryset = Post.objects.all() 13 | serializer_class = PostSerializer 14 | 15 | 16 | def news_view(request): 17 | posts = Post.objects.filter(active=True, published_date__lte=timezone.now()) 18 | context = {"news": posts} 19 | return render(request, "news.html", context) 20 | 21 | 22 | def post_detail(request, slug): 23 | post = get_object_or_404(Post, active=True, slug=slug) 24 | meta = Meta( 25 | title=strip_tags(post.title), 26 | description=strip_tags(post.text), 27 | keywords=post.keywords.names(), 28 | image=post.image.url, 29 | extra_props={ 30 | "viewport": "width=device-width, initial-scale=1.0, minimum-scale=1.0" 31 | }, 32 | ) 33 | 34 | context = {"post": post, "meta": meta} 35 | return render(request, "post.html", context) 36 | -------------------------------------------------------------------------------- /pyconbalkan/ngo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/ngo/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/ngo/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/ngo/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class NgoConfig(AppConfig): 5 | name = 'ngo' 6 | -------------------------------------------------------------------------------- /pyconbalkan/ngo/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/ngo/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/ngo/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/ngo/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/ngo/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/onsite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/onsite/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/onsite/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/onsite/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class OnsiteConfig(AppConfig): 5 | name = 'onsite' 6 | -------------------------------------------------------------------------------- /pyconbalkan/onsite/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/onsite/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/onsite/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/onsite/templates/workshops.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 |
6 |

Workshop Signup page

7 | {% if request.conference.workshop_application_embed_code %} 8 | {{ request.conference.workshop_application_embed_code|safe }} 9 | {% else %} 10 |

Signup form for workshops is not either not yet been published, or someone intentionally closed it !

11 |

In case you think that this is an error, please ping us on slack or through our contact us form.

12 |

Thank you,
PyCon Balkan Organizational team <3

13 | {% endif %} 14 |
15 | {% endblock %} 16 | -------------------------------------------------------------------------------- /pyconbalkan/onsite/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/onsite/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from django.views.generic import TemplateView 3 | from meta.views import Meta 4 | 5 | 6 | urlpatterns = [ 7 | path('lightning-talks', TemplateView.as_view(template_name="lightningtalks.html", extra_context={ 8 | "meta": Meta( 9 | title="PyCon Balkan - Lightning Talks", 10 | description="Not familiar with Lightning Talks ? Don't worry, we will make sure " 11 | "that for this year's PyCon we have you prepped and ready, Read more here.", 12 | ) 13 | }), name='lightning-talks'), 14 | path('open-spaces', TemplateView.as_view(template_name="openspaces.html", extra_context={ 15 | "meta": Meta( 16 | title="PyCon Balkan - Open Spaces", 17 | description="Open Spaces is a PyCon US Concept we will be bringing in to our PyCon from this year, " 18 | "read more here to get up to speed on how open-spaces work !" 19 | ) 20 | }), name='open-spaces'), 21 | path('workshops', TemplateView.as_view(template_name="workshops.html", extra_context={ 22 | "meta": Meta( 23 | title="PyCon Balkan - Workshops", 24 | description="Page containing the signup form for workshops during the PyCon Balkan event." 25 | ) 26 | }), name='workshops'), 27 | ] -------------------------------------------------------------------------------- /pyconbalkan/onsite/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/organizers/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/organizers/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from markdownx.admin import MarkdownxModelAdmin 3 | 4 | from pyconbalkan.organizers.models import Volunteer, VolunteerPhoto 5 | 6 | 7 | class VolunteerImageInline(admin.TabularInline): 8 | model = VolunteerPhoto 9 | 10 | class VolunteerAdmin(MarkdownxModelAdmin): 11 | inlines = [VolunteerImageInline] 12 | 13 | 14 | admin.site.register(Volunteer, VolunteerAdmin) -------------------------------------------------------------------------------- /pyconbalkan/organizers/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | 3 | from pyconbalkan.organizers.views import VolunteerViewSet 4 | 5 | router = routers.DefaultRouter() 6 | router.register(r'organizers', VolunteerViewSet) -------------------------------------------------------------------------------- /pyconbalkan/organizers/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class OrganizationConfig(AppConfig): 5 | name = 'organizers' 6 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.db import transaction 3 | 4 | from pyconbalkan.organizers.models import Volunteer, VolunteerPhoto 5 | 6 | 7 | class VolunteerCreateForm(forms.ModelForm): 8 | required_fields = ( 9 | 'full_name', 'name', 'date_of_birth', 'job', 10 | 'email', 'description', 'country', 'profile_photo' 11 | ) 12 | 13 | profile_picture = forms.ImageField(label='Profile Photo', required=True) 14 | 15 | def __init__(self, **kwargs): 16 | super().__init__(**kwargs) 17 | 18 | for name, field in self.fields.items(): 19 | self.add_required(name, field) 20 | self.add_form_control(field) 21 | self.label_as_placeholder(field, name) 22 | 23 | def add_form_control(self, field): 24 | old_classes = field.widget.attrs['class'] if 'class' in field.widget.attrs else '' 25 | field.widget.attrs.update({'class': f'{old_classes} form-control'}) 26 | 27 | def label_as_placeholder(self, field, name): 28 | placeholder = field.label if not field.required else field.label + '*' 29 | field.widget.attrs.update({'placeholder': placeholder}) 30 | 31 | if name != 'profile_picture': 32 | field.label = '' 33 | else: 34 | field.label = placeholder 35 | 36 | def add_required(self, name, field): 37 | if name in self.required_fields: 38 | field.required = True 39 | 40 | def save(self, commit=True): 41 | """ 42 | Save both Volunteer model and VolunteerPhoto at once. 43 | If more complex - maybe add formset. 44 | """ 45 | 46 | with transaction.atomic(): 47 | instance = super().save(commit=commit) 48 | VolunteerPhoto.objects.create( 49 | volunteer=instance, profile_picture=self.cleaned_data['profile_picture'] 50 | ) 51 | return instance 52 | 53 | class Meta: 54 | model = Volunteer 55 | exclude = ('active', 'user', 'type', 'slug', ) 56 | widgets = { 57 | 'date_of_birth': forms.DateInput(attrs={'class': 'datepicker'}), 58 | } 59 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0002_remove_volunteer_email.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-03 10:52 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('organizers', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='volunteer', 15 | name='email', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0003_auto_20180603_1156.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-03 11:56 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('organizers', '0002_remove_volunteer_email'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='volunteerphoto', 15 | name='profile_picture', 16 | field=models.ImageField(blank=True, upload_to='organizers/volunteer/profile_picture'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0004_volunteer_slug.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-10 16:08 2 | import random 3 | import string 4 | 5 | from django.db import migrations, models 6 | from slugify import slugify 7 | 8 | 9 | def create_slug_in_volunteer(apps, schema_editor): 10 | # Create slug in Volunteer 11 | Volunteer = apps.get_model("organizers", "Volunteer") 12 | for volunteer in Volunteer.objects.all(): 13 | volunteer.slug = '{}-{}'.format(slugify(volunteer.full_name), ''.join(random.choices(string.ascii_uppercase + string.digits, k=4))) 14 | volunteer.save() 15 | 16 | def remove_slug(apps, schema_editor): 17 | pass 18 | 19 | class Migration(migrations.Migration): 20 | 21 | dependencies = [ 22 | ('organizers', '0003_auto_20180603_1156'), 23 | ] 24 | 25 | operations = [ 26 | migrations.AddField( 27 | model_name='volunteer', 28 | name='slug', 29 | field=models.CharField(blank=True, max_length=100), 30 | ), 31 | migrations.RunPython(create_slug_in_volunteer, remove_slug) 32 | ] 33 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0005_auto_20180610_1608.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-10 16:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('organizers', '0004_volunteer_slug'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='volunteer', 15 | name='slug', 16 | field=models.CharField(blank=True, max_length=100, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0006_volunteer_description.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-11 12:03 2 | 3 | from django.db import migrations 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('organizers', '0005_auto_20180610_1608'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='volunteer', 16 | name='description', 17 | field=markdownx.models.MarkdownxField(blank=True, default=''), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0007_volunteer_weight.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-11 21:43 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | def update_weight_from_id(apps, schema_editor): 7 | # We get the model from the versioned app registry; 8 | # if we directly import it, it'll be the wrong version 9 | Volunteer = apps.get_model("organizers", "Volunteer") 10 | for volunteer in Volunteer.objects.all(): 11 | volunteer.weight = volunteer.id 12 | volunteer.save() 13 | 14 | def remove_weight(apps, schema_editor): 15 | pass 16 | 17 | 18 | class Migration(migrations.Migration): 19 | 20 | dependencies = [ 21 | ('organizers', '0006_volunteer_description'), 22 | ] 23 | 24 | operations = [ 25 | migrations.AddField( 26 | model_name='volunteer', 27 | name='weight', 28 | field=models.IntegerField(null=True), 29 | ), 30 | migrations.RunPython(update_weight_from_id, remove_weight) 31 | ] 32 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0008_auto_20180611_2147.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-11 21:47 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('organizers', '0007_volunteer_weight'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='volunteer', 15 | name='weight', 16 | field=models.IntegerField(unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0009_auto_20180613_1701.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-13 17:01 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('organizers', '0008_auto_20180611_2147'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='volunteer', 15 | name='github', 16 | field=models.URLField(blank=True, null=True), 17 | ), 18 | migrations.AlterField( 19 | model_name='volunteer', 20 | name='weight', 21 | field=models.IntegerField(blank=True, unique=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0010_person_email.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-20 19:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('organizers', '0009_auto_20180613_1701'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='volunteer', 15 | name='email', 16 | field=models.EmailField(blank=True, max_length=254, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0011_auto_20180801_2233.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-01 22:33 2 | 3 | from django.conf import settings 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('organizers', '0010_person_email'), 12 | ] 13 | 14 | operations = [ 15 | migrations.RemoveField( 16 | model_name='volunteer', 17 | name='weight', 18 | ), 19 | migrations.AlterField( 20 | model_name='volunteer', 21 | name='user', 22 | field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='volunteer', to=settings.AUTH_USER_MODEL), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0012_auto_20180801_2318.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-01 23:18 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('organizers', '0011_auto_20180801_2233'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name='volunteer', 15 | options={'ordering': ('full_name',)}, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/0013_volunteer_country.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-03 15:06 2 | 3 | from django.db import migrations 4 | import django_countries.fields 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('organizers', '0012_auto_20180801_2318'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='volunteer', 16 | name='country', 17 | field=django_countries.fields.CountryField(blank=True, max_length=2, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/organizers/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/organizers/models.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import User 2 | from django.db import models 3 | from django.db.models import CASCADE 4 | 5 | from pyconbalkan.core.models import Person, ActiveModel 6 | 7 | 8 | class Volunteer(ActiveModel, Person): 9 | ORGANIZER = 0 10 | VOLUNTEER = 1 11 | VOLUNTEER_TYPE = ( 12 | (ORGANIZER, 'Organizer'), 13 | (VOLUNTEER, 'Volunteer'), 14 | ) 15 | 16 | user = models.OneToOneField(User, blank=True, null=True, related_name='volunteer', on_delete=CASCADE) 17 | type = models.IntegerField(choices=VOLUNTEER_TYPE, default=VOLUNTEER) 18 | 19 | def __str__(self): 20 | return '{} [{}]'.format(self.name, self.get_type_display()) 21 | 22 | class Meta: 23 | ordering = ('full_name',) 24 | 25 | 26 | class VolunteerPhoto(models.Model): 27 | volunteer = models.ForeignKey(Volunteer, related_name='images', on_delete=CASCADE) 28 | profile_picture = models.ImageField(upload_to="organizers/volunteer/profile_picture", blank=True) 29 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from pyconbalkan.conference.models import Conference 4 | from pyconbalkan.organizers.models import Volunteer 5 | 6 | 7 | class VolunteerSerializer(serializers.ModelSerializer): 8 | class Meta: 9 | model = Volunteer 10 | fields = '__all__' 11 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/templates/organizer.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 | {# organizer INFO #} 6 | 7 |
8 |
9 | 10 |
11 |
12 |

13 | {% if organizer.country %}{% endif %} 14 | {{ organizer.name }} 15 |

16 |

17 | {{ organizer.job }} 18 |

19 |

20 | {{ organizer.description|safe }} 21 |

22 | 42 |
43 |
44 | 45 | {% endblock %} 46 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/templates/volunteers_create.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | 4 | {% block main_content %} 5 |

Sign up as a Volunteer!

6 | 7 | {% if success %} 8 |

9 | {{ success | safe }} 10 |

11 | {% endif %} 12 | 13 |
15 |
16 | {% csrf_token %} 17 | {{ form.as_p }} 18 | 20 |
21 |
22 | {{ form.media }} 23 | 24 | {% endblock main_content %} 25 | 26 | 27 | {% block scripts %} 28 | 31 | 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/organizers/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, get_object_or_404 2 | from rest_framework import viewsets 3 | 4 | from pyconbalkan.organizers.forms import VolunteerCreateForm 5 | from pyconbalkan.organizers.models import Volunteer 6 | from pyconbalkan.organizers.serializers import VolunteerSerializer 7 | 8 | 9 | class VolunteerViewSet(viewsets.ModelViewSet): 10 | queryset = Volunteer.objects.all() 11 | serializer_class = VolunteerSerializer 12 | 13 | 14 | def organizer_view(request, slug): 15 | organizer = get_object_or_404(Volunteer, slug=slug) 16 | context = { 17 | 'organizer': organizer, 18 | } 19 | return render(request, 'organizer.html', context) 20 | 21 | 22 | def organizers_list(request): 23 | volunteers = Volunteer.objects.filter(type=Volunteer.VOLUNTEER, active=True) 24 | organizers = Volunteer.objects.filter(type=Volunteer.ORGANIZER, active=True) 25 | context = { 26 | 'volunteers': volunteers, 27 | 'organizers': organizers, 28 | } 29 | return render(request, 'organizers.html', context) 30 | 31 | 32 | def volunteers_createview(request): 33 | context = {} 34 | 35 | if request.method == 'POST': 36 | form = VolunteerCreateForm(data=request.POST, files=request.FILES) 37 | if form.is_valid(): 38 | volunteer = form.save() 39 | context['success'] = f'{volunteer.full_name}, you have been successfully signed up ' \ 40 | f'as a volunteer!
We will contact you soon.

' \ 41 | f'Thank you! :)
' 42 | form = VolunteerCreateForm() 43 | else: 44 | form = VolunteerCreateForm() 45 | 46 | context['form'] = form 47 | return render(request, 'volunteers_create.html', context) 48 | -------------------------------------------------------------------------------- /pyconbalkan/pera.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/pera.json -------------------------------------------------------------------------------- /pyconbalkan/speaker/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/speaker/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/speaker/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from markdownx.admin import MarkdownxModelAdmin 3 | 4 | from pyconbalkan.speaker.models import Speaker, SpeakerPhoto, YouTubeLink 5 | from pyconbalkan.timetable.models import Presentation 6 | 7 | 8 | class SpeakerImageInline(admin.TabularInline): 9 | model = SpeakerPhoto 10 | 11 | 12 | class SpeakerYoutubeInline(admin.TabularInline): 13 | model = YouTubeLink 14 | 15 | 16 | @admin.register(Speaker) 17 | class SpeakerAdmin(MarkdownxModelAdmin): 18 | inlines = (SpeakerYoutubeInline,SpeakerImageInline,) 19 | search_fields = ('full_name',) 20 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | 3 | from pyconbalkan.speaker.views import SpeakerViewSet 4 | 5 | router = routers.DefaultRouter() 6 | router.register(r'speaker', SpeakerViewSet) -------------------------------------------------------------------------------- /pyconbalkan/speaker/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class SpeakerConfig(AppConfig): 5 | name = 'speaker' 6 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.11 on 2018-04-26 21:50 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | initial = True 12 | 13 | dependencies = [ 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Speaker', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('active', models.BooleanField(default=False)), 22 | ('name', models.CharField(max_length=50)), 23 | ('job', models.CharField(max_length=100)), 24 | ], 25 | options={ 26 | 'abstract': False, 27 | }, 28 | ), 29 | migrations.CreateModel( 30 | name='SpeakerPhoto', 31 | fields=[ 32 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 33 | ('profile_picture', models.ImageField(upload_to='static/img')), 34 | ('speaker', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='images', to='speaker.Speaker')), 35 | ], 36 | ), 37 | ] 38 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0002_auto_20180506_1828.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by Django 1.11.11 on 2018-05-06 18:28 3 | from __future__ import unicode_literals 4 | 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('speaker', '0001_initial'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='speaker', 17 | name='company', 18 | field=models.CharField(blank=True, max_length=100, null=True), 19 | ), 20 | migrations.AddField( 21 | model_name='speaker', 22 | name='date_of_birth', 23 | field=models.DateField(blank=True, null=True), 24 | ), 25 | migrations.AddField( 26 | model_name='speaker', 27 | name='facebook', 28 | field=models.URLField(blank=True, null=True), 29 | ), 30 | migrations.AddField( 31 | model_name='speaker', 32 | name='full_name', 33 | field=models.CharField(max_length=256, null=True), 34 | ), 35 | migrations.AddField( 36 | model_name='speaker', 37 | name='linkedin', 38 | field=models.URLField(blank=True, null=True), 39 | ), 40 | migrations.AddField( 41 | model_name='speaker', 42 | name='personal_website', 43 | field=models.URLField(blank=True, null=True), 44 | ), 45 | migrations.AddField( 46 | model_name='speaker', 47 | name='twitter', 48 | field=models.URLField(blank=True, null=True), 49 | ), 50 | migrations.AlterField( 51 | model_name='speaker', 52 | name='job', 53 | field=models.CharField(blank=True, max_length=100, null=True), 54 | ), 55 | migrations.AlterField( 56 | model_name='speaker', 57 | name='name', 58 | field=models.CharField(blank=True, max_length=256, null=True), 59 | ), 60 | ] 61 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0003_auto_20180603_1156.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-03 11:56 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('speaker', '0002_auto_20180506_1828'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='speakerphoto', 15 | name='profile_picture', 16 | field=models.ImageField(blank=True, upload_to='speakers/profile_picture'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0004_auto_20180610_1053.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-10 10:53 2 | 3 | from django.db import migrations, models 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('speaker', '0003_auto_20180603_1156'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='speaker', 16 | name='description', 17 | field=markdownx.models.MarkdownxField(blank=True, default=''), 18 | ), 19 | migrations.AddField( 20 | model_name='speaker', 21 | name='keynote', 22 | field=models.BooleanField(default=False), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0005_speaker_slug.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-10 16:08 2 | import random 3 | import string 4 | 5 | from django.db import migrations, models 6 | from slugify import slugify 7 | 8 | import pyconbalkan.core.models 9 | 10 | 11 | def forwards_func(apps, schema_editor): 12 | # We get the model from the versioned app registry; 13 | # if we directly import it, it'll be the wrong version 14 | Speaker = apps.get_model("speaker", "Speaker") 15 | for speaker in Speaker.objects.all(): 16 | speaker.slug = slugify(speaker.full_name) + '-' +''.join(random.choices(string.ascii_uppercase + string.digits, k=4)) 17 | speaker.save() 18 | 19 | 20 | class Migration(migrations.Migration): 21 | 22 | dependencies = [ 23 | ('speaker', '0004_auto_20180610_1053'), 24 | ] 25 | 26 | operations = [ 27 | migrations.AddField( 28 | model_name='speaker', 29 | name='slug', 30 | field=models.CharField(blank=True, max_length=100), 31 | ), 32 | migrations.RunPython(forwards_func) 33 | ] 34 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0006_auto_20180610_1608.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-10 16:08 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('speaker', '0005_speaker_slug'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='speaker', 15 | name='slug', 16 | field=models.CharField(blank=True, max_length=100, unique=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0007_speaker_github.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-11 19:54 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('speaker', '0006_auto_20180610_1608'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='speaker', 15 | name='github', 16 | field=models.URLField(blank=True, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0008_person_email.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-20 19:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('speaker', '0007_speaker_github'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='speaker', 15 | name='email', 16 | field=models.EmailField(blank=True, max_length=254, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0009_auto_20180801_2318.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-01 23:18 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('speaker', '0008_person_email'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name='speaker', 15 | options={'ordering': ('full_name',)}, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0010_speaker_country.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-03 15:06 2 | 3 | from django.db import migrations 4 | import django_countries.fields 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('speaker', '0009_auto_20180801_2318'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='speaker', 16 | name='country', 17 | field=django_countries.fields.CountryField(blank=True, max_length=2, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0011_speaker_conference.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-03 16:46 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import pyconbalkan.conference.abstractions 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('conference', '0007_auto_20190227_0738'), 12 | ('speaker', '0010_speaker_country'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='speaker', 18 | name='conference', 19 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0012_auto_20190827_1257.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-27 12:57 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('speaker', '0011_speaker_conference'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='speaker', 15 | name='active', 16 | ), 17 | migrations.RemoveField( 18 | model_name='speaker', 19 | name='conference', 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0013_remove_speaker_keynote.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-27 13:04 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('speaker', '0012_auto_20190827_1257'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='speaker', 15 | name='keynote', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/0014_youtubelink.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-29 10:56 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import embed_video.fields 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('speaker', '0013_remove_speaker_keynote'), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='YouTubeLink', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('video', embed_video.fields.EmbedVideoField()), 20 | ('speaker', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='videos', to='speaker.Speaker')), 21 | ], 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/speaker/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/speaker/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.db.models import CASCADE 3 | from embed_video.fields import EmbedVideoField 4 | 5 | from pyconbalkan.conference.models import AbstractConference 6 | from pyconbalkan.core.models import Person, ActiveModel 7 | 8 | 9 | class Speaker(Person): 10 | def __str__(self): 11 | return self.name 12 | 13 | @property 14 | def preffered_talk_type(self): 15 | return self.presentations.order_by("type").first().get_type_display().lower() 16 | 17 | class Meta: 18 | ordering = ('full_name',) 19 | 20 | 21 | class YouTubeLink(models.Model): 22 | speaker = models.ForeignKey(Speaker, related_name="videos", on_delete=models.CASCADE) 23 | video = EmbedVideoField() 24 | 25 | 26 | class SpeakerPhoto(models.Model): 27 | speaker = models.ForeignKey(Speaker, related_name='images', on_delete=CASCADE) 28 | profile_picture = models.ImageField(upload_to="speakers/profile_picture", blank=True) 29 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from pyconbalkan.speaker.models import Speaker 4 | 5 | 6 | class SpeakerSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = Speaker 9 | fields = '__all__' 10 | -------------------------------------------------------------------------------- /pyconbalkan/speaker/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/sponsors/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/sponsors/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from pyconbalkan.conference.abstractions import ConferenceAbstractAdmin 4 | from pyconbalkan.sponsors.models import Package, PackageItem, Sponsor, Sponsoring 5 | 6 | 7 | admin.site.register(Sponsor, ConferenceAbstractAdmin) 8 | admin.site.register(Sponsoring) 9 | admin.site.register(Package) 10 | admin.site.register(PackageItem) 11 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | from pyconbalkan.sponsors.views import SponsorsViewSet 3 | 4 | router = routers.DefaultRouter() 5 | router.register(r'sponsors', SponsorsViewSet) 6 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class SponsorsConfig(AppConfig): 5 | name = 'sponsors' 6 | 7 | 8 | class SponsoringConfig(AppConfig): 9 | name = 'sponsoring' 10 | 11 | 12 | class PackageConfig(AppConfig): 13 | name = 'package' 14 | 15 | 16 | class PackageItemConfig(AppConfig): 17 | name = 'package_item' -------------------------------------------------------------------------------- /pyconbalkan/sponsors/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.forms import ModelForm 3 | from django.forms.widgets import RadioSelect 4 | 5 | from pyconbalkan.sponsors.models import Sponsoring, ORGANIZATION_CHOICES, SponsorshipLevel 6 | 7 | 8 | class SponsoringForm(ModelForm): 9 | name = forms.CharField( 10 | widget=forms.TextInput(attrs={'placeholder': 'Name', 'class': 'form-control'}), 11 | max_length=256, 12 | error_messages={'required': 'Please, enter your name.'}, label='') 13 | phone = forms.CharField( 14 | widget=forms.TextInput(attrs={'placeholder': 'Phone number', 'class': 'form-control'}), 15 | max_length=17, 16 | error_messages={ 17 | 'required': 'Please, enter your phone number.', 18 | 'invalid': 'Please, enter a valid phone number.' 19 | }, label='') 20 | email = forms.EmailField( 21 | widget=forms.TextInput(attrs={'placeholder': 'Email', 'class': 'form-control'}), 22 | error_messages={ 23 | 'required': 'Please, enter your email address.', 24 | 'invalid': 'Please, enter a valid email address.' 25 | }, label='') 26 | organization = forms.CharField( 27 | widget=forms.TextInput(attrs={'placeholder': 'Company / Organization', 'class': 'form-control'}), 28 | max_length=100, 29 | required=False, label='') 30 | organization_type = forms.ChoiceField(choices=ORGANIZATION_CHOICES, label='Organization Type', widget=RadioSelect()) 31 | level = forms.ChoiceField(choices=SponsorshipLevel.choices, label='Level of Interest', widget=RadioSelect()) 32 | 33 | class Meta: 34 | model = Sponsoring 35 | fields = ( 36 | 'name', 37 | 'phone', 38 | 'email', 39 | 'organization', 40 | 'organization_type', 41 | 'level' 42 | ) 43 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-05-14 14:39 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Sponsor', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=256)), 19 | ('description', models.TextField()), 20 | ('level', models.CharField(choices=[('Keystone', 'keystone'), ('Platinum', 'platinum'), ('Gold', 'gold'), ('Silver', 'silver'), ('Partner', 'partner')], max_length=16)), 21 | ('logo', models.ImageField(blank=True, null=True, upload_to='static/img/sponsors')), 22 | ], 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0002_auto_20180603_1156.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-03 11:56 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='sponsor', 15 | name='logo', 16 | field=models.ImageField(blank=True, null=True, upload_to='sponsors/logo'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0003_auto_20180604_1346.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-04 13:46 2 | 3 | from django.db import migrations 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('sponsors', '0002_auto_20180603_1156'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='sponsor', 16 | name='description', 17 | field=markdownx.models.MarkdownxField(), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0004_sponsoring.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-04 19:58 2 | 3 | import django.core.validators 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('sponsors', '0003_auto_20180604_1346'), 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Sponsoring', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('organization', models.CharField(blank=True, max_length=100, null=True)), 19 | ('name', models.CharField(max_length=256)), 20 | ('phone', models.CharField(blank=True, max_length=17, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')])), 21 | ('email', models.EmailField(max_length=254)), 22 | ('approved', models.BooleanField(default=False)), 23 | ], 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0006_sponsoring_organization_type.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-04 21:48 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0005_auto_20180804_2052'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='sponsoring', 15 | name='organization_type', 16 | field=models.IntegerField(choices=[(1, 'For - profit corporation'), (2, 'Foundation / Non profit')], default=1), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0007_sponsoring_level.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-04 22:00 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0006_sponsoring_organization_type'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='sponsoring', 15 | name='level', 16 | field=models.CharField(choices=[('Keystone', 'keystone'), ('Platinum', 'platinum'), ('Gold', 'gold'), ('Silver', 'silver'), ('Partner', 'partner')], default='Partner', max_length=16), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0008_auto_20180811_1903.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-11 19:03 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0007_sponsoring_level'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='sponsoring', 15 | name='organization', 16 | field=models.CharField(blank=True, max_length=256, null=True), 17 | ), 18 | migrations.AlterField( 19 | model_name='sponsoring', 20 | name='organization_type', 21 | field=models.IntegerField(choices=[(1, 'Profit Corporation'), (2, 'Foundation / Non profit')], default=1), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0009_auto_20190303_1426.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-03 14:26 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0008_auto_20180811_1903'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='sponsor', 15 | name='logo', 16 | field=models.ImageField(upload_to='sponsors/logo'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0010_sponsor_conference.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-03 14:42 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import pyconbalkan.conference.abstractions 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('conference', '0007_auto_20190227_0738'), 12 | ('sponsors', '0009_auto_20190303_1426'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='sponsor', 18 | name='conference', 19 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0011_auto_20190321_2214.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-21 21:14 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0010_sponsor_conference'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='sponsor', 15 | name='sidebar', 16 | field=models.BooleanField(default=False), 17 | ), 18 | migrations.AddField( 19 | model_name='sponsor', 20 | name='url', 21 | field=models.URLField(max_length=256, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0012_auto_20190321_2148.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-21 21:48 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0011_auto_20190321_2214'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='sponsor', 15 | name='logo', 16 | field=models.FileField(upload_to='sponsors/logo'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0013_auto_20190322_1457.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-22 14:57 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0012_auto_20190321_2148'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='sponsor', 15 | name='logo', 16 | field=models.FileField(upload_to=''), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0014_sponsor_active.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-28 22:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('sponsors', '0013_auto_20190322_1457'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='sponsor', 15 | name='active', 16 | field=models.BooleanField(default=False), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/0015_auto_20190827_1159.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-27 11:59 2 | 3 | from django.db import migrations 4 | import djmoney.models.fields 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('sponsors', '0014_sponsor_active'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='package', 16 | name='amount', 17 | field=djmoney.models.fields.MoneyField(decimal_places=0, default_currency='EUR', max_digits=16), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/sponsors/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/sponsors/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from pyconbalkan.sponsors.models import Sponsor, Sponsoring 3 | 4 | 5 | class SponsorSerializer(serializers.ModelSerializer): 6 | class Meta: 7 | model = Sponsor 8 | fields = '__all__' 9 | 10 | 11 | class SponsoringSerializer(serializers.ModelSerializer): 12 | class Meta: 13 | model = Sponsoring 14 | fields = '__all__' -------------------------------------------------------------------------------- /pyconbalkan/sponsors/templates/sponsor.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block main_content %} 4 | 5 | {# sponsor INFO #} 6 | 7 | 19 | 20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /pyconbalkan/sponsors/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/sponsorship/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class SponsorshipConfig(AppConfig): 5 | name = 'sponsorship' 6 | -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-05-17 13:07 2 | 3 | from django.db import migrations, models 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='Sponsorship', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('active', models.BooleanField(default=False)), 20 | ('title', models.CharField(blank=True, max_length=100, null=True)), 21 | ('description', markdownx.models.MarkdownxField(blank=True, null=True)), 22 | ], 23 | options={ 24 | 'abstract': False, 25 | }, 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/sponsorship/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from markdownx.models import MarkdownxField 3 | 4 | from pyconbalkan.core.models import SingleActiveModel 5 | 6 | 7 | class Sponsorship(SingleActiveModel): 8 | title = models.CharField(null=True, blank=True, max_length=100) 9 | description = MarkdownxField(null=True, blank=True) 10 | 11 | def __str__(self): 12 | return self.title -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from pyconbalkan.sponsorship.models import Sponsorship 4 | 5 | 6 | class SponsorshipSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = Sponsorship 9 | fields = '__all__' 10 | -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/sponsorship/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from rest_framework import viewsets 3 | 4 | from pyconbalkan.sponsorship.models import Sponsorship 5 | from pyconbalkan.sponsorship.serializers import SponsorshipSerializer 6 | from pyconbalkan.coc.views import coc_view 7 | 8 | 9 | class SponsorshipViewSet(viewsets.ModelViewSet): 10 | queryset = Sponsorship.objects.all() 11 | serializer_class = SponsorshipSerializer 12 | 13 | 14 | def sponsorship_view(request): 15 | sponsorship = Sponsorship.objects.filter(active=True) 16 | context = { 17 | 'sponsorship': sponsorship.first() if sponsorship else None, 18 | } 19 | return render(request, 'sponsorship.html', context) 20 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/timetable/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/timetable/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from pyconbalkan.conference.abstractions import ConferenceAbstractAdmin 4 | from pyconbalkan.timetable.models import Presentation, Room, Slot 5 | 6 | 7 | @admin.register(Presentation) 8 | class PresentationAdmin(ConferenceAbstractAdmin): 9 | autocomplete_fields = ("speaker",) 10 | list_display = ("type", "title", "speaker", "tag_list", "active") 11 | list_editable = ("active",) 12 | 13 | def get_queryset(self, request): 14 | return super().get_queryset(request).prefetch_related('tags') 15 | 16 | def tag_list(self, obj): 17 | return u", ".join(o.name for o in obj.tags.all()) 18 | 19 | 20 | @admin.register(Room) 21 | class RoomAdmin(admin.ModelAdmin): 22 | pass 23 | 24 | 25 | @admin.register(Slot) 26 | class SlotAdmin(admin.ModelAdmin): 27 | pass 28 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/api_urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | 3 | from pyconbalkan.timetable.views import TimetableViewSet 4 | 5 | router = routers.DefaultRouter() 6 | router.register(r'timetable', TimetableViewSet) 7 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class TimetableConfig(AppConfig): 5 | name = 'timetable' 6 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/timetable/management/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/timetable/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/timetable/management/commands/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/timetable/migrations/0002_auto_20180604_1346.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-06-04 13:46 2 | 3 | from django.db import migrations 4 | import markdownx.models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('timetable', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='presentation', 16 | name='description', 17 | field=markdownx.models.MarkdownxField(blank=True, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/migrations/0003_auto_20180803_1820.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.5 on 2018-08-03 18:20 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('timetable', '0002_auto_20180604_1346'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='presentation', 15 | name='type', 16 | field=models.IntegerField(choices=[(0, 'Talk'), (1, 'Workshop'), (2, 'Keynote')], default=0), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/migrations/0004_presentation_conference.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.7 on 2019-03-21 19:07 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import pyconbalkan.conference.models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('conference', '0008_auto_20190303_1800'), 12 | ('timetable', '0003_auto_20180803_1820'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='presentation', 18 | name='conference', 19 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/migrations/0005_auto_20190827_1355.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-27 13:55 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('timetable', '0004_presentation_conference'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='presentation', 16 | name='speaker', 17 | field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='presentations', to='speaker.Speaker'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/migrations/0006_auto_20190827_2044.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-27 20:44 2 | 3 | from django.db import migrations, models 4 | import taggit.managers 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('taggit', '0003_taggeditem_add_unique_index'), 11 | ('timetable', '0005_auto_20190827_1355'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='presentation', 17 | name='tags', 18 | field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), 19 | ), 20 | migrations.AddField( 21 | model_name='presentation', 22 | name='youtube', 23 | field=models.URLField(blank=True, null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/migrations/0007_auto_20190827_2247.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-08-27 22:47 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | def forwards_func(apps, schema_editor): 7 | Presentation = apps.get_model("timetable", "Presentation") 8 | Presentation.objects.filter(type=0).update(type=10) # TALK = 10 # 0 9 | Presentation.objects.filter(type=1).update(type=15) # WORKSHOP = 15 # 1 10 | Presentation.objects.filter(type=2).update(type=5) # KEYNOTE = 5 # 2 11 | 12 | 13 | def reverse_func(apps, schema_editor): 14 | Presentation = apps.get_model("timetable", "Presentation") 15 | Presentation.objects.filter(type=10).update(type=0) # TALK = 10 # 0 16 | Presentation.objects.filter(type=15).update(type=1) # WORKSHOP = 15 # 1 17 | Presentation.objects.filter(type=5).update(type=2) # KEYNOTE = 5 # 2 18 | 19 | 20 | class Migration(migrations.Migration): 21 | dependencies = [ 22 | ('timetable', '0006_auto_20190827_2044'), 23 | ] 24 | 25 | operations = [ 26 | migrations.AlterField( 27 | model_name='presentation', 28 | name='type', 29 | field=models.IntegerField(choices=[(10, 'Talk'), (15, 'Workshop'), (5, 'Keynote')], default=10), 30 | ), 31 | migrations.RunPython(forwards_func, reverse_func), 32 | ] 33 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/migrations/0008_auto_20190912_1847.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.2.4 on 2019-09-12 18:47 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | import pyconbalkan.conference.models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('conference', '0009_remove_conference_timetable_pdf'), 12 | ('timetable', '0007_auto_20190827_2247'), 13 | ] 14 | 15 | operations = [ 16 | migrations.RemoveField( 17 | model_name='slot', 18 | name='timetable', 19 | ), 20 | migrations.AddField( 21 | model_name='room', 22 | name='conference', 23 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 24 | ), 25 | migrations.AddField( 26 | model_name='room', 27 | name='sort_order', 28 | field=models.IntegerField(default=1), 29 | preserve_default=False, 30 | ), 31 | migrations.AddField( 32 | model_name='slot', 33 | name='conference', 34 | field=models.ForeignKey(default=pyconbalkan.conference.models._get_default_conference, on_delete=django.db.models.deletion.CASCADE, to='conference.Conference'), 35 | ), 36 | migrations.DeleteModel( 37 | name='Timetable', 38 | ), 39 | ] 40 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/timetable/migrations/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/timetable/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from pyconbalkan.timetable.models import Timetable 3 | 4 | 5 | class TimetableSerializer(serializers.ModelSerializer): 6 | class Meta: 7 | model = Timetable 8 | fields = '__all__' 9 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/templates/timetable_sessionize.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "base.html" %} 3 | {% load static %} 4 | 5 | {% block main_content %} 6 | {# Timetable #} 7 |

Timetable

8 | 9 | {% endblock main_content %} -------------------------------------------------------------------------------- /pyconbalkan/timetable/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /pyconbalkan/timetable/views.py: -------------------------------------------------------------------------------- 1 | 2 | from django.shortcuts import render 3 | 4 | from pyconbalkan.timetable.models import Room, Slot 5 | 6 | 7 | def timetable_view(request): 8 | slots_by_rooms = {} 9 | rooms = Room.objects.all() 10 | slots = Slot.objects.all() 11 | slots_order_by_date = slots.order_by('from_date') 12 | for room in rooms: 13 | slots_by_rooms[room.name] = slots_order_by_date.filter(room=room) 14 | days_count = 0 15 | DAYS = {} 16 | for slot in slots: 17 | if slot.from_date.date() not in DAYS: 18 | DAYS[slot.from_date.date()] = 'Day {}'.format(days_count + 1) 19 | days_count += 1 20 | context = { 21 | 'slots': slots_order_by_date, 22 | 'slots_by_rooms': slots_by_rooms, 23 | 'rooms': rooms, 24 | 'DAYS': DAYS 25 | } 26 | return render(request, 'timetable_sessionize.html', context) 27 | -------------------------------------------------------------------------------- /pyconbalkan/venue/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PythonBalkan/pyconbalkan/833deed488ba3ad2fa80ff144465a5755b5e1f15/pyconbalkan/venue/__init__.py -------------------------------------------------------------------------------- /pyconbalkan/venue/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | 4 | def venue_view(request): 5 | return render(request, 'venue.html') 6 | -------------------------------------------------------------------------------- /pyconbalkan/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for pyconbalkan project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | from dj_static import Cling 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pyconbalkan.settings") 16 | 17 | application = Cling(get_wsgi_application()) 18 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | pip-tools # Used to generate requirements.txt from requirements.in -------------------------------------------------------------------------------- /requirements.in: -------------------------------------------------------------------------------- 1 | boto3 2 | dj-database-url 3 | dj-static 4 | Django 5 | django-choices 6 | django-ckeditor 7 | django-countries 8 | django-filter 9 | django-markdownx 10 | django-meta 11 | django-money 12 | django-moneyfield 13 | django-storages 14 | django-tagging 15 | django-taggit 16 | djangorestframework 17 | gunicorn 18 | Markdown 19 | money 20 | psycopg2-binary 21 | py-moneyed 22 | python-decouple 23 | python-slugify 24 | pytz 25 | raven 26 | django-markdownify 27 | requests 28 | django-embed-video 29 | django-select2 30 | fuzzyfinder -------------------------------------------------------------------------------- /run_migrate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | python manage.py migrate 4 | python manage.py runserver 5 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.6.13 --------------------------------------------------------------------------------