diff --git a/accounts/__init__.py b/accounts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/accounts/admin.py b/accounts/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/accounts/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/accounts/apps.py b/accounts/apps.py new file mode 100644 index 0000000..3e3c765 --- /dev/null +++ b/accounts/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AccountsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'accounts' diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py new file mode 100644 index 0000000..32c2885 --- /dev/null +++ b/accounts/migrations/0001_initial.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2 on 2022-09-25 23:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='UserAccount', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(max_length=2555, null=True, unique=True)), + ('email', models.EmailField(max_length=255, unique=True)), + ('first_name', models.CharField(max_length=255)), + ('last_name', models.CharField(max_length=255)), + ('avatar', models.ImageField(blank=True, null=True, upload_to='avatar/')), + ('is_active', models.BooleanField(default=True)), + ('is_staff', models.BooleanField(default=False)), + ('get_newsletter', models.BooleanField(db_index=True, default=True)), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'User', + 'verbose_name_plural': 'Users', + 'ordering': ['-id'], + }, + ), + ] diff --git a/accounts/migrations/__init__.py b/accounts/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/accounts/models.py b/accounts/models.py new file mode 100644 index 0000000..4d92152 --- /dev/null +++ b/accounts/models.py @@ -0,0 +1,74 @@ +import datetime + +from django.conf import settings +from django.contrib.auth.models import (AbstractBaseUser, BaseUserManager, + PermissionsMixin) +from django.db import models + +# Create your models here. + +class UserAccountManager(BaseUserManager): + """ Manages the functions needed to create a user """ + def create_user(self, email, password=None, **extra_fields): + """ Creates and saves a new user """ + if not email: + raise ValueError("Users must have an email address") + + email = self.normalize_email(email) + user = self.model(email=email, **extra_fields) + + user.set_password(password) + user.save(using=self._db) + + return user + + def create_superuser(self, email, password, **extra_fields): + user = self.create_user(email, password, **extra_fields) + + user.is_superuser = True + user.is_staff = True + user.save(using=self._db) + + return user + + +class UserAccount(AbstractBaseUser, PermissionsMixin): + """ General user account fields """ + + username = models.CharField(max_length=2555, null=True, unique=True) + email = models.EmailField(max_length=255, unique=True) + first_name = models.CharField(max_length=255) + last_name = models.CharField(max_length=255) + avatar = models.ImageField(upload_to='avatar/', null=True, blank=True) + is_active = models.BooleanField(default=True) + is_staff = models.BooleanField(default=False) + get_newsletter = models.BooleanField(default=True, db_index=True) + + objects = UserAccountManager() + + USERNAME_FIELD = "email" + REQUIRED_FIELDS = ["first_name", "last_name"] + + class Meta: + ordering = ['-id'] + verbose_name = "User" + verbose_name_plural = "Users" + + + def get_short_name(self): + return self.first_name + + def __str__(self): + return self.email + + def get_or_create_userprofile(self): + from profiles.models import UserProfile + profile, _ = UserProfile.objects.get_or_create(user=self) + return profile + + def get_avatar(self): + profile = self.get_or_create_userprofile() + return profile.avatar + + + \ No newline at end of file diff --git a/accounts/tests.py b/accounts/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/accounts/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/accounts/urls.py b/accounts/urls.py new file mode 100644 index 0000000..84c07f9 --- /dev/null +++ b/accounts/urls.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from django.urls import include, path + +app_name = 'accounts' + +urlpatterns = [ + +] diff --git a/accounts/views.py b/accounts/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/accounts/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/album/__init__.py b/album/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/album/admin.py b/album/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/album/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/album/apps.py b/album/apps.py new file mode 100644 index 0000000..83b2048 --- /dev/null +++ b/album/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AlbumConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'album' diff --git a/album/migrations/__init__.py b/album/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/album/models.py b/album/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/album/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/album/serializers.py b/album/serializers.py new file mode 100644 index 0000000..e69de29 diff --git a/album/static/album/css/album.css b/album/static/album/css/album.css new file mode 100644 index 0000000..e3bdccc --- /dev/null +++ b/album/static/album/css/album.css @@ -0,0 +1,39 @@ +:root { + --jumbotron-padding-y: 3rem; + } + + .jumbotron { + padding-top: var(--jumbotron-padding-y); + padding-bottom: var(--jumbotron-padding-y); + margin-bottom: 0; + background-color: #fff; + } + @media (min-width: 768px) { + .jumbotron { + padding-top: calc(var(--jumbotron-padding-y) * 2); + padding-bottom: calc(var(--jumbotron-padding-y) * 2); + } + } + + .jumbotron p:last-child { + margin-bottom: 0; + } + + .jumbotron-heading { + font-weight: 300; + } + + .jumbotron .container { + max-width: 40rem; + } + + footer { + padding-top: 3rem; + padding-bottom: 3rem; + } + + footer p { + margin-bottom: .25rem; + } + + .box-shadow { box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); } \ No newline at end of file diff --git a/album/templates/album/base.html b/album/templates/album/base.html new file mode 100644 index 0000000..f101c3b --- /dev/null +++ b/album/templates/album/base.html @@ -0,0 +1,389 @@ +{% extends 'base.html' %} + +{% block content %} + +
+ + +
+ +
+
+
+

Album example

+

+ Something short and leading about the collection below—its contents, the + creator, etc. Make it short and sweet, but not too short so folks don't + simply skip over it entirely. +

+

+ Main call to action + Secondary action +

+
+
+ +
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+ +
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+ +
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+
+
+ +{% endblock content %} diff --git a/album/templates/album/homepage.html b/album/templates/album/homepage.html new file mode 100644 index 0000000..f101c3b --- /dev/null +++ b/album/templates/album/homepage.html @@ -0,0 +1,389 @@ +{% extends 'base.html' %} + +{% block content %} + +
+ + +
+ +
+
+
+

Album example

+

+ Something short and leading about the collection below—its contents, the + creator, etc. Make it short and sweet, but not too short so folks don't + simply skip over it entirely. +

+

+ Main call to action + Secondary action +

+
+
+ +
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+ +
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+ +
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+ Card image cap +
+

+ This is a wider card with supporting text below as a natural + lead-in to additional content. This content is a little bit + longer. +

+
+
+ + +
+ 9 mins +
+
+
+
+
+
+
+
+ +{% endblock content %} diff --git a/album/tests.py b/album/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/album/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/album/urls.py b/album/urls.py new file mode 100644 index 0000000..8c0ea0a --- /dev/null +++ b/album/urls.py @@ -0,0 +1,10 @@ +from django.contrib import admin +from django.urls import include, path + +from album.views import HomePageView + +app_name = 'album' + +urlpatterns = [ + path('', HomePageView.as_view(), name='homepage') +] diff --git a/album/views.py b/album/views.py new file mode 100644 index 0000000..15a7df7 --- /dev/null +++ b/album/views.py @@ -0,0 +1,38 @@ +from django.contrib.auth.mixins import LoginRequiredMixin +from django.core.exceptions import PermissionDenied +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render +from django.views.generic import CreateView, TemplateView + +# Create your views here. + +class HomePageView(TemplateView): + template_name = 'album/homepage.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + # NOTE: This will be used to update the active window in navbar + context.update({ + 'contact_us_create': 'active' + }) + + return context + + # def post(self, request, *args, **kwargs) -> HttpResponse: + # data = { + # 'user': request.user.id, + # 'title': request.POST.get('title'), + # 'description': request.POST.get('description'), + # 'inquiry_type': request.POST.get('inquiry_type'), + # } + # serializer = ContactUsCreateSerializer(data=data) + + # serializer.is_valid(raise_exception=True) + # instance = serializer.save() + + # send_new_inquiry_notification.delay(instance.id) + + # messages.success(self.request, 'Enquiry submitted successfully.') + + # return HttpResponseRedirect('/dashboard') diff --git a/config/settings/base.py b/config/settings/base.py index 3339ec0..d0913ff 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -1,15 +1,4 @@ -""" -Django settings for config project. - -Generated by 'django-admin startproject' using Django 3.2.3. - -For more information on this file, see -https://docs.djangoproject.com/en/3.2/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/3.2/ref/settings/ -""" - +import os from pathlib import Path # Build paths inside the project like this: BASE_DIR / 'subdir'. @@ -32,6 +21,15 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + + # Local apps + 'accounts', + 'album', + 'core', + 'profiles', + + # Third party apps + # .... ] MIDDLEWARE = [ @@ -49,7 +47,7 @@ ROOT_URLCONF = 'config.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], + 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -64,6 +62,7 @@ TEMPLATES = [ WSGI_APPLICATION = 'config.wsgi.application' +AUTH_USER_MODEL = "accounts.UserAccount" # Password validation # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators @@ -102,6 +101,13 @@ USE_TZ = True # https://docs.djangoproject.com/en/3.2/howto/static-files/ STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') +# STATICFILES_DIRS = ( +# os.path.join(BASE_DIR, 'static'), +# ) + +MEDIA_URL = '/media/' +MEDIA_ROOT = os.path.join(BASE_DIR, 'static/media') # Default primary key field type # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field diff --git a/config/settings/development.py b/config/settings/development.py index 8fb548e..ade2695 100644 --- a/config/settings/development.py +++ b/config/settings/development.py @@ -12,6 +12,6 @@ ALLOWED_HOSTS = [] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', + 'NAME': 'db.sqlite3', } } diff --git a/config/urls.py b/config/urls.py index d52e577..46b8582 100644 --- a/config/urls.py +++ b/config/urls.py @@ -1,21 +1,16 @@ -"""config URL Configuration - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/3.2/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" +from django.conf import settings +from django.conf.urls.static import static from django.contrib import admin -from django.urls import path +from django.urls import include, path urlpatterns = [ path('admin/', admin.site.urls), + path('', include('accounts.urls')), + path('', include('core.urls')), + path('', include('album.urls')), + path('', include('profiles.urls')), ] + + +urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) +urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/admin.py b/core/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/core/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/core/apps.py b/core/apps.py new file mode 100644 index 0000000..8115ae6 --- /dev/null +++ b/core/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CoreConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'core' diff --git a/core/migrations/__init__.py b/core/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/models.py b/core/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/core/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/core/tests.py b/core/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/core/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/core/urls.py b/core/urls.py new file mode 100644 index 0000000..fd32f41 --- /dev/null +++ b/core/urls.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from django.urls import include, path + +app_name = 'core' + +urlpatterns = [ + +] diff --git a/core/views.py b/core/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/core/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/db.sqlite3 b/db.sqlite3 index 102ce87..1172d98 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/profiles/__init__.py b/profiles/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/profiles/admin.py b/profiles/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/profiles/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/profiles/apps.py b/profiles/apps.py new file mode 100644 index 0000000..d722976 --- /dev/null +++ b/profiles/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ProfilesConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'profiles' diff --git a/profiles/migrations/0001_initial.py b/profiles/migrations/0001_initial.py new file mode 100644 index 0000000..068e0e4 --- /dev/null +++ b/profiles/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# Generated by Django 3.2 on 2022-09-25 23:10 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='UserProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('avatar', models.ImageField(blank=True, null=True, upload_to='avatar/')), + ('phone_number', models.CharField(blank=True, max_length=100, null=True)), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'verbose_name': 'UserProfile', + 'verbose_name_plural': 'UserProfiles', + }, + ), + ] diff --git a/profiles/migrations/__init__.py b/profiles/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/profiles/models.py b/profiles/models.py new file mode 100644 index 0000000..783415e --- /dev/null +++ b/profiles/models.py @@ -0,0 +1,31 @@ +import datetime + +from django.db import models + +from accounts.models import UserAccount + +# Create your models here. + + +class UserProfile(models.Model): + """Model definition for UserProfile.""" + # from order.models import Address + user = models.OneToOneField(UserAccount, on_delete=models.CASCADE) + avatar = models.ImageField(upload_to='avatar/', null=True, blank=True) + phone_number = models.CharField(max_length=100, null=True, blank=True) + + class Meta: + """Meta definition for UserProfile.""" + + verbose_name = 'UserProfile' + verbose_name_plural = 'UserProfiles' + + def __str__(self): + return self.user.email + + def get_shipping_address_data(self): + return None if not self.shipping_address else self.get_serialized_data(self.shipping_address) + + def get_billing_address_data(self): + return None if not self.billing_address else self.get_serialized_data(self.billing_address)\ + diff --git a/profiles/tests.py b/profiles/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/profiles/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/profiles/urls.py b/profiles/urls.py new file mode 100644 index 0000000..9424d10 --- /dev/null +++ b/profiles/urls.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from django.urls import include, path + +app_name = 'profiles' + +urlpatterns = [ + +] diff --git a/profiles/views.py b/profiles/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/profiles/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/requirements.txt b/requirements.txt index 38ae39e..cd0ae47 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,35 @@ asgiref==3.5.2 +astroid==2.12.10 +autopep8==1.7.0 backports.zoneinfo==0.2.1 +black==22.8.0 +certifi==2022.9.24 +charset-normalizer==2.0.12 +click==8.1.3 +decorator==5.1.1 +dill==0.3.5.1 Django==3.2 +idna==3.4 +isort==5.10.1 +lazy-object-proxy==1.7.1 +mccabe==0.7.0 +mypy-extensions==0.4.3 +pathspec==0.10.1 Pillow==9.2.0 +platformdirs==2.5.2 +pycodestyle==2.9.1 +pylint==2.15.3 python-decouple==3.6 pytz==2022.2.1 +requests==2.27.1 +six==1.16.0 sqlparse==0.4.3 +toml==0.10.2 +tomli==2.0.1 +tomlkit==0.11.4 +tqdm==4.64.1 +typing-extensions==4.3.0 +urllib3==1.26.12 +validators==0.18.2 +weaviate-client==3.8.0 +wrapt==1.14.1 diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..4476626 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,53 @@ + +{% load static %} + + + + + + + + + + + Photo Album + + + + + + + + + + + + + + {% block content %} + + {% endblock content %} + + + + + + {% comment %} + + + + {% endcomment %} + + + + + diff --git a/templates/homepage.html b/templates/homepage.html new file mode 100644 index 0000000..e69de29