-
+ {% for page in pages %}
+
- {{page.name}} + {% endfor %} +
diff --git a/.gitignore b/.gitignore index cfe8779..e1dba2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ /build +*/uploads __pycache__ *.pyc .venv +*.sqlite3 diff --git a/README.md b/README.md index d08d610..d7112f5 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,19 @@ # wedding-site-backend +Web backend for hosting a wedding website. + +## Run development server: + +```sh +source .venv/bin/activate +cd wedding_site +python manage.py runserver +``` + +## Do Migrations + +```sh +cd wedding_site +python manage.py makemigrations primary +python manage.py migrate +``` \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index dddfeed..2e2e3ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ django markdown +pillow +beautifulsoup4 diff --git a/wedding_site/manage.py b/wedding_site/manage.py new file mode 100755 index 0000000..586897d --- /dev/null +++ b/wedding_site/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'wedding_site.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/wedding_site/primary/__init__.py b/wedding_site/primary/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wedding_site/primary/admin.py b/wedding_site/primary/admin.py new file mode 100644 index 0000000..e49b3c3 --- /dev/null +++ b/wedding_site/primary/admin.py @@ -0,0 +1,9 @@ +from django.contrib import admin + +# Register your models here. + +from .models import Site, Page, Image + +admin.site.register(Site) +admin.site.register(Page) +admin.site.register(Image) \ No newline at end of file diff --git a/wedding_site/primary/apps.py b/wedding_site/primary/apps.py new file mode 100644 index 0000000..bffd2c7 --- /dev/null +++ b/wedding_site/primary/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PrimaryConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'primary' diff --git a/wedding_site/primary/migrations/0001_initial.py b/wedding_site/primary/migrations/0001_initial.py new file mode 100644 index 0000000..fad6d38 --- /dev/null +++ b/wedding_site/primary/migrations/0001_initial.py @@ -0,0 +1,40 @@ +# Generated by Django 5.0.2 on 2024-02-10 17:58 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Image', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('alt_text', models.TextField()), + ], + ), + migrations.CreateModel( + name='Site', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('index', models.TextField()), + ], + ), + migrations.CreateModel( + name='Page', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField()), + ('name', models.CharField(max_length=200)), + ('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='primary.site')), + ], + ), + ] diff --git a/wedding_site/primary/migrations/0002_page_navigable_page_published_site_password.py b/wedding_site/primary/migrations/0002_page_navigable_page_published_site_password.py new file mode 100644 index 0000000..6488e51 --- /dev/null +++ b/wedding_site/primary/migrations/0002_page_navigable_page_published_site_password.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0.2 on 2024-02-10 18:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('primary', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='page', + name='navigable', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='page', + name='published', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='site', + name='password', + field=models.CharField(default='', max_length=200), + ), + ] diff --git a/wedding_site/primary/migrations/0003_site_name.py b/wedding_site/primary/migrations/0003_site_name.py new file mode 100644 index 0000000..134e77c --- /dev/null +++ b/wedding_site/primary/migrations/0003_site_name.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.2 on 2024-02-10 18:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('primary', '0002_page_navigable_page_published_site_password'), + ] + + operations = [ + migrations.AddField( + model_name='site', + name='name', + field=models.CharField(default='', max_length=200), + ), + ] diff --git a/wedding_site/primary/migrations/0004_template.py b/wedding_site/primary/migrations/0004_template.py new file mode 100644 index 0000000..6f215a2 --- /dev/null +++ b/wedding_site/primary/migrations/0004_template.py @@ -0,0 +1,21 @@ +# Generated by Django 5.0.2 on 2024-02-11 11:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('primary', '0003_site_name'), + ] + + operations = [ + migrations.CreateModel( + name='Template', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(default='', max_length=200)), + ('content', models.TextField()), + ], + ), + ] diff --git a/wedding_site/primary/migrations/0005_image_content_image_height_image_width.py b/wedding_site/primary/migrations/0005_image_content_image_height_image_width.py new file mode 100644 index 0000000..28c202e --- /dev/null +++ b/wedding_site/primary/migrations/0005_image_content_image_height_image_width.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0.2 on 2024-02-11 12:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('primary', '0004_template'), + ] + + operations = [ + migrations.AddField( + model_name='image', + name='content', + field=models.ImageField(default=None, height_field='height', upload_to='uploads', width_field='width'), + ), + migrations.AddField( + model_name='image', + name='height', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='image', + name='width', + field=models.IntegerField(default=0), + ), + ] diff --git a/wedding_site/primary/migrations/0006_site_header.py b/wedding_site/primary/migrations/0006_site_header.py new file mode 100644 index 0000000..eb129e7 --- /dev/null +++ b/wedding_site/primary/migrations/0006_site_header.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.2 on 2024-02-11 12:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('primary', '0005_image_content_image_height_image_width'), + ] + + operations = [ + migrations.AddField( + model_name='site', + name='header', + field=models.TextField(default=''), + ), + ] diff --git a/wedding_site/primary/migrations/0007_site_page_header.py b/wedding_site/primary/migrations/0007_site_page_header.py new file mode 100644 index 0000000..19ef19c --- /dev/null +++ b/wedding_site/primary/migrations/0007_site_page_header.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.2 on 2024-02-11 12:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('primary', '0006_site_header'), + ] + + operations = [ + migrations.AddField( + model_name='site', + name='page_header', + field=models.TextField(default=''), + ), + ] diff --git a/wedding_site/primary/migrations/0008_delete_template.py b/wedding_site/primary/migrations/0008_delete_template.py new file mode 100644 index 0000000..e059df4 --- /dev/null +++ b/wedding_site/primary/migrations/0008_delete_template.py @@ -0,0 +1,16 @@ +# Generated by Django 5.0.2 on 2024-02-11 13:13 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('primary', '0007_site_page_header'), + ] + + operations = [ + migrations.DeleteModel( + name='Template', + ), + ] diff --git a/wedding_site/primary/migrations/0009_page_pretty_name.py b/wedding_site/primary/migrations/0009_page_pretty_name.py new file mode 100644 index 0000000..58475cf --- /dev/null +++ b/wedding_site/primary/migrations/0009_page_pretty_name.py @@ -0,0 +1,18 @@ +# Generated by Django 5.0.2 on 2024-02-11 13:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('primary', '0008_delete_template'), + ] + + operations = [ + migrations.AddField( + model_name='page', + name='pretty_name', + field=models.CharField(default='', max_length=200), + ), + ] diff --git a/wedding_site/primary/migrations/__init__.py b/wedding_site/primary/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/wedding_site/primary/models.py b/wedding_site/primary/models.py new file mode 100644 index 0000000..a73c009 --- /dev/null +++ b/wedding_site/primary/models.py @@ -0,0 +1,34 @@ +from django.db import models + +class Site(models.Model): + name = models.CharField(max_length=200, default="") + title = models.CharField(max_length=200) + header = models.TextField(default="") + page_header = models.TextField(default="") + index = models.TextField() + password = models.CharField(max_length=200, default="") + + def __str__(self): + return self.name + +class Page(models.Model): + site = models.ForeignKey(Site, on_delete=models.CASCADE) + content = models.TextField() + name = models.CharField(max_length=200) + pretty_name = models.CharField(max_length=200, default="") + published = models.BooleanField(default=False) + navigable = models.BooleanField(default=False) + + def __str__(self): + return self.name + +class Image(models.Model): + name = models.CharField(max_length=200) + content = models.ImageField(upload_to="uploads", + width_field="width", height_field="height", default=None) + width = models.IntegerField(default=0) + height = models.IntegerField(default=0) + alt_text = models.TextField() + + def __str__(self): + return self.name diff --git a/wedding_site/primary/tests.py b/wedding_site/primary/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/wedding_site/primary/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/wedding_site/primary/urls.py b/wedding_site/primary/urls.py new file mode 100644 index 0000000..3fe02fa --- /dev/null +++ b/wedding_site/primary/urls.py @@ -0,0 +1,12 @@ + +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.index, name="index"), + path("schedule", views.schedule, name="schedule"), + path("thingstodo", views.things_to_do, name="thingstodo"), + path("travel", views.travel, name="travel"), +] + diff --git a/wedding_site/primary/views.py b/wedding_site/primary/views.py new file mode 100644 index 0000000..c315607 --- /dev/null +++ b/wedding_site/primary/views.py @@ -0,0 +1,112 @@ +from django.shortcuts import render +from django.http import HttpResponse + +from django.template import Template +from django.template import Context +import markdown +from bs4 import BeautifulSoup + +from .models import Site, Page + +_TEMPLATE = """ + + +
+ {{site_header}} + + + {{page_body}} + + + +""" + +_BODY = """ +