27 changed files with 852 additions and 0 deletions
@ -0,0 +1,39 @@ |
|||
# Django project |
|||
/media/ |
|||
/static/ |
|||
*.sqlite3 |
|||
|
|||
# Python and others |
|||
__pycache__ |
|||
*.pyc |
|||
.DS_Store |
|||
*.swp |
|||
/venv/ |
|||
/tmp/ |
|||
/.vagrant/ |
|||
/Vagrantfile.local |
|||
node_modules/ |
|||
/npm-debug.log |
|||
/.idea/ |
|||
.vscode |
|||
coverage |
|||
.python-version |
|||
|
|||
# Distribution / packaging |
|||
.Python |
|||
env/ |
|||
build/ |
|||
develop-eggs/ |
|||
dist/ |
|||
downloads/ |
|||
eggs/ |
|||
.eggs/ |
|||
lib/ |
|||
lib64/ |
|||
parts/ |
|||
sdist/ |
|||
var/ |
|||
wheels/ |
|||
*.egg-info/ |
|||
.installed.cfg |
|||
*.egg |
@ -0,0 +1,60 @@ |
|||
# Use an official Python runtime based on Debian 10 "buster" as a parent image. |
|||
FROM python:3.8.1-slim-buster |
|||
|
|||
# Add user that will be used in the container. |
|||
RUN useradd wagtail |
|||
|
|||
# Port used by this container to serve HTTP. |
|||
EXPOSE 8000 |
|||
|
|||
# Set environment variables. |
|||
# 1. Force Python stdout and stderr streams to be unbuffered. |
|||
# 2. Set PORT variable that is used by Gunicorn. This should match "EXPOSE" |
|||
# command. |
|||
ENV PYTHONUNBUFFERED=1 \ |
|||
PORT=8000 |
|||
|
|||
# Install system packages required by Wagtail and Django. |
|||
RUN apt-get update --yes --quiet && apt-get install --yes --quiet --no-install-recommends \ |
|||
build-essential \ |
|||
libpq-dev \ |
|||
libmariadbclient-dev \ |
|||
libjpeg62-turbo-dev \ |
|||
zlib1g-dev \ |
|||
libwebp-dev \ |
|||
&& rm -rf /var/lib/apt/lists/* |
|||
|
|||
# Install the application server. |
|||
RUN pip install "gunicorn==20.0.4" |
|||
|
|||
# Install the project requirements. |
|||
COPY requirements.txt / |
|||
RUN pip install -r /requirements.txt |
|||
|
|||
# Use /app folder as a directory where the source code is stored. |
|||
WORKDIR /app |
|||
|
|||
# Set this directory to be owned by the "wagtail" user. This Wagtail project |
|||
# uses SQLite, the folder needs to be owned by the user that |
|||
# will be writing to the database file. |
|||
RUN chown wagtail:wagtail /app |
|||
|
|||
# Copy the source code of the project into the container. |
|||
COPY --chown=wagtail:wagtail . . |
|||
|
|||
# Use user "wagtail" to run the build commands below and the server itself. |
|||
USER wagtail |
|||
|
|||
# Collect static files. |
|||
RUN python manage.py collectstatic --noinput --clear |
|||
|
|||
# Runtime command that executes when "docker run" is called, it does the |
|||
# following: |
|||
# 1. Migrate the database. |
|||
# 2. Start the application server. |
|||
# WARNING: |
|||
# Migrating database at the same time as starting the server IS NOT THE BEST |
|||
# PRACTICE. The database should be migrated manually or using the release |
|||
# phase facilities of your hosting platform. This is used only so the |
|||
# Wagtail instance can be started with a simple "docker run" command. |
|||
CMD set -xe; python manage.py migrate --noinput; gunicorn blog.wsgi:application |
@ -0,0 +1,162 @@ |
|||
""" |
|||
Django settings for blog project. |
|||
|
|||
Generated by 'django-admin startproject' using Django 3.1.2. |
|||
|
|||
For more information on this file, see |
|||
https://docs.djangoproject.com/en/3.1/topics/settings/ |
|||
|
|||
For the full list of settings and their values, see |
|||
https://docs.djangoproject.com/en/3.1/ref/settings/ |
|||
""" |
|||
|
|||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) |
|||
import os |
|||
|
|||
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
|||
BASE_DIR = os.path.dirname(PROJECT_DIR) |
|||
|
|||
|
|||
# Quick-start development settings - unsuitable for production |
|||
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ |
|||
|
|||
|
|||
# Application definition |
|||
|
|||
INSTALLED_APPS = [ |
|||
'home', |
|||
'search', |
|||
|
|||
'wagtail.contrib.forms', |
|||
'wagtail.contrib.redirects', |
|||
'wagtail.embeds', |
|||
'wagtail.sites', |
|||
'wagtail.users', |
|||
'wagtail.snippets', |
|||
'wagtail.documents', |
|||
'wagtail.images', |
|||
'wagtail.search', |
|||
'wagtail.admin', |
|||
'wagtail.core', |
|||
|
|||
'modelcluster', |
|||
'taggit', |
|||
|
|||
'django.contrib.admin', |
|||
'django.contrib.auth', |
|||
'django.contrib.contenttypes', |
|||
'django.contrib.sessions', |
|||
'django.contrib.messages', |
|||
'django.contrib.staticfiles', |
|||
] |
|||
|
|||
MIDDLEWARE = [ |
|||
'django.contrib.sessions.middleware.SessionMiddleware', |
|||
'django.middleware.common.CommonMiddleware', |
|||
'django.middleware.csrf.CsrfViewMiddleware', |
|||
'django.contrib.auth.middleware.AuthenticationMiddleware', |
|||
'django.contrib.messages.middleware.MessageMiddleware', |
|||
'django.middleware.clickjacking.XFrameOptionsMiddleware', |
|||
'django.middleware.security.SecurityMiddleware', |
|||
|
|||
'wagtail.contrib.redirects.middleware.RedirectMiddleware', |
|||
] |
|||
|
|||
ROOT_URLCONF = 'blog.urls' |
|||
|
|||
TEMPLATES = [ |
|||
{ |
|||
'BACKEND': 'django.template.backends.django.DjangoTemplates', |
|||
'DIRS': [ |
|||
os.path.join(PROJECT_DIR, 'templates'), |
|||
], |
|||
'APP_DIRS': True, |
|||
'OPTIONS': { |
|||
'context_processors': [ |
|||
'django.template.context_processors.debug', |
|||
'django.template.context_processors.request', |
|||
'django.contrib.auth.context_processors.auth', |
|||
'django.contrib.messages.context_processors.messages', |
|||
], |
|||
}, |
|||
}, |
|||
] |
|||
|
|||
WSGI_APPLICATION = 'blog.wsgi.application' |
|||
|
|||
|
|||
# Database |
|||
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases |
|||
|
|||
DATABASES = { |
|||
'default': { |
|||
'ENGINE': 'django.db.backends.sqlite3', |
|||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), |
|||
} |
|||
} |
|||
|
|||
|
|||
# Password validation |
|||
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators |
|||
|
|||
AUTH_PASSWORD_VALIDATORS = [ |
|||
{ |
|||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', |
|||
}, |
|||
{ |
|||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', |
|||
}, |
|||
{ |
|||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', |
|||
}, |
|||
{ |
|||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', |
|||
}, |
|||
] |
|||
|
|||
|
|||
# Internationalization |
|||
# https://docs.djangoproject.com/en/3.1/topics/i18n/ |
|||
|
|||
LANGUAGE_CODE = 'en-us' |
|||
|
|||
TIME_ZONE = 'UTC' |
|||
|
|||
USE_I18N = True |
|||
|
|||
USE_L10N = True |
|||
|
|||
USE_TZ = True |
|||
|
|||
|
|||
# Static files (CSS, JavaScript, Images) |
|||
# https://docs.djangoproject.com/en/3.1/howto/static-files/ |
|||
|
|||
STATICFILES_FINDERS = [ |
|||
'django.contrib.staticfiles.finders.FileSystemFinder', |
|||
'django.contrib.staticfiles.finders.AppDirectoriesFinder', |
|||
] |
|||
|
|||
STATICFILES_DIRS = [ |
|||
os.path.join(PROJECT_DIR, 'static'), |
|||
] |
|||
|
|||
# ManifestStaticFilesStorage is recommended in production, to prevent outdated |
|||
# Javascript / CSS assets being served from cache (e.g. after a Wagtail upgrade). |
|||
# See https://docs.djangoproject.com/en/3.1/ref/contrib/staticfiles/#manifeststaticfilesstorage |
|||
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage' |
|||
|
|||
STATIC_ROOT = os.path.join(BASE_DIR, 'static') |
|||
STATIC_URL = '/static/' |
|||
|
|||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') |
|||
MEDIA_URL = '/media/' |
|||
|
|||
|
|||
# Wagtail settings |
|||
|
|||
WAGTAIL_SITE_NAME = "blog" |
|||
|
|||
# Base URL to use when referring to full URLs within the Wagtail admin backend - |
|||
# e.g. in notification emails. Don't include '/admin' or a trailing slash |
|||
BASE_URL = 'http://example.com' |
@ -0,0 +1,18 @@ |
|||
from .base import * |
|||
|
|||
# SECURITY WARNING: don't run with debug turned on in production! |
|||
DEBUG = True |
|||
|
|||
# SECURITY WARNING: keep the secret key used in production secret! |
|||
SECRET_KEY = '+&u(o6q&6ozwx93abpj(u=s)75d%@+vhk997iyh6))%(jy_&^&' |
|||
|
|||
# SECURITY WARNING: define the correct hosts in production! |
|||
ALLOWED_HOSTS = ['*'] |
|||
|
|||
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' |
|||
|
|||
|
|||
try: |
|||
from .local import * |
|||
except ImportError: |
|||
pass |
@ -0,0 +1,8 @@ |
|||
from .base import * |
|||
|
|||
DEBUG = False |
|||
|
|||
try: |
|||
from .local import * |
|||
except ImportError: |
|||
pass |
@ -0,0 +1,9 @@ |
|||
{% extends "base.html" %} |
|||
|
|||
{% block body_class %}template-404{% endblock %} |
|||
|
|||
{% block content %} |
|||
<h1>Page not found</h1> |
|||
|
|||
<h2>Sorry, this page could not be found.</h2> |
|||
{% endblock %} |
@ -0,0 +1,13 @@ |
|||
<!DOCTYPE html> |
|||
<html class="no-js"> |
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<title>Internal server error</title> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
|||
</head> |
|||
<body> |
|||
<h1>Internal server error</h1> |
|||
|
|||
<h2>Sorry, there seems to be an error. Please try again soon.</h2> |
|||
</body> |
|||
</html> |
@ -0,0 +1,40 @@ |
|||
{% load static wagtailuserbar %} |
|||
|
|||
<!DOCTYPE html> |
|||
<html class="no-js" lang="en"> |
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<title> |
|||
{% block title %} |
|||
{% if self.seo_title %}{{ self.seo_title }}{% else %}{{ self.title }}{% endif %} |
|||
{% endblock %} |
|||
{% block title_suffix %} |
|||
{% with self.get_site.site_name as site_name %} |
|||
{% if site_name %}- {{ site_name }}{% endif %} |
|||
{% endwith %} |
|||
{% endblock %} |
|||
</title> |
|||
<meta name="description" content="" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
|||
|
|||
{# Global stylesheets #} |
|||
<link rel="stylesheet" type="text/css" href="{% static 'css/blog.css' %}"> |
|||
|
|||
{% block extra_css %} |
|||
{# Override this in templates to add extra stylesheets #} |
|||
{% endblock %} |
|||
</head> |
|||
|
|||
<body class="{% block body_class %}{% endblock %}"> |
|||
{% wagtailuserbar %} |
|||
|
|||
{% block content %}{% endblock %} |
|||
|
|||
{# Global javascript #} |
|||
<script type="text/javascript" src="{% static 'js/blog.js' %}"></script> |
|||
|
|||
{% block extra_js %} |
|||
{# Override this in templates to add extra javascript #} |
|||
{% endblock %} |
|||
</body> |
|||
</html> |
@ -0,0 +1,39 @@ |
|||
from django.conf import settings |
|||
from django.urls import include, path |
|||
from django.contrib import admin |
|||
|
|||
from wagtail.admin import urls as wagtailadmin_urls |
|||
from wagtail.core import urls as wagtail_urls |
|||
from wagtail.documents import urls as wagtaildocs_urls |
|||
|
|||
from search import views as search_views |
|||
|
|||
urlpatterns = [ |
|||
path('django-admin/', admin.site.urls), |
|||
|
|||
path('admin/', include(wagtailadmin_urls)), |
|||
path('documents/', include(wagtaildocs_urls)), |
|||
|
|||
path('search/', search_views.search, name='search'), |
|||
|
|||
] |
|||
|
|||
|
|||
if settings.DEBUG: |
|||
from django.conf.urls.static import static |
|||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns |
|||
|
|||
# Serve static and media files from development server |
|||
urlpatterns += staticfiles_urlpatterns() |
|||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) |
|||
|
|||
urlpatterns = urlpatterns + [ |
|||
# For anything not caught by a more specific rule above, hand over to |
|||
# Wagtail's page serving mechanism. This should be the last pattern in |
|||
# the list: |
|||
path("", include(wagtail_urls)), |
|||
|
|||
# Alternatively, if you want Wagtail pages to be served from a subpath |
|||
# of your site, rather than the site root: |
|||
# path("pages/", include(wagtail_urls)), |
|||
] |
@ -0,0 +1,16 @@ |
|||
""" |
|||
WSGI config for blog project. |
|||
|
|||
It exposes the WSGI callable as a module-level variable named ``application``. |
|||
|
|||
For more information on this file, see |
|||
https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ |
|||
""" |
|||
|
|||
import os |
|||
|
|||
from django.core.wsgi import get_wsgi_application |
|||
|
|||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "blog.settings.dev") |
|||
|
|||
application = get_wsgi_application() |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('wagtailcore', '0040_page_draft_title'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.CreateModel( |
|||
name='HomePage', |
|||
fields=[ |
|||
('page_ptr', models.OneToOneField(on_delete=models.CASCADE, parent_link=True, auto_created=True, primary_key=True, serialize=False, to='wagtailcore.Page')), |
|||
], |
|||
options={ |
|||
'abstract': False, |
|||
}, |
|||
bases=('wagtailcore.page',), |
|||
), |
|||
] |
@ -0,0 +1,58 @@ |
|||
# -*- coding: utf-8 -*- |
|||
from django.db import migrations |
|||
|
|||
|
|||
def create_homepage(apps, schema_editor): |
|||
# Get models |
|||
ContentType = apps.get_model('contenttypes.ContentType') |
|||
Page = apps.get_model('wagtailcore.Page') |
|||
Site = apps.get_model('wagtailcore.Site') |
|||
HomePage = apps.get_model('home.HomePage') |
|||
|
|||
# Delete the default homepage |
|||
# If migration is run multiple times, it may have already been deleted |
|||
Page.objects.filter(id=2).delete() |
|||
|
|||
# Create content type for homepage model |
|||
homepage_content_type, __ = ContentType.objects.get_or_create( |
|||
model='homepage', app_label='home') |
|||
|
|||
# Create a new homepage |
|||
homepage = HomePage.objects.create( |
|||
title="Home", |
|||
draft_title="Home", |
|||
slug='home', |
|||
content_type=homepage_content_type, |
|||
path='00010001', |
|||
depth=2, |
|||
numchild=0, |
|||
url_path='/home/', |
|||
) |
|||
|
|||
# Create a site with the new homepage set as the root |
|||
Site.objects.create( |
|||
hostname='localhost', root_page=homepage, is_default_site=True) |
|||
|
|||
|
|||
def remove_homepage(apps, schema_editor): |
|||
# Get models |
|||
ContentType = apps.get_model('contenttypes.ContentType') |
|||
HomePage = apps.get_model('home.HomePage') |
|||
|
|||
# Delete the default homepage |
|||
# Page and Site objects CASCADE |
|||
HomePage.objects.filter(slug='home', depth=2).delete() |
|||
|
|||
# Delete content type for homepage model |
|||
ContentType.objects.filter(model='homepage', app_label='home').delete() |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('home', '0001_initial'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.RunPython(create_homepage, remove_homepage), |
|||
] |
@ -0,0 +1,7 @@ |
|||
from django.db import models |
|||
|
|||
from wagtail.core.models import Page |
|||
|
|||
|
|||
class HomePage(Page): |
|||
pass |
@ -0,0 +1,204 @@ |
|||
html { |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
*, |
|||
*:before, |
|||
*:after { |
|||
box-sizing: inherit; |
|||
} |
|||
|
|||
body { |
|||
max-width: 960px; |
|||
min-height: 100vh; |
|||
margin: 0 auto; |
|||
padding: 0 15px; |
|||
color: #231f20; |
|||
font-family: 'Helvetica Neue', 'Segoe UI', Arial, sans-serif; |
|||
line-height: 1.25; |
|||
} |
|||
|
|||
a { |
|||
background-color: transparent; |
|||
color: #308282; |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
a:hover { |
|||
color: #ea1b10; |
|||
} |
|||
|
|||
h1, |
|||
h2, |
|||
h3, |
|||
h4, |
|||
h5, |
|||
p, |
|||
ul { |
|||
padding: 0; |
|||
margin: 0; |
|||
font-weight: 400; |
|||
} |
|||
|
|||
main { |
|||
display: block; /* For IE11 support */ |
|||
} |
|||
|
|||
svg:not(:root) { |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.header { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding-top: 20px; |
|||
padding-bottom: 10px; |
|||
border-bottom: 1px solid #e6e6e6; |
|||
} |
|||
|
|||
.logo { |
|||
width: 150px; |
|||
margin-right: 20px; |
|||
} |
|||
|
|||
.logo a { |
|||
display: block; |
|||
} |
|||
|
|||
.figure-logo { |
|||
max-width: 150px; |
|||
max-height: 55.1px; |
|||
} |
|||
|
|||
.release-notes { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.main { |
|||
padding: 40px 0; |
|||
margin: 0 auto; |
|||
text-align: center; |
|||
} |
|||
|
|||
.figure-space { |
|||
max-width: 265px; |
|||
} |
|||
|
|||
@-webkit-keyframes pos { |
|||
0%, 100% { |
|||
-webkit-transform: rotate(-6deg); |
|||
transform: rotate(-6deg); |
|||
} |
|||
50% { |
|||
-webkit-transform: rotate(6deg); |
|||
transform: rotate(6deg); |
|||
} |
|||
} |
|||
|
|||
@keyframes pos { |
|||
0%, 100% { |
|||
-webkit-transform: rotate(-6deg); |
|||
transform: rotate(-6deg); |
|||
} |
|||
50% { |
|||
-webkit-transform: rotate(6deg); |
|||
transform: rotate(6deg); |
|||
} |
|||
} |
|||
|
|||
.egg { |
|||
fill: #43b1b0; |
|||
-webkit-animation: pos 3s ease infinite; |
|||
animation: pos 3s ease infinite; |
|||
-webkit-transform: translateY(50px); |
|||
transform: translateY(50px); |
|||
-webkit-transform-origin: 50% 80%; |
|||
transform-origin: 50% 80%; |
|||
} |
|||
|
|||
.main-text { |
|||
max-width: 400px; |
|||
margin: 5px auto; |
|||
} |
|||
|
|||
.main-text h1 { |
|||
font-size: 22px; |
|||
} |
|||
|
|||
.main-text p { |
|||
margin: 15px auto 0; |
|||
} |
|||
|
|||
.footer { |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
justify-content: space-between; |
|||
border-top: 1px solid #e6e6e6; |
|||
padding: 10px; |
|||
} |
|||
|
|||
.option { |
|||
display: block; |
|||
padding: 10px 10px 10px 34px; |
|||
position: relative; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
.option svg { |
|||
width: 24px; |
|||
height: 24px; |
|||
fill: gray; |
|||
border: 1px solid #d9d9d9; |
|||
padding: 5px; |
|||
border-radius: 100%; |
|||
top: 10px; |
|||
left: 0; |
|||
position: absolute; |
|||
} |
|||
|
|||
.option h4 { |
|||
font-size: 19px; |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
.option p { |
|||
padding-top: 3px; |
|||
color: #231f20; |
|||
font-size: 15px; |
|||
font-weight: 300; |
|||
} |
|||
|
|||
@media (max-width: 996px) { |
|||
body { |
|||
max-width: 780px; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 767px) { |
|||
.option { |
|||
flex: 0 0 50%; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 599px) { |
|||
.main { |
|||
padding: 20px 0; |
|||
} |
|||
|
|||
.figure-space { |
|||
max-width: 200px; |
|||
} |
|||
|
|||
.footer { |
|||
display: block; |
|||
width: 300px; |
|||
margin: 0 auto; |
|||
} |
|||
} |
|||
|
|||
@media (max-width: 360px) { |
|||
.header-link { |
|||
max-width: 100px; |
|||
} |
|||
} |
@ -0,0 +1,21 @@ |
|||
{% extends "base.html" %} |
|||
{% load static %} |
|||
|
|||
{% block body_class %}template-homepage{% endblock %} |
|||
|
|||
{% block extra_css %} |
|||
|
|||
{% comment %} |
|||
Delete the line below if you're just getting started and want to remove the welcome screen! |
|||
{% endcomment %} |
|||
<link rel="stylesheet" href="{% static 'css/welcome_page.css' %}"> |
|||
{% endblock extra_css %} |
|||
|
|||
{% block content %} |
|||
|
|||
{% comment %} |
|||
Delete the line below if you're just getting started and want to remove the welcome screen! |
|||
{% endcomment %} |
|||
{% include 'home/welcome_page.html' %} |
|||
|
|||
{% endblock content %} |
@ -0,0 +1,52 @@ |
|||
{% load i18n wagtailcore_tags %} |
|||
|
|||
<header class="header"> |
|||
<div class="logo"> |
|||
<a href="https://wagtail.io/"> |
|||
<svg class="figure-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 342.5 126.2"><title>{% trans "Visit the Wagtail website" %}</title><path fill="#FFF" d="M84 1.9v5.7s-10.2-3.8-16.8 3.1c-4.8 5-5.2 10.6-3 18.1 21.6 0 25 12.1 25 12.1L87 27l6.8-8.3c0-9.8-8.1-16.3-9.8-16.8z"/><circle cx="85.9" cy="15.9" r="2.6"/><path d="M89.2 40.9s-3.3-16.6-24.9-12.1c-2.2-7.5-1.8-13 3-18.1C73.8 3.8 84 7.6 84 7.6V1.9C80.4.3 77 0 73.2 0 59.3 0 51.6 10.4 48.3 17.4L9.2 89.3l11-2.1-20.2 39 14.1-2.5L24.9 93c30.6 0 69.8-11 64.3-52.1z"/><path d="M102.4 27l-8.6-8.3L87 27z"/><path fill="#FFF" d="M30 84.1s1-.2 2.8-.6c1.8-.4 4.3-1 7.3-1.8 1.5-.4 3.1-.9 4.8-1.5 1.7-.6 3.5-1.2 5.2-2 1.8-.7 3.6-1.6 5.4-2.6 1.8-1 3.5-2.1 5.1-3.4.4-.3.8-.6 1.2-1l1.2-1c.7-.7 1.5-1.4 2.2-2.2.7-.7 1.3-1.5 1.9-2.3l.9-1.2.4-.6.4-.6c.2-.4.5-.8.7-1.2.2-.4.4-.8.7-1.2l.3-.6.3-.6c.2-.4.4-.8.5-1.2l.9-2.4c.2-.8.5-1.6.7-2.3.2-.7.3-1.5.5-2.1.1-.7.2-1.3.3-2 .1-.6.2-1.2.2-1.7.1-.5.1-1 .2-1.5.1-1.8.1-2.8.1-2.8l1.6.1s-.1 1.1-.2 2.9c-.1.5-.1 1-.2 1.5-.1.6-.1 1.2-.3 1.8-.1.6-.3 1.3-.4 2-.2.7-.4 1.4-.6 2.2-.2.8-.5 1.5-.8 2.4-.3.8-.6 1.6-1 2.5l-.6 1.2-.3.6-.3.6c-.2.4-.5.8-.7 1.3-.3.4-.5.8-.8 1.2-.1.2-.3.4-.4.6l-.4.6-.9 1.2c-.7.8-1.3 1.6-2.1 2.3-.7.8-1.5 1.4-2.3 2.2l-1.2 1c-.4.3-.8.6-1.3.9-1.7 1.2-3.5 2.3-5.3 3.3-1.8.9-3.7 1.8-5.5 2.5-1.8.7-3.6 1.3-5.3 1.8-1.7.5-3.3 1-4.9 1.3-3 .7-5.6 1.3-7.4 1.6-1.6.6-2.6.8-2.6.8z"/><g fill="#231F20"><path d="M127 83.9h-8.8l-12.6-36.4h7.9l9 27.5 9-27.5h7.9l9 27.5 9-27.5h7.9L153 83.9h-8.8L135.6 59 127 83.9zM200.1 83.9h-7V79c-3 3.6-7 5.4-12.1 5.4-3.8 0-6.9-1.1-9.4-3.2s-3.7-5-3.7-8.6c0-3.6 1.3-6.3 4-8 2.6-1.8 6.2-2.7 10.7-2.7h9.9v-1.4c0-4.8-2.7-7.3-8.1-7.3-3.4 0-6.9 1.2-10.5 3.7l-3.4-4.8c4.4-3.5 9.4-5.3 15.1-5.3 4.3 0 7.8 1.1 10.5 3.2 2.7 2.2 4.1 5.6 4.1 10.2v23.7zm-7.7-13.6v-3.1h-8.6c-5.5 0-8.3 1.7-8.3 5.2 0 1.8.7 3.1 2.1 4.1 1.4.9 3.3 1.4 5.7 1.4 2.4 0 4.6-.7 6.4-2.1 1.8-1.3 2.7-3.1 2.7-5.5zM241.7 47.5v31.7c0 6.4-1.7 11.3-5.2 14.5-3.5 3.2-8 4.8-13.4 4.8-5.5 0-10.4-1.7-14.8-5.1l3.6-5.8c3.6 2.7 7.1 4 10.8 4 3.6 0 6.5-.9 8.6-2.8 2.1-1.9 3.2-4.9 3.2-9v-4.7c-1.1 2.1-2.8 3.9-4.9 5.1-2.1 1.3-4.5 1.9-7.1 1.9-4.8 0-8.8-1.7-11.9-5.1-3.1-3.4-4.7-7.6-4.7-12.6s1.6-9.2 4.7-12.6c3.1-3.4 7.1-5.1 11.9-5.1 4.8 0 8.7 2 11.7 6v-5.4h7.5zm-28.4 16.8c0 3 .9 5.6 2.8 7.7 1.8 2.2 4.3 3.2 7.5 3.2 3.1 0 5.7-1 7.6-3.1 1.9-2.1 2.9-4.7 2.9-7.8 0-3.1-1-5.8-2.9-7.9-2-2.2-4.5-3.2-7.6-3.2-3.1 0-5.6 1.1-7.4 3.4-2 2.1-2.9 4.7-2.9 7.7zM260.9 53.6v18.5c0 1.7.5 3.1 1.4 4.1.9 1 2.2 1.5 3.8 1.5 1.6 0 3.2-.8 4.7-2.4l3.1 5.4c-2.7 2.4-5.7 3.6-8.9 3.6-3.3 0-6-1.1-8.3-3.4-2.3-2.3-3.5-5.3-3.5-9.1V53.6h-4.6v-6.2h4.6V36.1h7.7v11.4h9.6v6.2h-9.6zM309.5 83.9h-7V79c-3 3.6-7 5.4-12.1 5.4-3.8 0-6.9-1.1-9.4-3.2s-3.7-5-3.7-8.6c0-3.6 1.3-6.3 4-8 2.6-1.8 6.2-2.7 10.7-2.7h9.9v-1.4c0-4.8-2.7-7.3-8.1-7.3-3.4 0-6.9 1.2-10.5 3.7l-3.4-4.8c4.4-3.5 9.4-5.3 15.1-5.3 4.3 0 7.8 1.1 10.5 3.2 2.7 2.2 4.1 5.6 4.1 10.2v23.7zm-7.7-13.6v-3.1h-8.6c-5.5 0-8.3 1.7-8.3 5.2 0 1.8.7 3.1 2.1 4.1 1.4.9 3.3 1.4 5.7 1.4 2.4 0 4.6-.7 6.4-2.1 1.8-1.3 2.7-3.1 2.7-5.5zM319.3 40.2c-1-1-1.4-2.1-1.4-3.4 0-1.3.5-2.5 1.4-3.4 1-1 2.1-1.4 3.4-1.4 1.3 0 2.5.5 3.4 1.4 1 1 1.4 2.1 1.4 3.4 0 1.3-.5 2.5-1.4 3.4s-2.1 1.4-3.4 1.4c-1.3.1-2.4-.4-3.4-1.4zm7.2 43.7h-7.7V47.5h7.7v36.4zM342.5 83.9h-7.7V33.1h7.7v50.8z"/></g></svg> |
|||
</a> |
|||
</div> |
|||
<div class="header-link"> |
|||
{% comment %} |
|||
This works for all cases but prerelease versions: |
|||
{% endcomment %} |
|||
<a href="{% wagtail_documentation_path %}/releases/{% wagtail_release_notes_path %}"> |
|||
{% trans "View the release notes" %} |
|||
</a> |
|||
</div> |
|||
</header> |
|||
<main class="main"> |
|||
<div class="figure"> |
|||
<svg class="figure-space" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300" aria-hidden="true"> |
|||
<path class="egg" fill="currentColor" d="M150 250c-42.741 0-75-32.693-75-90s42.913-110 75-110c32.088 0 75 52.693 75 110s-32.258 90-75 90z"/> |
|||
<ellipse fill="#ddd" cx="150" cy="270" rx="40" ry="7"/> |
|||
</svg> |
|||
</div> |
|||
<div class="main-text"> |
|||
<h1>{% trans "Welcome to your new Wagtail site!" %}</h1> |
|||
<p>{% trans 'Please feel free to <a href="https://github.com/wagtail/wagtail/wiki/Slack">join our community on Slack</a>, or get started with one of the links below.' %}</p> |
|||
</div> |
|||
</main> |
|||
<footer class="footer" role="contentinfo"> |
|||
<a class="option option-one" href="{% wagtail_documentation_path %}/"> |
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M9 21c0 .5.4 1 1 1h4c.6 0 1-.5 1-1v-1H9v1zm3-19C8.1 2 5 5.1 5 9c0 2.4 1.2 4.5 3 5.7V17c0 .5.4 1 1 1h6c.6 0 1-.5 1-1v-2.3c1.8-1.3 3-3.4 3-5.7 0-3.9-3.1-7-7-7zm2.9 11.1l-.9.6V16h-4v-2.3l-.9-.6C7.8 12.2 7 10.6 7 9c0-2.8 2.2-5 5-5s5 2.2 5 5c0 1.6-.8 3.2-2.1 4.1z"/></svg> |
|||
<div> |
|||
<h4>{% trans "Wagtail Documentation" %}</h4> |
|||
<p>{% trans "Topics, references, & how-tos" %}</p> |
|||
</div> |
|||
</a> |
|||
<a class="option option-two" href="{% wagtail_documentation_path %}/getting_started/tutorial.html"> |
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/></svg> |
|||
<div> |
|||
<h4>{% trans "Tutorial" %}</h4> |
|||
<p>{% trans "Build your first Wagtail site" %}</p> |
|||
</div> |
|||
</a> |
|||
<a class="option option-three" href="{% url 'wagtailadmin_home' %}"> |
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"><path d="M0 0h24v24H0z" fill="none"/><path d="M16.5 13c-1.2 0-3.07.34-4.5 1-1.43-.67-3.3-1-4.5-1C5.33 13 1 14.08 1 16.25V19h22v-2.75c0-2.17-4.33-3.25-6.5-3.25zm-4 4.5h-10v-1.25c0-.54 2.56-1.75 5-1.75s5 1.21 5 1.75v1.25zm9 0H14v-1.25c0-.46-.2-.86-.52-1.22.88-.3 1.96-.53 3.02-.53 2.44 0 5 1.21 5 1.75v1.25zM7.5 12c1.93 0 3.5-1.57 3.5-3.5S9.43 5 7.5 5 4 6.57 4 8.5 5.57 12 7.5 12zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 5.5c1.93 0 3.5-1.57 3.5-3.5S18.43 5 16.5 5 13 6.57 13 8.5s1.57 3.5 3.5 3.5zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z"/></svg> |
|||
<div> |
|||
<h4>{% trans "Admin Interface" %}</h4> |
|||
<p>{% trans "Create your superuser first!" %}</p> |
|||
</div> |
|||
</a> |
|||
</footer> |
@ -0,0 +1,10 @@ |
|||
#!/usr/bin/env python |
|||
import os |
|||
import sys |
|||
|
|||
if __name__ == "__main__": |
|||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "blog.settings.dev") |
|||
|
|||
from django.core.management import execute_from_command_line |
|||
|
|||
execute_from_command_line(sys.argv) |
@ -0,0 +1,2 @@ |
|||
Django>=3.1,<3.2 |
|||
wagtail>=2.10,<2.11 |
@ -0,0 +1,38 @@ |
|||
{% extends "base.html" %} |
|||
{% load static wagtailcore_tags %} |
|||
|
|||
{% block body_class %}template-searchresults{% endblock %} |
|||
|
|||
{% block title %}Search{% endblock %} |
|||
|
|||
{% block content %} |
|||
<h1>Search</h1> |
|||
|
|||
<form action="{% url 'search' %}" method="get"> |
|||
<input type="text" name="query"{% if search_query %} value="{{ search_query }}"{% endif %}> |
|||
<input type="submit" value="Search" class="button"> |
|||
</form> |
|||
|
|||
{% if search_results %} |
|||
<ul> |
|||
{% for result in search_results %} |
|||
<li> |
|||
<h4><a href="{% pageurl result %}">{{ result }}</a></h4> |
|||
{% if result.search_description %} |
|||
{{ result.search_description }} |
|||
{% endif %} |
|||
</li> |
|||
{% endfor %} |
|||
</ul> |
|||
|
|||
{% if search_results.has_previous %} |
|||
<a href="{% url 'search' %}?query={{ search_query|urlencode }}&page={{ search_results.previous_page_number }}">Previous</a> |
|||
{% endif %} |
|||
|
|||
{% if search_results.has_next %} |
|||
<a href="{% url 'search' %}?query={{ search_query|urlencode }}&page={{ search_results.next_page_number }}">Next</a> |
|||
{% endif %} |
|||
{% elif search_query %} |
|||
No results found |
|||
{% endif %} |
|||
{% endblock %} |
@ -0,0 +1,34 @@ |
|||
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator |
|||
from django.template.response import TemplateResponse |
|||
|
|||
from wagtail.core.models import Page |
|||
from wagtail.search.models import Query |
|||
|
|||
|
|||
def search(request): |
|||
search_query = request.GET.get('query', None) |
|||
page = request.GET.get('page', 1) |
|||
|
|||
# Search |
|||
if search_query: |
|||
search_results = Page.objects.live().search(search_query) |
|||
query = Query.get(search_query) |
|||
|
|||
# Record hit |
|||
query.add_hit() |
|||
else: |
|||
search_results = Page.objects.none() |
|||
|
|||
# Pagination |
|||
paginator = Paginator(search_results, 10) |
|||
try: |
|||
search_results = paginator.page(page) |
|||
except PageNotAnInteger: |
|||
search_results = paginator.page(1) |
|||
except EmptyPage: |
|||
search_results = paginator.page(paginator.num_pages) |
|||
|
|||
return TemplateResponse(request, 'search/search.html', { |
|||
'search_query': search_query, |
|||
'search_results': search_results, |
|||
}) |
Loading…
Reference in new issue