Merge pull request 'blog-markdown' (#31) from blog-markdown into devel
Reviewed-on: #31
This commit is contained in:
commit
1ce0d52302
15
README.md
15
README.md
|
@ -1,4 +1,4 @@
|
|||
# gawa
|
||||
# Gawa
|
||||
|
||||
Gawa is my personal website. I've personally written it using the Django framework.
|
||||
|
||||
|
@ -7,13 +7,13 @@ Gawa is my personal website. I've personally written it using the Django framewo
|
|||
These are the Credentials for logging into the admin panel:
|
||||
| Username | Password |
|
||||
|----------|----------|
|
||||
| root | root |
|
||||
| `root` | `root` |
|
||||
|
||||
### Blog
|
||||
|
||||
| Username | Password |
|
||||
|--------------------|--------------|
|
||||
| contact@cscherr.de | hrCcDa0jBspG |
|
||||
|--------------------------------------------------|----------------|
|
||||
| [`contact@cscherr.de`](mailto:contact@cscherr.de) | `hrCcDa0jBspG` |
|
||||
|
||||
## License
|
||||
|
||||
|
@ -22,6 +22,13 @@ Django: BSD 3-Clause "New" or "Revised" License
|
|||
|
||||
__Gawa: MIT Licensed, see LICENSE__
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Description | Package (fedora) |
|
||||
|----------------|------------------|
|
||||
| Database stuff | `libpq-devel` |
|
||||
| Database stuff | `mariadb` |
|
||||
|
||||
## Security
|
||||
|
||||
- [ ] Do something about the files in the blog dir
|
||||
|
|
|
@ -9,15 +9,18 @@ services:
|
|||
# MYSQL_PASSWORD: changethisforprod
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
volumes:
|
||||
- db_data:/var/lib/mysql
|
||||
# - db_data:/var/lib/mysql
|
||||
- ./docker/db/scripts:/docker-entrypoint-initdb.d/
|
||||
|
||||
main:
|
||||
build: ./docker/main
|
||||
command: bash -c "
|
||||
python manage.py migrate
|
||||
command: bash -c "echo 'setting django up'
|
||||
&& python manage.py collectstatic --noinput
|
||||
&& python manage.py runserver 0.0.0.0:8000
|
||||
&& sleep 3
|
||||
&& python manage.py migrate
|
||||
&& DJANGO_SUPERUSER_PASSWORD='root' python manage.py createsuperuser\
|
||||
--username root --noinput --email software@cscherr.de || true
|
||||
&& python manage.py runserver 0.0.0.0:80
|
||||
"
|
||||
volumes:
|
||||
- ./gawa:/app
|
||||
|
@ -43,21 +46,6 @@ services:
|
|||
- ./gawa/static:/srv/static
|
||||
- ./gawa/media:/srv/media
|
||||
|
||||
|
||||
blog:
|
||||
image: ghost
|
||||
environment:
|
||||
database__client: mysql
|
||||
database__connection__host: db
|
||||
database__connection__user: blog
|
||||
database__connection__password: blogpass
|
||||
database__connection__database: blog
|
||||
url: http://localhost:8081
|
||||
NODE_ENV: development
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
|
||||
db-admin:
|
||||
image: phpmyadmin
|
||||
ports:
|
||||
|
@ -71,4 +59,4 @@ services:
|
|||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
db_data:
|
||||
# db_data:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -22,863 +22,3 @@ SET time_zone = "+00:00";
|
|||
--
|
||||
CREATE DATABASE IF NOT EXISTS `gawa` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
|
||||
USE `gawa`;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `auth_group`
|
||||
--
|
||||
|
||||
CREATE TABLE `auth_group` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` varchar(150) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `auth_group_permissions`
|
||||
--
|
||||
|
||||
CREATE TABLE `auth_group_permissions` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`group_id` int(11) NOT NULL,
|
||||
`permission_id` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `auth_permission`
|
||||
--
|
||||
|
||||
CREATE TABLE `auth_permission` (
|
||||
`id` int(11) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`content_type_id` int(11) NOT NULL,
|
||||
`codename` varchar(100) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `auth_permission`
|
||||
--
|
||||
|
||||
INSERT INTO `auth_permission` (`id`, `name`, `content_type_id`, `codename`) VALUES
|
||||
(1, 'Can add keyword', 1, 'add_keyword'),
|
||||
(2, 'Can change keyword', 1, 'change_keyword'),
|
||||
(3, 'Can delete keyword', 1, 'delete_keyword'),
|
||||
(4, 'Can view keyword', 1, 'view_keyword'),
|
||||
(5, 'Can add searchable', 2, 'add_searchable'),
|
||||
(6, 'Can change searchable', 2, 'change_searchable'),
|
||||
(7, 'Can delete searchable', 2, 'delete_searchable'),
|
||||
(8, 'Can view searchable', 2, 'view_searchable'),
|
||||
(9, 'Can add static site', 3, 'add_staticsite'),
|
||||
(10, 'Can change static site', 3, 'change_staticsite'),
|
||||
(11, 'Can delete static site', 3, 'delete_staticsite'),
|
||||
(12, 'Can view static site', 3, 'view_staticsite'),
|
||||
(13, 'Can add category', 4, 'add_category'),
|
||||
(14, 'Can change category', 4, 'change_category'),
|
||||
(15, 'Can delete category', 4, 'delete_category'),
|
||||
(16, 'Can view category', 4, 'view_category'),
|
||||
(17, 'Can add blog post', 5, 'add_blogpost'),
|
||||
(18, 'Can change blog post', 5, 'change_blogpost'),
|
||||
(19, 'Can delete blog post', 5, 'delete_blogpost'),
|
||||
(20, 'Can view blog post', 5, 'view_blogpost'),
|
||||
(21, 'Can add log entry', 6, 'add_logentry'),
|
||||
(22, 'Can change log entry', 6, 'change_logentry'),
|
||||
(23, 'Can delete log entry', 6, 'delete_logentry'),
|
||||
(24, 'Can view log entry', 6, 'view_logentry'),
|
||||
(25, 'Can add permission', 7, 'add_permission'),
|
||||
(26, 'Can change permission', 7, 'change_permission'),
|
||||
(27, 'Can delete permission', 7, 'delete_permission'),
|
||||
(28, 'Can view permission', 7, 'view_permission'),
|
||||
(29, 'Can add group', 8, 'add_group'),
|
||||
(30, 'Can change group', 8, 'change_group'),
|
||||
(31, 'Can delete group', 8, 'delete_group'),
|
||||
(32, 'Can view group', 8, 'view_group'),
|
||||
(33, 'Can add user', 9, 'add_user'),
|
||||
(34, 'Can change user', 9, 'change_user'),
|
||||
(35, 'Can delete user', 9, 'delete_user'),
|
||||
(36, 'Can view user', 9, 'view_user'),
|
||||
(37, 'Can add content type', 10, 'add_contenttype'),
|
||||
(38, 'Can change content type', 10, 'change_contenttype'),
|
||||
(39, 'Can delete content type', 10, 'delete_contenttype'),
|
||||
(40, 'Can view content type', 10, 'view_contenttype'),
|
||||
(41, 'Can add session', 11, 'add_session'),
|
||||
(42, 'Can change session', 11, 'change_session'),
|
||||
(43, 'Can delete session', 11, 'delete_session'),
|
||||
(44, 'Can view session', 11, 'view_session'),
|
||||
(45, 'Can add Link', 12, 'add_link'),
|
||||
(46, 'Can change Link', 12, 'change_link'),
|
||||
(47, 'Can delete Link', 12, 'delete_link'),
|
||||
(48, 'Can view Link', 12, 'view_link');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `auth_user`
|
||||
--
|
||||
|
||||
CREATE TABLE `auth_user` (
|
||||
`id` int(11) NOT NULL,
|
||||
`password` varchar(128) NOT NULL,
|
||||
`last_login` datetime(6) DEFAULT NULL,
|
||||
`is_superuser` tinyint(1) NOT NULL,
|
||||
`username` varchar(150) NOT NULL,
|
||||
`first_name` varchar(150) NOT NULL,
|
||||
`last_name` varchar(150) NOT NULL,
|
||||
`email` varchar(254) NOT NULL,
|
||||
`is_staff` tinyint(1) NOT NULL,
|
||||
`is_active` tinyint(1) NOT NULL,
|
||||
`date_joined` datetime(6) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `auth_user`
|
||||
--
|
||||
|
||||
INSERT INTO `auth_user` (`id`, `password`, `last_login`, `is_superuser`, `username`, `first_name`, `last_name`, `email`, `is_staff`, `is_active`, `date_joined`) VALUES
|
||||
(1, 'pbkdf2_sha256$260000$cOxciSMkcV8kSVG1gUjOi7$LmOAxpppL7oBM2F+rFy0cdOZfReqdHqq1T6vw8PfODQ=', '2023-09-26 20:47:23.142649', 1, 'root', '', '', '', 1, 1, '2023-06-03 11:59:57.779755');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `auth_user_groups`
|
||||
--
|
||||
|
||||
CREATE TABLE `auth_user_groups` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`group_id` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `auth_user_user_permissions`
|
||||
--
|
||||
|
||||
CREATE TABLE `auth_user_user_permissions` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`permission_id` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `blog_blogpost`
|
||||
--
|
||||
|
||||
CREATE TABLE `blog_blogpost` (
|
||||
`searchable_ptr_id` bigint(20) NOT NULL,
|
||||
`thumbnail` varchar(100) NOT NULL,
|
||||
`category_id` bigint(20) DEFAULT NULL,
|
||||
`slug` varchar(50) NOT NULL,
|
||||
`featured` tinyint(1) NOT NULL,
|
||||
`markdown` tinyint(1) NOT NULL,
|
||||
`body_de` longtext NOT NULL,
|
||||
`body_en` longtext NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `blog_blogpost`
|
||||
--
|
||||
|
||||
INSERT INTO `blog_blogpost` (`searchable_ptr_id`, `thumbnail`, `category_id`, `slug`, `featured`, `markdown`, `body_de`, `body_en`) VALUES
|
||||
(3, 'img/thumbnails/echter_ottifant.png', 1, 'test', 1, 0, 'Bis jetzt keine deutsche Übersetzung.', '<pre>\r\n81.271 Aufrufe 29.03.2023\r\nStellaris First Contact challenge video. No FTL Challenge. We will not research or use any FTL methods, from hyperdrive to jump drive. Can we survive and become a galactic superpower? Or will the forces of darkness seek to usurp us!\r\n\r\nThey called me a madman.\r\nThey said it couldn\'t be done.\r\nNow I present to you,\r\n\r\nStellaris With No FTL Travel.\r\n\r\nLets Dive In!\r\n\r\nSellaris Stories Playlist: • Stellaris Playthr... \r\n\r\nStellaris Version 3.7\r\n\r\nIf you enjoyed this video please leave a like & SUBSCRIBE!\r\n\r\nHumble Bundle Affiliate link: https://www.humblebundle.com/?partner...\r\n\r\nPatreon: https://www.patreon.com/MontuPlays\r\nChannel Membership: / @montuplays \r\nTwitter: https://twitter.com/MontuPlays\r\nTwitch: https://www.twitch.tv/montuplays\r\nInstagram: https://www.instagram.com/montuplays/\r\nTiktok: https://www.tiktok.com/@montuplays\r\n\r\nAnd please comment with any feedback, any ideas or if you disagree!\r\n</pre>'),
|
||||
(4, 'img/thumbnails/thuglifemathemann.png', 1, 'hidden', 0, 0, 'Bis jetzt keine deutsche Übersetzung.', 'No english translation yet.'),
|
||||
(5, 'img/thumbnails/wayland_logo.jpg', 2, 'wayland', 1, 0, 'Bis jetzt keine deutsche Übersetzung.', 'No english translation yet.'),
|
||||
(6, 'img/thumbnails/Center_of_the_Milky_Way_Galaxy_IV__Composite.jpg', 1, 'badly-formatted', 1, 0, 'Bis jetzt keine deutsche Übersetzung.', 'No english translation yet.');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `blog_category`
|
||||
--
|
||||
|
||||
CREATE TABLE `blog_category` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`name` varchar(50) NOT NULL,
|
||||
`slug` varchar(50) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `blog_category`
|
||||
--
|
||||
|
||||
INSERT INTO `blog_category` (`id`, `name`, `slug`) VALUES
|
||||
(1, 'test', 'test'),
|
||||
(2, 'Linux', 'Linux');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `django_admin_log`
|
||||
--
|
||||
|
||||
CREATE TABLE `django_admin_log` (
|
||||
`id` int(11) NOT NULL,
|
||||
`action_time` datetime(6) NOT NULL,
|
||||
`object_id` longtext DEFAULT NULL,
|
||||
`object_repr` varchar(200) NOT NULL,
|
||||
`action_flag` smallint(5) UNSIGNED NOT NULL CHECK (`action_flag` >= 0),
|
||||
`change_message` longtext NOT NULL,
|
||||
`content_type_id` int(11) DEFAULT NULL,
|
||||
`user_id` int(11) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `django_admin_log`
|
||||
--
|
||||
|
||||
INSERT INTO `django_admin_log` (`id`, `action_time`, `object_id`, `object_repr`, `action_flag`, `change_message`, `content_type_id`, `user_id`) VALUES
|
||||
(1, '2023-06-03 12:04:18.697869', '1', 'Keyword object (1)', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(2, '2023-06-03 12:04:25.298763', '1', 'StaticSite object (1)', 1, '[{\"added\": {}}]', 3, 1),
|
||||
(3, '2023-06-03 12:39:47.580686', '2', 'Keyword object (2)', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(4, '2023-06-03 12:39:54.676532', '2', 'StaticSite object (2)', 1, '[{\"added\": {}}]', 3, 1),
|
||||
(5, '2023-06-03 18:49:19.838998', '3', 'Keyword object (3)', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(6, '2023-06-03 18:49:38.820915', '1', 'Category object (1)', 1, '[{\"added\": {}}]', 4, 1),
|
||||
(7, '2023-06-03 18:50:06.156603', '3', 'BlogPost object (3)', 1, '[{\"added\": {}}]', 5, 1),
|
||||
(8, '2023-06-03 22:24:55.684062', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Body\", \"Thumbnail\"]}}]', 5, 1),
|
||||
(9, '2023-06-03 22:25:23.238473', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Body\"]}}]', 5, 1),
|
||||
(10, '2023-06-03 22:32:15.868151', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(11, '2023-06-03 22:32:19.806919', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(12, '2023-06-03 22:34:12.390100', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(13, '2023-06-03 22:34:18.657049', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(14, '2023-06-03 22:35:20.148384', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(15, '2023-06-03 22:35:31.942529', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(16, '2023-06-03 22:37:55.565581', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(17, '2023-06-03 22:38:00.515394', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(18, '2023-06-03 22:42:32.527820', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(19, '2023-06-03 22:42:38.983331', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(20, '2023-06-03 22:43:03.221503', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(21, '2023-06-03 22:43:09.756742', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(22, '2023-06-03 22:43:32.898889', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(23, '2023-06-03 22:43:58.455830', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(24, '2023-06-03 22:44:49.711409', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(25, '2023-06-03 22:44:53.900045', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(26, '2023-06-03 22:46:22.495718', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(27, '2023-06-03 22:46:48.813958', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(28, '2023-06-03 23:10:31.960472', '3', 'BlogPost object (3)', 2, '[{\"changed\": {\"fields\": [\"Featured\"]}}]', 5, 1),
|
||||
(29, '2023-06-03 23:11:49.738524', '3', 'BlogPost object (3)', 2, '[]', 5, 1),
|
||||
(30, '2023-06-03 23:12:32.389296', '4', 'BlogPost object (4)', 1, '[{\"added\": {}}]', 5, 1),
|
||||
(31, '2023-06-03 23:12:40.179260', '4', 'BlogPost object (4)', 2, '[{\"changed\": {\"fields\": [\"Public\", \"Featured\"]}}]', 5, 1),
|
||||
(32, '2023-06-04 18:05:05.011703', '4', '{<BlogPost>\"hidden test\"}', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(33, '2023-06-04 18:30:33.544753', '4', '{<Keyword>\"some keyword\"}', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(34, '2023-06-04 18:30:36.040424', '4', '{<BlogPost>\"hidden test\"}', 2, '[{\"changed\": {\"fields\": [\"Keywords\"]}}]', 5, 1),
|
||||
(35, '2023-06-04 18:43:00.039374', '5', '{<Keyword>\"Linux\"}', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(36, '2023-06-04 18:43:06.821221', '6', '{<Keyword>\"Wayland\"}', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(37, '2023-06-04 18:43:30.492957', '2', '{<Category>\"Linux\"}', 1, '[{\"added\": {}}]', 4, 1),
|
||||
(38, '2023-06-04 18:43:53.420012', '5', '{<BlogPost>\"wayland\"}', 1, '[{\"added\": {}}]', 5, 1),
|
||||
(39, '2023-06-04 18:44:38.145122', '5', '{<BlogPost>\"wayland\"}', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(40, '2023-06-04 18:48:08.975475', '5', '{<BlogPost>\"wayland\"}', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(41, '2023-06-04 20:59:48.580334', '3', '{<BlogPost>\"test\"}', 2, '[{\"changed\": {\"fields\": [\"Keywords\"]}}]', 5, 1),
|
||||
(42, '2023-06-04 21:12:48.508525', '6', '{<BlogPost>\"keywords\"}', 1, '[{\"added\": {}}]', 5, 1),
|
||||
(43, '2023-06-04 21:13:03.091539', '6', '{<BlogPost>\"keywords\"}', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(44, '2023-06-04 21:13:30.855689', '6', '{<BlogPost>\"keywords\"}', 2, '[{\"changed\": {\"fields\": [\"Thumbnail\"]}}]', 5, 1),
|
||||
(45, '2023-06-05 16:17:00.484477', '7', '{<Keyword>\"selfhosting\"}', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(46, '2023-06-05 16:19:31.228250', 'https://european-alternatives.eu/', '{<Link>\"european alternative\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(47, '2023-06-05 16:19:42.921776', 'https://european-alternatives.eu/', '{<Link>\"european alternatives\"}', 2, '[{\"changed\": {\"fields\": [\"Title en\"]}}]', 12, 1),
|
||||
(48, '2023-06-05 16:40:04.807992', '8', '{<Keyword>\"tool\"}', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(49, '2023-06-05 16:40:51.112180', 'https://grep.app/', '{<Link>\"grep.app\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(50, '2023-06-05 16:46:27.851078', 'https://cscherr.de', '{<Link>\"title EN\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(51, '2023-06-05 16:46:30.662372', 'https://cscherr.de', '{<Link>\"title EN\"}', 2, '[]', 12, 1),
|
||||
(52, '2023-06-05 16:46:32.422354', 'https://cscherr.de', '{<Link>\"title EN\"}', 2, '[]', 12, 1),
|
||||
(53, '2023-06-05 16:46:59.815579', 'https://cscherr.de', '{<Link>\"title EN\"}', 2, '[]', 12, 1),
|
||||
(54, '2023-06-05 16:47:14.035243', 'https://cschderr.de', '{<Link>\"title EN\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(55, '2023-06-05 16:47:19.004185', 'https://dscschderr.de', '{<Link>\"title EN\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(56, '2023-06-05 16:47:23.499798', 'https://cssdachderr.de', '{<Link>\"title EN\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(57, '2023-06-05 17:13:16.967522', 'https://cscherr.de', '{<Link>\"title EN\"}', 2, '[{\"changed\": {\"fields\": [\"Keywords\"]}}]', 12, 1),
|
||||
(58, '2023-06-05 17:14:44.255231', 'https://dscschderr.de', '{<Link>\"title EN\"}', 3, '', 12, 1),
|
||||
(59, '2023-06-05 17:14:44.256420', 'https://cssdachderr.de', '{<Link>\"title EN\"}', 3, '', 12, 1),
|
||||
(60, '2023-06-05 17:14:44.257328', 'https://cscherr.de', '{<Link>\"title EN\"}', 3, '', 12, 1),
|
||||
(61, '2023-06-05 17:14:44.258159', 'https://cschderr.de', '{<Link>\"title EN\"}', 3, '', 12, 1),
|
||||
(62, '2023-06-05 17:57:00.163052', 'https://cscherr.de', '{<Link>\"title EN\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(63, '2023-06-05 20:58:00.230539', 'https://teslskdhglkjsahglkjdhflahgdlkjshgalskdhglkjsahglkjdsah.de', '{<Link>\"unavailable test\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(64, '2023-06-05 21:17:01.550940', '4', '{<BlogPost>\"hidden test\"}', 2, '[{\"changed\": {\"fields\": [\"Featured\"]}}]', 5, 1),
|
||||
(65, '2023-06-16 20:37:32.073731', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Title de\", \"Title en\", \"Subtitle de\", \"Subtitle en\", \"Desc de\", \"Desc en\", \"Body en\"]}}]', 5, 1),
|
||||
(66, '2023-06-16 22:05:16.217084', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Body en\"]}}]', 5, 1),
|
||||
(67, '2023-06-16 22:06:07.120314', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Body en\"]}}]', 5, 1),
|
||||
(68, '2023-06-16 22:09:16.732254', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Body en\"]}}]', 5, 1),
|
||||
(69, '2023-06-16 22:09:57.723744', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Desc de\"]}}]', 5, 1),
|
||||
(70, '2023-06-16 22:11:24.685523', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Desc en\"]}}]', 5, 1),
|
||||
(71, '2023-06-16 22:35:07.849677', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Desc de\"]}}]', 5, 1),
|
||||
(72, '2023-06-16 22:36:52.536498', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Body en\"]}}]', 5, 1),
|
||||
(73, '2023-06-16 22:37:59.812320', '3', '{<BlogPost>\"test en\"}', 2, '[{\"changed\": {\"fields\": [\"Body en\"]}}]', 5, 1),
|
||||
(74, '2023-07-15 12:44:37.681112', '9', '{<Keyword>\"social media\"}', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(75, '2023-07-15 12:44:47.420748', '10', '{<Keyword>\"mastodon\"}', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(76, '2023-07-15 12:46:17.179222', 'https://infosec.exchange/@plexsheep/', '{<Link>\"Mastodon\"}', 1, '[{\"added\": {}}]', 12, 1),
|
||||
(77, '2023-07-15 12:47:41.308504', 'https://cscherr.de', '{<Link>\"title EN\"}', 3, '', 12, 1),
|
||||
(78, '2023-09-27 18:43:24.048812', '11', '{<Keyword>\"Hacking\"}', 1, '[{\"added\": {}}]', 1, 1),
|
||||
(79, '2023-09-27 18:43:32.913389', 'https://cscg.de/', '{<Link>\"Cyber Security Challenge Germany\"}', 1, '[{\"added\": {}}]', 12, 1);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `django_content_type`
|
||||
--
|
||||
|
||||
CREATE TABLE `django_content_type` (
|
||||
`id` int(11) NOT NULL,
|
||||
`app_label` varchar(100) NOT NULL,
|
||||
`model` varchar(100) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `django_content_type`
|
||||
--
|
||||
|
||||
INSERT INTO `django_content_type` (`id`, `app_label`, `model`) VALUES
|
||||
(6, 'admin', 'logentry'),
|
||||
(8, 'auth', 'group'),
|
||||
(7, 'auth', 'permission'),
|
||||
(9, 'auth', 'user'),
|
||||
(5, 'blog', 'blogpost'),
|
||||
(4, 'blog', 'category'),
|
||||
(10, 'contenttypes', 'contenttype'),
|
||||
(11, 'sessions', 'session'),
|
||||
(1, 'start', 'keyword'),
|
||||
(12, 'start', 'link'),
|
||||
(2, 'start', 'searchable'),
|
||||
(3, 'start', 'staticsite');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `django_migrations`
|
||||
--
|
||||
|
||||
CREATE TABLE `django_migrations` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`app` varchar(255) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`applied` datetime(6) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `django_migrations`
|
||||
--
|
||||
|
||||
INSERT INTO `django_migrations` (`id`, `app`, `name`, `applied`) VALUES
|
||||
(1, 'contenttypes', '0001_initial', '2023-06-03 11:56:39.134383'),
|
||||
(2, 'auth', '0001_initial', '2023-06-03 11:56:39.493397'),
|
||||
(3, 'admin', '0001_initial', '2023-06-03 11:56:39.576389'),
|
||||
(4, 'admin', '0002_logentry_remove_auto_add', '2023-06-03 11:56:39.587912'),
|
||||
(5, 'admin', '0003_logentry_add_action_flag_choices', '2023-06-03 11:56:39.599213'),
|
||||
(6, 'contenttypes', '0002_remove_content_type_name', '2023-06-03 11:56:39.670533'),
|
||||
(7, 'auth', '0002_alter_permission_name_max_length', '2023-06-03 11:56:39.707524'),
|
||||
(8, 'auth', '0003_alter_user_email_max_length', '2023-06-03 11:56:39.731843'),
|
||||
(9, 'auth', '0004_alter_user_username_opts', '2023-06-03 11:56:39.745982'),
|
||||
(10, 'auth', '0005_alter_user_last_login_null', '2023-06-03 11:56:39.782422'),
|
||||
(11, 'auth', '0006_require_contenttypes_0002', '2023-06-03 11:56:39.785282'),
|
||||
(12, 'auth', '0007_alter_validators_add_error_messages', '2023-06-03 11:56:39.797106'),
|
||||
(13, 'auth', '0008_alter_user_username_max_length', '2023-06-03 11:56:39.827272'),
|
||||
(14, 'auth', '0009_alter_user_last_name_max_length', '2023-06-03 11:56:39.851866'),
|
||||
(15, 'auth', '0010_alter_group_name_max_length', '2023-06-03 11:56:39.879276'),
|
||||
(16, 'auth', '0011_update_proxy_permissions', '2023-06-03 11:56:39.894042'),
|
||||
(17, 'auth', '0012_alter_user_first_name_max_length', '2023-06-03 11:56:39.922412'),
|
||||
(18, 'sessions', '0001_initial', '2023-06-03 11:56:39.960733'),
|
||||
(19, 'start', '0001_initial', '2023-06-03 12:03:45.768696'),
|
||||
(20, 'start', '0002_keyword_searchable_staticsite', '2023-06-03 12:03:45.941730'),
|
||||
(21, 'blog', '0001_initial', '2023-06-03 12:03:45.945010'),
|
||||
(22, 'blog', '0002_blogpost_category', '2023-06-03 12:03:46.053269'),
|
||||
(23, 'blog', '0003_blogpost_public', '2023-06-03 18:52:48.544852'),
|
||||
(24, 'blog', '0004_blogpost_slug', '2023-06-03 19:06:14.602364'),
|
||||
(25, 'blog', '0005_auto_20230604_0050', '2023-06-03 22:50:53.031820'),
|
||||
(26, 'blog', '0006_blogpost_markdown', '2023-06-03 22:55:58.592031'),
|
||||
(27, 'blog', '0007_remove_blogpost_public', '2023-06-03 23:13:24.592228'),
|
||||
(28, 'start', '0003_searchable_public', '2023-06-03 23:13:24.624613'),
|
||||
(29, 'blog', '0008_auto_20230604_0156', '2023-06-03 23:56:46.268858'),
|
||||
(30, 'start', '0004_auto_20230604_2312', '2023-06-04 21:12:38.055586'),
|
||||
(31, 'start', '0005_link', '2023-06-05 16:15:09.586322'),
|
||||
(32, 'start', '0006_alter_searchable_title_en', '2023-06-05 16:18:36.026234'),
|
||||
(33, 'start', '0007_link_favicon', '2023-06-05 17:48:34.359895'),
|
||||
(34, 'start', '0008_link_status', '2023-06-05 20:55:49.654569'),
|
||||
(35, 'start', '0009_alter_link_favicon', '2023-06-05 23:01:06.878071'),
|
||||
(36, 'blog', '0009_auto_20230616_2236', '2023-06-16 20:36:25.811914'),
|
||||
(37, 'start', '0010_link_personal', '2023-07-15 12:20:30.979727'),
|
||||
(38, 'start', '0011_auto_20230715_1441', '2023-07-15 12:41:41.290671');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `django_session`
|
||||
--
|
||||
|
||||
CREATE TABLE `django_session` (
|
||||
`session_key` varchar(40) NOT NULL,
|
||||
`session_data` longtext NOT NULL,
|
||||
`expire_date` datetime(6) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `django_session`
|
||||
--
|
||||
|
||||
INSERT INTO `django_session` (`session_key`, `session_data`, `expire_date`) VALUES
|
||||
('0upcgnoxwloj2oe517p5gs49u5lp5zzq', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1qAGqc:py_DCOFJ-FumxDRyHNdQX5fRdemoczmVG1R6SSAoQXA', '2023-06-30 21:19:10.696506'),
|
||||
('1gv9x0aqsv9wnwjrdfn2jb2lmb6e7m1q', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1q6I0M:8ck2jJRPvLCTVo8eO3Uf55V1qSCCmhbIVhoTqD-r-Io', '2023-06-19 21:44:46.153044'),
|
||||
('2vj0n37v54tosuve9rzd869cxcto8mz2', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q5sLF:8r4rYdTtQYok9kkyr3UhO9m92jAPZC405pDYwP09-qA', '2023-06-18 18:20:37.522039'),
|
||||
('3xiqj0zj3hqhng68kgetjvl3h3ef6rga', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6Dwi:pSwhudkZDOHfIFHna_Qhk4zH3yb3hNDC_HIwKt70DIE', '2023-06-19 17:24:44.189905'),
|
||||
('64c4rub7ajgnj111shwcpvpvhfangkw6', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6IWp:gB20zXAKoPRbLklQlEzPAB2etNe510dvcw3HjZ2YqhE', '2023-06-19 22:18:19.400916'),
|
||||
('7ig4cdxegsgr67am0qahc168ne7vnl6n', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q5aKH:la2kbcUB5332lRGgq-fmRfExgAqu21jCINyFziVMiPw', '2023-06-17 23:06:25.760931'),
|
||||
('7zziio2fl6g4y2zlmbod3iqz8axi0c0w', '.eJxVjDsOgzAQBe_iOrLwD-yU6TmDtbteAwkyEuAqyt0DEg3tvJn3FXGGMlQYWDwFF_EQEeo-xrrxGqd0QHVnCPThcg7pfZSLpKXs64TyVOS1brJfEs-vy70djLCNR20Qk2tyY3UO1gT0wWhEm5kaF6gNGdkZRc560IrYAOkWsLPOd4iEIH5_vbE96w:1qAdo6:_7Ggp630uFVTXvIfzqnMcFQPZifnfd32YNw2xrRX4e4', '2023-07-01 21:50:06.829517'),
|
||||
('82mt5l930fx2l18pvq62xve1dyjuczg4', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6ImI:L5uK3sW-CLiZwmK82SRpB46kruvoVv7shUM9VtzOvaw', '2023-06-19 22:34:18.417914'),
|
||||
('90cu9ksglbxjuav0ycu34entpl3u4qze', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6DPn:FCYUrqa7sxjHrLAxvrd4xcXst3Bld3roZXiMIm6_F7g', '2023-06-19 16:50:43.835428'),
|
||||
('9vrglur3tcfw30khosdk0whixdw5868f', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6DJf:JMQ65g3ch9bxIJXCyHfBkmz8xqpCFDLqCCEB-Fjk1j8', '2023-06-19 16:44:23.542502'),
|
||||
('a4lile9twdhc1yhb4jm2v5arw3njpmej', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6bpg:OnpuTHTxOIhBWx00CQPrpYZhMxGIhsNypGHc_4oxT_Q', '2023-06-20 18:55:04.321078'),
|
||||
('aj8r2xou6zmiev2qu09skea7uxl7mk4s', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1qlEwK:PJsxynHSnR99RgKTXCdS04bczAM31zWnfKa_JbPQZJQ', '2023-10-10 20:45:52.004706'),
|
||||
('b19ur3eet73u66lfhf7iowvb8e6ki2td', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6IJN:ZIdTfsHuPhlUBDAW9wvz2hoEtMH4NYqgkomYVIieAhY', '2023-06-19 22:04:25.445445'),
|
||||
('b1xgysjxf4yjco704xam548jixstkxk4', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6IWp:gB20zXAKoPRbLklQlEzPAB2etNe510dvcw3HjZ2YqhE', '2023-06-19 22:18:19.426849'),
|
||||
('evj2deqvxhbyxb49e9h6l9na2qbaqf95', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q5QmI:1rGcG2CjkEKezGaLrT8fLFdInLOqIDp2ctZb5w2h9eY', '2023-06-17 12:54:42.590440'),
|
||||
('gx6813mra4mjk14s8731rtb9yrqepdq6', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6IJN:ZIdTfsHuPhlUBDAW9wvz2hoEtMH4NYqgkomYVIieAhY', '2023-06-19 22:04:25.426613'),
|
||||
('hseisfnzpao3n9vgsrm5xup83mnh5m8x', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6Ddw:jbkCHqvAo-dZVnT_cPPyzr3ifoYQ8RWqavgGkZOLxM4', '2023-06-19 17:05:20.044989'),
|
||||
('i99yua650ef8vl8b5fj5ap6adkwga4mf', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1qlEKO:T9QlV6VyTrt6qAIWcDbc_DQAlr_CjRHFQupnY92Oqnc', '2023-10-10 20:06:40.283402'),
|
||||
('iax6u7cdt7ccouzt9ewkgyzz1my8jl16', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6FnU:aw4jJP-LzV0_VQMDgNJdIAkd4HinLKxDb6fP3ls6p5I', '2023-06-19 19:23:20.996410'),
|
||||
('ir5lngwwf38u4ro0dreraqdv7sy8fl4j', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1qkrLe:q--VIRxGKEfZEr1h28GRACqTPEwcSGOklzwjb2-BBco', '2023-10-09 19:34:26.798740'),
|
||||
('jav4im7bxc31yig1weoojczl725hjetd', '.eJxVjDsOgzAQBe_iOrLwD-yU6TmDtbteAwkyEuAqyt0DEg3tvJn3FXGGMlQYWDwFF_EQEeo-xrrxGqd0QHVnCPThcg7pfZSLpKXs64TyVOS1brJfEs-vy70djLCNR20Qk2tyY3UO1gT0wWhEm5kaF6gNGdkZRc560IrYAOkWsLPOd4iEIH5_vbE96w:1qKfJc:bpPnwVuuqPB9oVGr8Revg7vj3eAIo1niHfWEmf8O0o0', '2023-07-29 13:28:04.767178'),
|
||||
('jf3upknvj24cbyz5ucf2hvqes4o6brzf', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1qAFve:_RL7IYW9MkLOwRPU7s-iljlJETcf2JNT8-s0CiQBgbI', '2023-06-30 20:20:18.080997'),
|
||||
('nowaza4auf15ea5ceduizupmuoai5wed', '.eJxVjDsOgzAQBe_iOrLwD-yU6TmDtbteAwkyEuAqyt0DEg3tvJn3FXGGMlQYWDwFF_EQEeo-xrrxGqd0QHVnCPThcg7pfZSLpKXs64TyVOS1brJfEs-vy70djLCNR20Qk2tyY3UO1gT0wWhEm5kaF6gNGdkZRc560IrYAOkWsLPOd4iEIH5_vbE96w:1qlZTU:uwTe0XhXUDx5AoyAuiMe8bsgud4-dczCsuKKhjQxjno', '2023-10-11 18:41:28.391526'),
|
||||
('nxbpuu69n360c4rtr30gatez80zceypc', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1q5uwg:26g54m5XFWYTIyQ_XXmbuFM0dXKFK5PjIpnffTPooec', '2023-06-18 21:07:26.651759'),
|
||||
('oksqlmqq4d95qbthf77cekpstsoras0x', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1qAHVI:zMwTYu2mF4TuMp3z6xyGegM5Z4dV2QOS4KErwB_42IY', '2023-06-30 22:01:12.013664'),
|
||||
('ou12hhptv10i3dicpx9eg73qhr2c2spw', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1qAFve:D4NUcsnUU5BQLest9ZT3q98QlX1Vidt_wW73IIUcD0c', '2023-06-30 20:20:18.023866'),
|
||||
('oxfk3q8saufspyg0hiinj9re5by7exfa', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1qKdzi:6328QizeSnm7IrCb8D9WhpBYgBql6UhxN2DT65FLV8I', '2023-07-29 12:03:26.437263'),
|
||||
('puu3uusjwghp6krjt33eh1hkd8zmpzp5', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6bpg:OnpuTHTxOIhBWx00CQPrpYZhMxGIhsNypGHc_4oxT_Q', '2023-06-20 18:55:04.318858'),
|
||||
('qizi095sgnejjvs8rwhp7pqdfekmallu', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1q5WGm:eC3Esvpesob9k12yWTUQU-w3r1_FbxdRLENuAFm9ZXk', '2023-06-17 18:46:32.666643'),
|
||||
('qkmrqp3xxmungtb5xbrwe2yjwe7lqt4g', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6D0o:MBtnPS-eBpBPozK1IVNCJRQ7FAd7kNKqq2aK4M8oq80', '2023-06-19 16:24:54.958490'),
|
||||
('qwkkyzzeqjg9172kyfek1hd9nzqtru3q', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6IWp:gB20zXAKoPRbLklQlEzPAB2etNe510dvcw3HjZ2YqhE', '2023-06-19 22:18:19.401336'),
|
||||
('qysgaziztbpgvtl3kyttosi93s1zwtvf', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q5QV9:1Uw36kLgFSXm1VjcuuiIGpkmQuRN_KK0Ma3Zl4DXT6o', '2023-06-17 12:36:59.495979'),
|
||||
('rkty698r11z7zm85k2geknm0rcjwyfqv', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6IWp:gB20zXAKoPRbLklQlEzPAB2etNe510dvcw3HjZ2YqhE', '2023-06-19 22:18:19.414335'),
|
||||
('rtammfv9ja1mbvbgw7sdw4veiyp03xxm', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6IJN:ZIdTfsHuPhlUBDAW9wvz2hoEtMH4NYqgkomYVIieAhY', '2023-06-19 22:04:25.435536'),
|
||||
('swp0hlg8yx4hxwu7u9d7si0o9m8it1pn', 'eyJfbGFuZ3VhZ2UiOiJlbiJ9:1q5uoj:aBQfKM4_0_2dMJJKcfn6UXCiUpxS-b_UgIJiN0nRaqo', '2023-06-18 20:59:13.449268'),
|
||||
('t2kwan6ekp81crswrsi9hii4b61imuue', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6DnA:j-cI0mcCObdleGdnyjXwXCzYLi4AmXpo610VPxQBmM4', '2023-06-19 17:14:52.657342'),
|
||||
('tvscp47jrsn5z4fzay4sozctp4o9tpr7', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6Ftl:fbR1czINKX_3OFLpBEjlPSoOqVf4B5Yx5U13i83cz2Y', '2023-06-19 19:29:49.516429'),
|
||||
('ty2uxmb0kropbz7ag4yk848t4hen54j7', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6J1L:beudjtx8mUL9cLZg3z3PKqP5hW8lp_inxnyW3f3HEDk', '2023-06-19 22:49:51.870050'),
|
||||
('whu9nbomfw3i5gs8fttvjxacu247tuft', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6Drn:Eb7ima9uOKmHWTfkubqTkzHczghiDOglJCki3bib51I', '2023-06-19 17:19:39.665491'),
|
||||
('z35tevuzugpk08wbgtlcvktitb5cuuvj', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1qkrLg:t7mBZwP_Vzcn3gtTR-jeZ3P779bwZI_4o502I-Erxks', '2023-10-09 19:34:28.894312'),
|
||||
('zj7tnj6l3xwq4n2vy4eg1gsvmc7rgagx', 'eyJfbGFuZ3VhZ2UiOiJkZSJ9:1q6Czj:IPERPMMtjCuW4sOHOEc7FY58NgjY0u8Lh10NMcinf_Y', '2023-06-19 16:23:47.958648');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `start_keyword`
|
||||
--
|
||||
|
||||
CREATE TABLE `start_keyword` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`text_de` varchar(40) NOT NULL,
|
||||
`text_en` varchar(40) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `start_keyword`
|
||||
--
|
||||
|
||||
INSERT INTO `start_keyword` (`id`, `text_de`, `text_en`) VALUES
|
||||
(1, 'Statisch', 'static'),
|
||||
(2, 'Blog', 'blog'),
|
||||
(3, 'test', 'test'),
|
||||
(4, 'ein keyword', 'some keyword'),
|
||||
(5, 'Linux', 'Linux'),
|
||||
(6, 'Wayland', 'Wayland'),
|
||||
(7, 'Selfhosting', 'selfhosting'),
|
||||
(8, 'Tool', 'tool'),
|
||||
(9, 'Social Media', 'social media'),
|
||||
(10, 'Mastodon', 'mastodon'),
|
||||
(11, 'Hacking', 'Hacking');
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `start_link`
|
||||
--
|
||||
|
||||
CREATE TABLE `start_link` (
|
||||
`searchable_ptr_id` bigint(20) NOT NULL,
|
||||
`url` varchar(200) NOT NULL,
|
||||
`favicon` varchar(100) DEFAULT NULL,
|
||||
`status` tinyint(1) NOT NULL,
|
||||
`personal` tinyint(1) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `start_link`
|
||||
--
|
||||
|
||||
INSERT INTO `start_link` (`searchable_ptr_id`, `url`, `favicon`, `status`, `personal`) VALUES
|
||||
(19, 'https://cscg.de/', 'img/links/favicons/favicon-12398.png', 1, 0),
|
||||
(10, 'https://european-alternatives.eu/', 'img/links/favicons/favicon-36105.png', 1, 0),
|
||||
(11, 'https://grep.app/', 'img/links/favicons/favicon-43495.png', 1, 0),
|
||||
(18, 'https://infosec.exchange/@plexsheep/', 'img/links/favicons/favicon-46734.png', 1, 1),
|
||||
(17, 'https://teslskdhglkjsahglkjdhflahgdlkjshgalskdhglkjsahglkjdsah.de', '', 0, 0);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `start_searchable`
|
||||
--
|
||||
|
||||
CREATE TABLE `start_searchable` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`title_de` varchar(50) NOT NULL,
|
||||
`title_en` varchar(50) NOT NULL,
|
||||
`subtitle_de` varchar(50) NOT NULL,
|
||||
`subtitle_en` varchar(50) NOT NULL,
|
||||
`desc_de` longtext NOT NULL,
|
||||
`desc_en` longtext NOT NULL,
|
||||
`date` date DEFAULT NULL,
|
||||
`suburl` varchar(200) DEFAULT NULL,
|
||||
`public` tinyint(1) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `start_searchable`
|
||||
--
|
||||
|
||||
INSERT INTO `start_searchable` (`id`, `title_de`, `title_en`, `subtitle_de`, `subtitle_en`, `desc_de`, `desc_en`, `date`, `suburl`, `public`) VALUES
|
||||
(1, 'Startseite', 'startpage', '', '', 'Die Startseite von cscherr.de', 'The startpage of cscherr.de', NULL, '/', 1),
|
||||
(2, 'Blog', 'blog', '', '', 'Die Startseite des Blogs', 'The startpage of the blob', NULL, '/blog', 1),
|
||||
(3, 'Test de', 'test en', 'test blogpost de', 'test blogpost en', 'selbst gebaut oder template? Moritz — gestern um 23:16 Uhr Selbst natürlich Christoph — gestern um 23:16 Uhr wenn du ein framework suchst empfehle ich django, gibt aber genug auswahl Moritz — gestern um 23:16 Uhr Brauche aber erstmal die Zeit, wollte', 'ENENENEN<div class=\"d-md-flex flex-md-row-reverse align-items-center justify-content-between\"> <div class=\"mb-3 mb-md-0 d-flex text-nowrap\"><a class=\"btn btn-sm btn-bd-light rounded-2\" href=\"https://github.com/twbs/bootstrap/blob/v5.3.0/sit', '2023-06-03', '/blog/test/test', 1),
|
||||
(4, 'hidden test', 'hidden test', '', '', 'Beschreibung DE', 'Description EN', NULL, '/blog/test/hidden', 1),
|
||||
(5, 'Wayland', 'wayland', 'Linux Display Server', 'linux display server', 'Wayland ist ein Linux Display Server der endlich X11 verdrängen soll.', 'Wayland is a linux display server that will finally make X11 legacy software.', '2023-06-04', '/blog/Linux/wayland', 1),
|
||||
(6, 'schlüsslis', 'keywords', 'viele von denen', 'too many', 'Beschreibung DE', 'Description EN', '2023-06-04', '/blog/test/badly-formatted', 1),
|
||||
(10, 'Europäische Alternativen', 'european alternatives', '', '', 'Hilft bei der Suche nach europäischen Alternativen für digitale Dienstleistungen und Produkte, wie Cloud-Dienste und SaaS-Produkte.', 'Helps you find European alternatives for digital service and products, like cloud services and SaaS products.', '2023-06-05', '/links#european alternatives', 1),
|
||||
(11, 'grep.app', 'grep.app', '', '', 'Suche über eine halbe Million Git-Repos', 'Search across a half million git repos', '2023-06-05', '/links#grep.app', 1),
|
||||
(17, 'unavailable test', 'unavailable test', '', '', 'Beschreibung DE', 'Description EN', NULL, '/links#unavailable test', 1),
|
||||
(18, 'Mastodon', 'Mastodon', 'Dezentralisiertes social Media', 'decentralized social media', 'Mastodon ist ein Microblogging Dienst im Fediverse. Ähnlich wie Twitter, aber besser.', 'Mastodon is a microblogging service on the fediverse, think twitter but better and more free.', '2023-07-15', '/links#Mastodon', 1),
|
||||
(19, 'Cyber Security Challenge Deutschland', 'Cyber Security Challenge Germany', 'Nationaler IT-Sicherheitswettbewerb', 'National IT-Security Competition', 'Wettbewerb für Jugendliche (bis zu 25 Jahren) im Bereich IT-Sicherheit', 'Competition for youth (up to 25 years old) in Cybersecurity', '2023-09-27', '/links#Cyber Security Challenge Germany', 1);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `start_searchable_keywords`
|
||||
--
|
||||
|
||||
CREATE TABLE `start_searchable_keywords` (
|
||||
`id` bigint(20) NOT NULL,
|
||||
`searchable_id` bigint(20) NOT NULL,
|
||||
`keyword_id` bigint(20) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `start_searchable_keywords`
|
||||
--
|
||||
|
||||
INSERT INTO `start_searchable_keywords` (`id`, `searchable_id`, `keyword_id`) VALUES
|
||||
(1, 1, 1),
|
||||
(2, 2, 2),
|
||||
(9, 3, 1),
|
||||
(10, 3, 2),
|
||||
(3, 3, 3),
|
||||
(4, 4, 3),
|
||||
(5, 4, 4),
|
||||
(6, 5, 3),
|
||||
(7, 5, 5),
|
||||
(8, 5, 6),
|
||||
(11, 6, 1),
|
||||
(12, 6, 2),
|
||||
(13, 6, 3),
|
||||
(14, 6, 4),
|
||||
(15, 6, 5),
|
||||
(16, 6, 6),
|
||||
(20, 10, 7),
|
||||
(21, 11, 8),
|
||||
(34, 17, 3),
|
||||
(35, 18, 9),
|
||||
(36, 18, 10),
|
||||
(37, 19, 11);
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- Tabellenstruktur für Tabelle `start_staticsite`
|
||||
--
|
||||
|
||||
CREATE TABLE `start_staticsite` (
|
||||
`searchable_ptr_id` bigint(20) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
-- Daten für Tabelle `start_staticsite`
|
||||
--
|
||||
|
||||
INSERT INTO `start_staticsite` (`searchable_ptr_id`) VALUES
|
||||
(1),
|
||||
(2);
|
||||
|
||||
--
|
||||
-- Indizes der exportierten Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `auth_group`
|
||||
--
|
||||
ALTER TABLE `auth_group`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `name` (`name`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `auth_group_permissions`
|
||||
--
|
||||
ALTER TABLE `auth_group_permissions`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `auth_group_permissions_group_id_permission_id_0cd325b0_uniq` (`group_id`,`permission_id`),
|
||||
ADD KEY `auth_group_permissio_permission_id_84c5c92e_fk_auth_perm` (`permission_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `auth_permission`
|
||||
--
|
||||
ALTER TABLE `auth_permission`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `auth_permission_content_type_id_codename_01ab375a_uniq` (`content_type_id`,`codename`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `auth_user`
|
||||
--
|
||||
ALTER TABLE `auth_user`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `username` (`username`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `auth_user_groups`
|
||||
--
|
||||
ALTER TABLE `auth_user_groups`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `auth_user_groups_user_id_group_id_94350c0c_uniq` (`user_id`,`group_id`),
|
||||
ADD KEY `auth_user_groups_group_id_97559544_fk_auth_group_id` (`group_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `auth_user_user_permissions`
|
||||
--
|
||||
ALTER TABLE `auth_user_user_permissions`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `auth_user_user_permissions_user_id_permission_id_14a6b632_uniq` (`user_id`,`permission_id`),
|
||||
ADD KEY `auth_user_user_permi_permission_id_1fbb5f2c_fk_auth_perm` (`permission_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `blog_blogpost`
|
||||
--
|
||||
ALTER TABLE `blog_blogpost`
|
||||
ADD PRIMARY KEY (`searchable_ptr_id`),
|
||||
ADD KEY `blog_blogpost_category_id_0e9835dd_fk_blog_category_id` (`category_id`),
|
||||
ADD KEY `blog_blogpost_slug_9e84ade1` (`slug`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `blog_category`
|
||||
--
|
||||
ALTER TABLE `blog_category`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `blog_category_slug_92643dc5` (`slug`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `django_admin_log`
|
||||
--
|
||||
ALTER TABLE `django_admin_log`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD KEY `django_admin_log_content_type_id_c4bce8eb_fk_django_co` (`content_type_id`),
|
||||
ADD KEY `django_admin_log_user_id_c564eba6_fk_auth_user_id` (`user_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `django_content_type`
|
||||
--
|
||||
ALTER TABLE `django_content_type`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `django_content_type_app_label_model_76bd3d3b_uniq` (`app_label`,`model`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `django_migrations`
|
||||
--
|
||||
ALTER TABLE `django_migrations`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `django_session`
|
||||
--
|
||||
ALTER TABLE `django_session`
|
||||
ADD PRIMARY KEY (`session_key`),
|
||||
ADD KEY `django_session_expire_date_a5c62663` (`expire_date`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `start_keyword`
|
||||
--
|
||||
ALTER TABLE `start_keyword`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `start_link`
|
||||
--
|
||||
ALTER TABLE `start_link`
|
||||
ADD PRIMARY KEY (`url`),
|
||||
ADD UNIQUE KEY `searchable_ptr_id` (`searchable_ptr_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `start_searchable`
|
||||
--
|
||||
ALTER TABLE `start_searchable`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `start_searchable_keywords`
|
||||
--
|
||||
ALTER TABLE `start_searchable_keywords`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `start_searchable_keywords_searchable_id_keyword_id_2feb5e58_uniq` (`searchable_id`,`keyword_id`),
|
||||
ADD KEY `start_searchable_key_keyword_id_230512a8_fk_start_key` (`keyword_id`);
|
||||
|
||||
--
|
||||
-- Indizes für die Tabelle `start_staticsite`
|
||||
--
|
||||
ALTER TABLE `start_staticsite`
|
||||
ADD PRIMARY KEY (`searchable_ptr_id`);
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für exportierte Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `auth_group`
|
||||
--
|
||||
ALTER TABLE `auth_group`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `auth_group_permissions`
|
||||
--
|
||||
ALTER TABLE `auth_group_permissions`
|
||||
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `auth_permission`
|
||||
--
|
||||
ALTER TABLE `auth_permission`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=49;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `auth_user`
|
||||
--
|
||||
ALTER TABLE `auth_user`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `auth_user_groups`
|
||||
--
|
||||
ALTER TABLE `auth_user_groups`
|
||||
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `auth_user_user_permissions`
|
||||
--
|
||||
ALTER TABLE `auth_user_user_permissions`
|
||||
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `blog_category`
|
||||
--
|
||||
ALTER TABLE `blog_category`
|
||||
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `django_admin_log`
|
||||
--
|
||||
ALTER TABLE `django_admin_log`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=80;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `django_content_type`
|
||||
--
|
||||
ALTER TABLE `django_content_type`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=13;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `django_migrations`
|
||||
--
|
||||
ALTER TABLE `django_migrations`
|
||||
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=39;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `start_keyword`
|
||||
--
|
||||
ALTER TABLE `start_keyword`
|
||||
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `start_searchable`
|
||||
--
|
||||
ALTER TABLE `start_searchable`
|
||||
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=20;
|
||||
|
||||
--
|
||||
-- AUTO_INCREMENT für Tabelle `start_searchable_keywords`
|
||||
--
|
||||
ALTER TABLE `start_searchable_keywords`
|
||||
MODIFY `id` bigint(20) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=38;
|
||||
|
||||
--
|
||||
-- Constraints der exportierten Tabellen
|
||||
--
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `auth_group_permissions`
|
||||
--
|
||||
ALTER TABLE `auth_group_permissions`
|
||||
ADD CONSTRAINT `auth_group_permissio_permission_id_84c5c92e_fk_auth_perm` FOREIGN KEY (`permission_id`) REFERENCES `auth_permission` (`id`),
|
||||
ADD CONSTRAINT `auth_group_permissions_group_id_b120cbf9_fk_auth_group_id` FOREIGN KEY (`group_id`) REFERENCES `auth_group` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `auth_permission`
|
||||
--
|
||||
ALTER TABLE `auth_permission`
|
||||
ADD CONSTRAINT `auth_permission_content_type_id_2f476e4b_fk_django_co` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `auth_user_groups`
|
||||
--
|
||||
ALTER TABLE `auth_user_groups`
|
||||
ADD CONSTRAINT `auth_user_groups_group_id_97559544_fk_auth_group_id` FOREIGN KEY (`group_id`) REFERENCES `auth_group` (`id`),
|
||||
ADD CONSTRAINT `auth_user_groups_user_id_6a12ed8b_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `auth_user_user_permissions`
|
||||
--
|
||||
ALTER TABLE `auth_user_user_permissions`
|
||||
ADD CONSTRAINT `auth_user_user_permi_permission_id_1fbb5f2c_fk_auth_perm` FOREIGN KEY (`permission_id`) REFERENCES `auth_permission` (`id`),
|
||||
ADD CONSTRAINT `auth_user_user_permissions_user_id_a95ead1b_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `blog_blogpost`
|
||||
--
|
||||
ALTER TABLE `blog_blogpost`
|
||||
ADD CONSTRAINT `blog_blogpost_category_id_0e9835dd_fk_blog_category_id` FOREIGN KEY (`category_id`) REFERENCES `blog_category` (`id`),
|
||||
ADD CONSTRAINT `blog_blogpost_searchable_ptr_id_2b1446e8_fk_start_searchable_id` FOREIGN KEY (`searchable_ptr_id`) REFERENCES `start_searchable` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `django_admin_log`
|
||||
--
|
||||
ALTER TABLE `django_admin_log`
|
||||
ADD CONSTRAINT `django_admin_log_content_type_id_c4bce8eb_fk_django_co` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`),
|
||||
ADD CONSTRAINT `django_admin_log_user_id_c564eba6_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `start_link`
|
||||
--
|
||||
ALTER TABLE `start_link`
|
||||
ADD CONSTRAINT `start_link_searchable_ptr_id_be644807_fk_start_searchable_id` FOREIGN KEY (`searchable_ptr_id`) REFERENCES `start_searchable` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `start_searchable_keywords`
|
||||
--
|
||||
ALTER TABLE `start_searchable_keywords`
|
||||
ADD CONSTRAINT `start_searchable_key_keyword_id_230512a8_fk_start_key` FOREIGN KEY (`keyword_id`) REFERENCES `start_keyword` (`id`),
|
||||
ADD CONSTRAINT `start_searchable_key_searchable_id_a2d58376_fk_start_sea` FOREIGN KEY (`searchable_id`) REFERENCES `start_searchable` (`id`);
|
||||
|
||||
--
|
||||
-- Constraints der Tabelle `start_staticsite`
|
||||
--
|
||||
ALTER TABLE `start_staticsite`
|
||||
ADD CONSTRAINT `start_staticsite_searchable_ptr_id_aae84485_fk_start_sea` FOREIGN KEY (`searchable_ptr_id`) REFERENCES `start_searchable` (`id`);
|
||||
COMMIT;
|
||||
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
|
|
|
@ -8,3 +8,5 @@ RUN apt update && apt install -y gettext && rm -rf /var/lib/apt/lists/*
|
|||
COPY requirements.txt /app/
|
||||
RUN pip install -r requirements.txt
|
||||
COPY . /app/
|
||||
RUN mkdir -p /app/static
|
||||
RUN pygmentize -S nord -f html -a .codehilite > /app/static/codehighlight.css
|
||||
|
|
|
@ -6,4 +6,6 @@ django-libsass>=0.7
|
|||
pillow>=9.0.0
|
||||
colorlog>=6.7.0
|
||||
favicon>=0.7.0
|
||||
libpt>=0.1.5
|
||||
markdown>=3.4.4
|
||||
Pygments>=2.16.1
|
||||
toml>=0.10
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from django.utils.translation import gettext as _
|
||||
from django.http.response import HttpResponseRedirect
|
||||
from .models import *
|
||||
|
||||
@admin.register(Category)
|
||||
|
@ -15,6 +17,7 @@ def regenerate(modeladmin, request, queryset):
|
|||
for obj in queryset:
|
||||
obj.regenerate()
|
||||
|
||||
|
||||
@admin.register(BlogPost)
|
||||
class BlogPostAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
|
@ -24,3 +27,16 @@ class BlogPostAdmin(admin.ModelAdmin):
|
|||
date_hierarchy = "date"
|
||||
ordering = ['title_de', 'title_en']
|
||||
actions = [regenerate]
|
||||
|
||||
change_list_template = "admin/blogpost.html"
|
||||
|
||||
def get_urls(self):
|
||||
urls = super().get_urls()
|
||||
my_urls = [
|
||||
path('sync/', self.sync_with_fs),
|
||||
]
|
||||
return my_urls + urls
|
||||
|
||||
def sync_with_fs(self, request):
|
||||
BlogPost.sync_with_fs()
|
||||
return HttpResponseRedirect("../")
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
date = "2023-10-02 09:59:00.127936"
|
||||
update = "2023-10-02 10:59:00.127936"
|
||||
keywords = ["bash"]
|
||||
category = "Guide"
|
||||
featured = true
|
||||
public = true
|
||||
thumbnail = "img/thumbnails/bash.png"
|
||||
|
||||
[lang.en]
|
||||
title = "bash arrays"
|
||||
subtitle = "how to work with bash arrays"
|
||||
desc = """
|
||||
bash scripting can be kind of weird.
|
||||
This guide explains how they work without any fuzz.
|
||||
"""
|
|
@ -0,0 +1,91 @@
|
|||
**NOTE**
|
||||
|
||||
This is a stolen article from [opensource.com](https://opensource.com/article/18/5/you-dont-know-bash-intro-bash-arrays)
|
||||
about bash scripting. It's a good article and I've decided to use it to test my
|
||||
markdown rendering.
|
||||
|
||||
# GERMAN VERY YES YES
|
||||
# Bash scripting
|
||||
|
||||
[TOC]
|
||||
|
||||
|
||||
## Wait, but why?
|
||||
|
||||
Writing about Bash is challenging because it's remarkably easy for an article
|
||||
to devolve into a manual that focuses on syntax oddities. Rest assured,
|
||||
however, the intent of this article is to avoid having you RTFM.
|
||||
|
||||
## A real (actually useful) example
|
||||
|
||||
To that end, let's consider a real-world scenario and how Bash can help:
|
||||
You are leading a new effort at your company to evaluate and optimize the
|
||||
runtime of your internal data pipeline. As a first step, you want to do a
|
||||
parameter sweep to evaluate how well the pipeline makes use of threads. For
|
||||
the sake of simplicity, we'll treat the pipeline as a compiled C++ black box
|
||||
where the only parameter we can tweak is the number of threads reserved for
|
||||
data processing: `./pipeline --threads 4.`
|
||||
|
||||
## The basics
|
||||
|
||||
The first thing we'll do is define an array containing the values of the
|
||||
`--threads` parameter that we want to test:
|
||||
|
||||
```bash
|
||||
allThreads=(1 2 4 8 16 32 64 128)
|
||||
```
|
||||
|
||||
In this example, all the elements are numbers, but it need not be the
|
||||
case—arrays in Bash can contain both numbers and strings, e.g., `myArray=(1
|
||||
2 "three" 4 "five")` is a valid expression. And just as with any other Bash
|
||||
variable, make sure to leave no spaces around the equal sign. Otherwise,
|
||||
Bash will treat the variable name as a program to execute, and the `=` as its
|
||||
first parameter!
|
||||
|
||||
Now that we've initialized the array, let's retrieve a few of its
|
||||
elements. You'll notice that simply doing `echo $allThreads` will output only
|
||||
the first element.
|
||||
|
||||
To understand why that is, let's take a step back and revisit how we usually
|
||||
output variables in Bash. Consider the following scenario:
|
||||
|
||||
```bash
|
||||
type="article" echo "Found 42 $type"
|
||||
```
|
||||
|
||||
Say the variable $type is given to us as a singular noun and we want to add
|
||||
an `s` at the end of our sentence. We can't simply add an s to `$type` since
|
||||
that would turn it into a different variable, `$types`. And although we could
|
||||
utilize code contortions such as `echo "Found 42 "$type"s"`, the best way
|
||||
to solve this problem is to use curly braces: `echo "Found 42 ${type}s"`,
|
||||
which allows us to tell Bash where the name of a variable starts and ends
|
||||
(interestingly, this is the same syntax used in JavaScript/ES6 to inject
|
||||
variables and expressions in template literals).
|
||||
|
||||
So as it turns out, although Bash variables don't generally require curly
|
||||
brackets, they are required for arrays. In turn, this allows us to specify
|
||||
the index to access, e.g., `echo ${allThreads[1]}` returns the second element
|
||||
of the array. Not including brackets, e.g.,`echo $allThreads[1]`, leads Bash
|
||||
to treat `[1]` as a string and output it as such.
|
||||
|
||||
Yes, Bash arrays have odd syntax, but at least they are zero-indexed, unlike
|
||||
some other languages (I'm looking at you, R).[^1]
|
||||
|
||||
## Looping through arrays
|
||||
|
||||
Although in the examples above we used integer indices in our arrays, let's
|
||||
consider two occasions when that won't be the case: First, if we wanted the
|
||||
$i-th element of the array, where $i is a variable containing the index of
|
||||
interest, we can retrieve that element using: echo ${allThreads[$i]}. Second,
|
||||
to output all the elements of an array, we replace the numeric index with
|
||||
the @ symbol (you can think of @ as standing for all):
|
||||
|
||||
```bash
|
||||
type="article"
|
||||
echo "Found 42 $type"
|
||||
```
|
||||
|
||||
*[RTFM]: Read the Fucking Manual
|
||||
*[HTML]: Hyper Text Markup Language
|
||||
|
||||
[^1]: Example Footnote
|
|
@ -0,0 +1,90 @@
|
|||
**NOTE**
|
||||
|
||||
This is a stolen article from [opensource.com](https://opensource.com/article/18/5/you-dont-know-bash-intro-bash-arrays)
|
||||
about bash scripting. It's a good article and I've decided to use it to test my
|
||||
markdown rendering.
|
||||
|
||||
# Bash scripting
|
||||
|
||||
[TOC]
|
||||
|
||||
|
||||
## Wait, but why?
|
||||
|
||||
Writing about Bash is challenging because it's remarkably easy for an article
|
||||
to devolve into a manual that focuses on syntax oddities. Rest assured,
|
||||
however, the intent of this article is to avoid having you RTFM.
|
||||
|
||||
## A real (actually useful) example
|
||||
|
||||
To that end, let's consider a real-world scenario and how Bash can help:
|
||||
You are leading a new effort at your company to evaluate and optimize the
|
||||
runtime of your internal data pipeline. As a first step, you want to do a
|
||||
parameter sweep to evaluate how well the pipeline makes use of threads. For
|
||||
the sake of simplicity, we'll treat the pipeline as a compiled C++ black box
|
||||
where the only parameter we can tweak is the number of threads reserved for
|
||||
data processing: `./pipeline --threads 4.`
|
||||
|
||||
## The basics
|
||||
|
||||
The first thing we'll do is define an array containing the values of the
|
||||
`--threads` parameter that we want to test:
|
||||
|
||||
```bash
|
||||
allThreads=(1 2 4 8 16 32 64 128)
|
||||
```
|
||||
|
||||
In this example, all the elements are numbers, but it need not be the
|
||||
case—arrays in Bash can contain both numbers and strings, e.g., `myArray=(1
|
||||
2 "three" 4 "five")` is a valid expression. And just as with any other Bash
|
||||
variable, make sure to leave no spaces around the equal sign. Otherwise,
|
||||
Bash will treat the variable name as a program to execute, and the `=` as its
|
||||
first parameter!
|
||||
|
||||
Now that we've initialized the array, let's retrieve a few of its
|
||||
elements. You'll notice that simply doing `echo $allThreads` will output only
|
||||
the first element.
|
||||
|
||||
To understand why that is, let's take a step back and revisit how we usually
|
||||
output variables in Bash. Consider the following scenario:
|
||||
|
||||
```bash
|
||||
type="article" echo "Found 42 $type"
|
||||
```
|
||||
|
||||
Say the variable $type is given to us as a singular noun and we want to add
|
||||
an `s` at the end of our sentence. We can't simply add an s to `$type` since
|
||||
that would turn it into a different variable, `$types`. And although we could
|
||||
utilize code contortions such as `echo "Found 42 "$type"s"`, the best way
|
||||
to solve this problem is to use curly braces: `echo "Found 42 ${type}s"`,
|
||||
which allows us to tell Bash where the name of a variable starts and ends
|
||||
(interestingly, this is the same syntax used in JavaScript/ES6 to inject
|
||||
variables and expressions in template literals).
|
||||
|
||||
So as it turns out, although Bash variables don't generally require curly
|
||||
brackets, they are required for arrays. In turn, this allows us to specify
|
||||
the index to access, e.g., `echo ${allThreads[1]}` returns the second element
|
||||
of the array. Not including brackets, e.g.,`echo $allThreads[1]`, leads Bash
|
||||
to treat `[1]` as a string and output it as such.
|
||||
|
||||
Yes, Bash arrays have odd syntax, but at least they are zero-indexed, unlike
|
||||
some other languages (I'm looking at you, R).[^1]
|
||||
|
||||
## Looping through arrays
|
||||
|
||||
Although in the examples above we used integer indices in our arrays, let's
|
||||
consider two occasions when that won't be the case: First, if we wanted the
|
||||
$i-th element of the array, where $i is a variable containing the index of
|
||||
interest, we can retrieve that element using: echo ${allThreads[$i]}. Second,
|
||||
to output all the elements of an array, we replace the numeric index with
|
||||
the @ symbol (you can think of @ as standing for all):
|
||||
|
||||
```bash
|
||||
type="article"
|
||||
echo "Found 42 $type"
|
||||
```
|
||||
|
||||
*[RTFM]: Read the Fucking Manual
|
||||
*[HTML]: Hyper Text Markup Language
|
||||
|
||||
[^1]: Example Footnote
|
|
@ -1,12 +1,47 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 12:03
|
||||
# Generated by Django 3.2.21 on 2023-10-02 08:14
|
||||
|
||||
from django.db import migrations
|
||||
import blog.models
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('start', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Category',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('slug', models.SlugField(unique=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Category',
|
||||
'verbose_name_plural': 'Categories',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BlogPost',
|
||||
fields=[
|
||||
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='start.searchable')),
|
||||
('body_en', models.TextField(blank=True, default='Dieser Artikel ist nicht auf deutsch verfügbar.')),
|
||||
('body_de', models.TextField(blank=True, default='This aritcle is not available in english.')),
|
||||
('thumbnail', models.ImageField(blank=True, default='img/thumbnails/default.jpg', upload_to='img/thumbnails')),
|
||||
('featured', models.BooleanField(default=False)),
|
||||
('langs', models.CharField(default="{'en': False, 'de': False}", max_length=64)),
|
||||
('slug', models.SlugField()),
|
||||
('category', models.ForeignKey(default=blog.models.Category.get_or_create_uncategorized, on_delete=django.db.models.deletion.SET_DEFAULT, to='blog.category')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'blog post',
|
||||
'verbose_name_plural': 'blog posts',
|
||||
},
|
||||
bases=('start.searchable',),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 12:03
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('start', '0002_keyword_searchable_staticsite'),
|
||||
('blog', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Category',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50)),
|
||||
('slug', models.SlugField()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='BlogPost',
|
||||
fields=[
|
||||
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='start.searchable')),
|
||||
('body', models.TextField()),
|
||||
('thumbnail', models.ImageField(blank=True, upload_to='')),
|
||||
('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='blog.category')),
|
||||
],
|
||||
bases=('start.searchable',),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 18:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('blog', '0002_blogpost_category'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='blogpost',
|
||||
name='public',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
|
@ -1,19 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 19:06
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('blog', '0003_blogpost_public'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='blogpost',
|
||||
name='slug',
|
||||
field=models.SlugField(default='test'),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 22:50
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('blog', '0004_blogpost_slug'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='blogpost',
|
||||
name='featured',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='blogpost',
|
||||
name='thumbnail',
|
||||
field=models.ImageField(blank=True, upload_to='img/thumbnails'),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 22:55
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('blog', '0005_auto_20230604_0050'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='blogpost',
|
||||
name='markdown',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -1,17 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 23:13
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('blog', '0006_blogpost_markdown'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='blogpost',
|
||||
name='public',
|
||||
),
|
||||
]
|
|
@ -1,21 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 23:56
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('blog', '0007_remove_blogpost_public'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='blogpost',
|
||||
options={'verbose_name': 'blog post', 'verbose_name_plural': 'blog posts'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='category',
|
||||
options={'verbose_name': 'Category', 'verbose_name_plural': 'Categories'},
|
||||
),
|
||||
]
|
|
@ -1,27 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-16 20:36
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('blog', '0008_auto_20230604_0156'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='blogpost',
|
||||
name='body',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='blogpost',
|
||||
name='body_de',
|
||||
field=models.TextField(default='Bis jetzt keine deutsche Übersetzung.'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='blogpost',
|
||||
name='body_en',
|
||||
field=models.TextField(default='No english translation yet.'),
|
||||
),
|
||||
]
|
|
@ -1,10 +1,34 @@
|
|||
import toml
|
||||
import ast
|
||||
import re
|
||||
import os
|
||||
import pathlib
|
||||
import markdown
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext as _
|
||||
from start.models import Searchable
|
||||
from start.models import Keyword, Searchable
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
EXTENSIONS = [
|
||||
"extra",
|
||||
"admonition",
|
||||
"codehilite",
|
||||
"meta",
|
||||
"toc"
|
||||
]
|
||||
EXTENSION_CONFIGS = {
|
||||
'codehilite': {
|
||||
'linenums': True,
|
||||
'pygments_style': 'monokai'
|
||||
},
|
||||
}
|
||||
|
||||
MD = markdown.Markdown(extensions=EXTENSIONS,
|
||||
extension_configs=EXTENSION_CONFIGS)
|
||||
|
||||
|
||||
class Category(models.Model):
|
||||
"""
|
||||
A category of blog posts
|
||||
|
@ -12,8 +36,8 @@ class Category(models.Model):
|
|||
Name not translated because it would make i18n in urls and Searchables specifically a pain.
|
||||
Maybe some day it would be cool if these were Searchable
|
||||
"""
|
||||
name= models.CharField(max_length=50)
|
||||
slug = models.SlugField()
|
||||
name = models.CharField(max_length=50)
|
||||
slug = models.SlugField(unique=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Category")
|
||||
|
@ -22,18 +46,46 @@ class Category(models.Model):
|
|||
def __str__(self):
|
||||
return f"{{<{self.__class__.__name__}>\"{self.name}\"}}"
|
||||
|
||||
@staticmethod
|
||||
def get_or_create_uncategorized():
|
||||
try:
|
||||
return Category.objects.get(slug="uncategorized")
|
||||
except Category.DoesNotExist:
|
||||
return Category.objects.create(
|
||||
slug="uncategorized", name="uncategorized")
|
||||
|
||||
|
||||
class BlogPost(Searchable):
|
||||
"""
|
||||
Should contain a blogpost
|
||||
"""
|
||||
body_en = models.TextField(default="No english translation yet.")
|
||||
body_de = models.TextField(default="Bis jetzt keine deutsche Übersetzung.")
|
||||
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
|
||||
thumbnail = models.ImageField(blank=True, upload_to="img/thumbnails")
|
||||
featured = models.BooleanField(default=False)
|
||||
markdown = models.BooleanField(default=False)
|
||||
slug = models.SlugField()
|
||||
DATA_DIR = "/app/blog/data/articles"
|
||||
DEFAULT_LANGS = {'en': False, 'de': False}
|
||||
META_TOP_KEYS = [
|
||||
"date",
|
||||
"update",
|
||||
"keywords",
|
||||
"category",
|
||||
"featured",
|
||||
"public",
|
||||
"lang"]
|
||||
META_LANG_KEYS = ["title", "subtitle", "desc"]
|
||||
|
||||
body_en = models.TextField(blank=True,
|
||||
default="""Dieser Artikel ist nicht auf deutsch verfügbar.""")
|
||||
body_de = models.TextField(blank=True,
|
||||
default="""This aritcle is not available in english.""")
|
||||
category = models.ForeignKey(
|
||||
Category, on_delete=models.SET_DEFAULT, null=False,
|
||||
default=Category.get_or_create_uncategorized)
|
||||
thumbnail = models.ImageField(
|
||||
blank=True,
|
||||
upload_to="img/thumbnails",
|
||||
default="img/thumbnails/default.jpg")
|
||||
featured = models.BooleanField(default=False)
|
||||
langs = models.CharField(
|
||||
default=DEFAULT_LANGS.__repr__(), max_length=64)
|
||||
slug = models.SlugField()
|
||||
|
||||
def regenerate(self):
|
||||
"""
|
||||
|
@ -42,9 +94,207 @@ class BlogPost(Searchable):
|
|||
Implements the abstract method of Searchable
|
||||
"""
|
||||
logger.info(f"regenerating {self.__class__.__name__} object: {self}")
|
||||
# url stuff
|
||||
self.suburl = f"/blog/{self.category.name}/{self.slug}"
|
||||
|
||||
# load from markdown
|
||||
# self.sync_file()
|
||||
|
||||
# redundand vvvv
|
||||
self.save()
|
||||
|
||||
def sync_file(self):
|
||||
"""
|
||||
generate an article fromm it's original markdown file
|
||||
"""
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.info(f"syncing article to markdown for: {self}")
|
||||
# read metadata
|
||||
try:
|
||||
fmeta = open(f"{self.DATA_DIR}/{self.slug}.toml", "r")
|
||||
except Exception as e:
|
||||
logger.error(f"could not find meta file for '{self}'")
|
||||
return
|
||||
data = toml.load(fmeta)
|
||||
langs = self.get_langs()
|
||||
for key in self.META_TOP_KEYS:
|
||||
if key not in data:
|
||||
logger.error(f"Key '{key}' missing in meta file for '{self}'")
|
||||
raise ValueError(
|
||||
f"Key '{key}' missing in meta file for '{self}'")
|
||||
for lang in self.DEFAULT_LANGS.keys():
|
||||
if lang not in data['lang']:
|
||||
langs[lang] = False
|
||||
else:
|
||||
langs[lang] = True
|
||||
self.set_langs(langs)
|
||||
for lang in data['lang']:
|
||||
for key in self.META_LANG_KEYS:
|
||||
if key not in data['lang'][lang]:
|
||||
logger.warning(
|
||||
f"Key '{key}' ('{lang}') missing in meta file for '{self}'")
|
||||
langs[lang] = False
|
||||
else:
|
||||
langs[lang] = True
|
||||
if not langs[lang]:
|
||||
# no translation for this language
|
||||
continue
|
||||
with open(f"{self.DATA_DIR}/{lang}-{self.slug}.md") as f_en:
|
||||
MD.reset()
|
||||
body: str = f_en.read()
|
||||
match lang:
|
||||
case "en":
|
||||
self.title_en = data['lang'][lang]["title"]
|
||||
self.subtitle_en = data['lang'][lang]["subtitle"]
|
||||
self.desc_en = data['lang'][lang]["desc"]
|
||||
self.body_en = MD.convert(body)
|
||||
case "de":
|
||||
self.title_de = data['lang'][lang]["title"]
|
||||
self.subtitle_de = data['lang'][lang]["subtitle"]
|
||||
self.desc_de = data['lang'][lang]["desc"]
|
||||
self.body_de = MD.convert(body)
|
||||
case _:
|
||||
logger.error(
|
||||
f"unknown language '{lang}' in meta file for '{self}'")
|
||||
self.date = data["date"]
|
||||
self.update = data["update"]
|
||||
self.featured = data["featured"]
|
||||
self.public = data["public"]
|
||||
# NOTE: thumbnail is optional
|
||||
if "thumbnail" in data:
|
||||
self.thumbnail = data["thumbnail"]
|
||||
# NOTE: category is optional
|
||||
if "category" in data:
|
||||
try:
|
||||
category: Category = Category.objects.get(
|
||||
slug=data['category'])
|
||||
except Category.DoesNotExist:
|
||||
category = Category.objects.create(
|
||||
name=data['category'], slug=data['category'])
|
||||
self.category = category
|
||||
self.save()
|
||||
for keyword in data["keywords"]:
|
||||
try:
|
||||
self.keywords.add(Keyword.objects.get(slug=keyword))
|
||||
except Keyword.DoesNotExist:
|
||||
self.keywords.create(
|
||||
slug=keyword, text_en=keyword, text_de=keyword)
|
||||
self.save()
|
||||
|
||||
def get_langs(self) -> dict[str, bool]:
|
||||
"""
|
||||
get available languages
|
||||
"""
|
||||
# SECURITY:
|
||||
# If someone could inject the langs field, literal_eval will evaluate to
|
||||
# any literal Python value. This should not be a concern.
|
||||
# If we would use a regular eval here, an attacker who controls one of
|
||||
# the `langs` of a BlogPost could run arbitrary Python code.
|
||||
try:
|
||||
# literal_eval is safe because it only parses literals, not any kind
|
||||
# of python expression. If the given str is not a valid literal,
|
||||
# ValueError will be raised
|
||||
langs = ast.literal_eval(str(self.langs))
|
||||
return langs
|
||||
except ValueError as e:
|
||||
logger.error(
|
||||
f"could not safely evaluate 'langs' for '{self}': {e}")
|
||||
raise e
|
||||
|
||||
def set_langs(self, langs: dict[str, bool]):
|
||||
"""
|
||||
set available languages
|
||||
"""
|
||||
self.langs = langs.__repr__()
|
||||
|
||||
@ classmethod
|
||||
def sync_with_fs(cls):
|
||||
"""
|
||||
Sync all Blog Posts with the filesystem.
|
||||
|
||||
Caution: Will delete all Blog Posts
|
||||
"""
|
||||
# logger.name = logger.name + ".sync_with_fs"
|
||||
|
||||
# delete all existing objects
|
||||
BlogPost.objects.all().delete()
|
||||
|
||||
# check if the DATA_DIR is OK
|
||||
data_dir = pathlib.Path(cls.DATA_DIR)
|
||||
if not data_dir.exists():
|
||||
logger.error(f"'{cls.DATA_DIR} does not exist'")
|
||||
if not data_dir.is_dir():
|
||||
logger.error(f"'{cls.DATA_DIR} is not a directory'")
|
||||
|
||||
files = [f for f in os.listdir(data_dir) if (
|
||||
data_dir.joinpath(f)).is_file()]
|
||||
logger.debug(f"discovered files: {files}")
|
||||
|
||||
# finding lang and title
|
||||
regex = r"^(en|de)-(.*)\.md"
|
||||
# TODO: only find toml files
|
||||
|
||||
# filepath, language codes, slug
|
||||
files = [[f, cls.DEFAULT_LANGS, ""] for f in files]
|
||||
for file in files:
|
||||
# parse file name
|
||||
try:
|
||||
matches = re.match(regex, file[0])
|
||||
if matches is None:
|
||||
logger.warning(
|
||||
f"Data file '{file[0]}' does not fit to the filename\
|
||||
regex")
|
||||
files.remove(file)
|
||||
else:
|
||||
current_lang = matches.group(1)
|
||||
file[1][current_lang] = True
|
||||
file[2] = matches.group(2)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
files.remove(file)
|
||||
|
||||
# PERF:
|
||||
# Optimize for single loop, should be doable and better design
|
||||
|
||||
# collapse diffrent versions
|
||||
for file in files:
|
||||
try:
|
||||
if [_f[2] for _f in files].count(file[2]) >= 2:
|
||||
logger.debug(f"multiple versions of '{file[2]}'")
|
||||
versions = [_f for _f in files if _f[2] == file[2]]
|
||||
lang: dict[str, bool] = file[1]
|
||||
for version in versions:
|
||||
for key in version[1]:
|
||||
lang[key] |= version[1][key]
|
||||
else:
|
||||
# only a single version of this file
|
||||
continue
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Could not combine BlogPosts for '{file[0]}': {e}")
|
||||
|
||||
# TODO: not needed when relying on toml files
|
||||
try:
|
||||
# deduplicate
|
||||
_files = []
|
||||
for f in [[_f[1], _f[2]]
|
||||
for _f in files]: # dont care about fname
|
||||
if f not in _files:
|
||||
_files.append(f)
|
||||
files = _files
|
||||
logger.debug(f"to save: {files}")
|
||||
except Exception as e:
|
||||
logger.error(f"Could not dedup BlogPosts: {e}")
|
||||
|
||||
for file in files:
|
||||
try:
|
||||
obj = BlogPost(langs=file[0], slug=file[1])
|
||||
obj.sync_file()
|
||||
obj.regenerate()
|
||||
obj.save()
|
||||
except Exception as e:
|
||||
logger.error(f"Could not create BlogPost for '{file[1]}': {e}")
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("blog post")
|
||||
verbose_name_plural = _("blog posts")
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{% extends 'admin/change_list.html' %} {% block object-tools %}
|
||||
<form action="sync" method="POST">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="button" style="padding: 4px">Sync with FS</button>
|
||||
</form>
|
||||
{{ block.super }} {% endblock %}
|
|
@ -1,40 +1,58 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% load helper_tags %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
{% block languagecode %}{{ LANGUAGE_CODE }}{% endblock languagecode %}
|
||||
{% block title %}{% translate "cscherr.de" %} - {% translate "Blog" %}{% endblock title %}
|
||||
{% block languagecode %}
|
||||
{{ LANGUAGE_CODE }}
|
||||
{% endblock languagecode %}
|
||||
{% block title %}
|
||||
{% translate "cscherr.de" %} - {% translate "Blog" %}
|
||||
{% endblock title %}
|
||||
{% block nav %}
|
||||
{% include 'nav.html' %}
|
||||
{% include 'nav.html' %}
|
||||
{% endblock nav %}
|
||||
{% block headscripts %}
|
||||
<script type="text/javascript" id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3.0.0/es5/tex-mml-chtml.js"></script>
|
||||
<script type="text/javascript"
|
||||
id="MathJax-script"
|
||||
async
|
||||
src="https://cdn.jsdelivr.net/npm/mathjax@3.0.0/es5/tex-mml-chtml.js"></script>
|
||||
{% endblock headscripts %}
|
||||
{% block main %}
|
||||
<div class="container-xl">
|
||||
<div class="container-xl">
|
||||
<article>
|
||||
<div class="jumbotron my-5">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
{% if LANGUAGE_CODE == "de" %}
|
||||
<h1 class="">{{ post.title_de }}<br>
|
||||
<small class="fs-4">{{ post.subtitle_de }}</small></h1><br>
|
||||
{% elif LANGUAGE_CODE == "en" %}
|
||||
<h1 class="">{{ post.title_en }}<br>
|
||||
<small class="fs-4">{{ post.subtitle_en }}</small></h1><br>
|
||||
{% else %}
|
||||
<h1 class="">{{ post.title_en }}<br>
|
||||
<small class="fs-4">{{ post.subtitle_en }}</small></h1><br>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-center text-center">
|
||||
<div class="col">
|
||||
<picture>
|
||||
<img src="{{ post.thumbnail.url }}" alt="thumbnail" class="img-fluid">
|
||||
</picture>
|
||||
</div>
|
||||
<div class="col px-3">
|
||||
<div class="col">
|
||||
<div class="row py-5">
|
||||
{% if LANGUAGE_CODE == "de" %}
|
||||
<h1 class="">
|
||||
{{ post.title_de }}
|
||||
<br>
|
||||
<small class="fs-4">{{ post.subtitle_de }}</small>
|
||||
</h1>
|
||||
<br>
|
||||
{% elif LANGUAGE_CODE == "en" %}
|
||||
<h1 class="">
|
||||
{{ post.title_en }}
|
||||
<br>
|
||||
<small class="fs-4">{{ post.subtitle_en }}</small>
|
||||
</h1>
|
||||
<br>
|
||||
{% else %}
|
||||
<h1 class="">
|
||||
{{ post.title_en }}
|
||||
<br>
|
||||
<small class="fs-4">{{ post.subtitle_en }}</small>
|
||||
</h1>
|
||||
<br>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="row py-5">
|
||||
{% if LANGUAGE_CODE == "de" %}
|
||||
<p class="lead">{{ post.desc_de }}</p>
|
||||
{% elif LANGUAGE_CODE == "en" %}
|
||||
|
@ -43,11 +61,10 @@
|
|||
<p class="lead">{{ post.desc_en }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col">
|
||||
<p>{{ post.date }}</p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p>{{ post.category.name }}</p>
|
||||
<div class="row py-5">
|
||||
<p>
|
||||
<b>{{ post.category.name }}<b>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -63,7 +80,17 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row text-center">
|
||||
<div class="col">
|
||||
{% format_time post.date as date %}
|
||||
<p>{% trans "published" %}: {{ date }}</p>
|
||||
</div>
|
||||
<div class="col">
|
||||
{% format_time post.update as update %}
|
||||
<p>{% trans "updated" %}: {{ update }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
{% include 'blog/featured.html' %}
|
||||
{% endblock main %}
|
||||
</div>
|
||||
{% include 'blog/featured.html' %}
|
||||
{% endblock main %}
|
||||
|
|
|
@ -1,27 +1,40 @@
|
|||
{% load i18n %}
|
||||
{% load helper_tags %}
|
||||
{% get_current_language as LANGUAGE_CODE %}
|
||||
<div class="container-lg mt-5">
|
||||
<h4 class="">{% trans "Featured" %}</h4>
|
||||
<div class="row row-cols-1 row-cols-md-5 my-4">
|
||||
{% for post in featured_posts %}
|
||||
<div class="card col m-2 p-0">
|
||||
<a class="text-reset link-offset-2 link-underline link-underline-opacity-0" href=" {% url 'blog:post' post.category.slug post.slug %}">
|
||||
<img src="{{ post.thumbnail.url }}" class="card-img-top img-fluid" style="max-height: 150px;" alt="thumbnail">
|
||||
<div class="card-body" style="height: 100px;">
|
||||
<a class="text-reset link-offset-2 link-underline link-underline-opacity-0"
|
||||
href=" {% url 'blog:post' post.category.slug post.slug %}">
|
||||
<img src="{{ post.thumbnail.url }}"
|
||||
class="card-img-top img-fluid mx-auto d-block"
|
||||
style="max-height: 150px; width: auto; padding-top: 8px;"
|
||||
alt="thumbnail" />
|
||||
<div class="card-body" style="height: 100px">
|
||||
{% if LANGUAGE_CODE == "de" %}
|
||||
<h5 class="card-title">{{ post.title_de }}<small class="text-body-secondary">{{ post.subtitle }}</small></h5>
|
||||
<h5 class="card-title">
|
||||
{{ post.title_de }}<small class="text-body-secondary">{{ post.subtitle }}</small>
|
||||
</h5>
|
||||
<p class="card-text">{{ post.desc_de }}</p>
|
||||
{% elif LANGUAGE_CODE == "en" %}
|
||||
<h5 class="card-title">{{ post.title_en }}<small class="text-body-secondary">{{ post.subtitle }}</small></h5>
|
||||
<h5 class="card-title">
|
||||
{{ post.title_en }}<small class="text-body-secondary">{{ post.subtitle }}</small>
|
||||
</h5>
|
||||
<p class="card-text">{{ post.desc_en }}</p>
|
||||
{% else %}
|
||||
<h5 class="card-title">{{ post.title_en }}<small class="text-body-secondary">{{ post.subtitle }}</small></h5>
|
||||
<h5 class="card-title">
|
||||
{{ post.title_en }}<small class="text-body-secondary">{{ post.subtitle }}</small>
|
||||
</h5>
|
||||
<p class="card-text">{{ post.desc_en }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="container pt-5">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">{% translate "category" %}: <b>{{ post.category.name }}</b></li>
|
||||
<li class="list-group-item">
|
||||
{% translate "category" %}: <b>{{ post.category.name }}</b>
|
||||
</li>
|
||||
{% for keyword in post.keywords.all %}
|
||||
{% if LANGUAGE_CODE == "de" %}
|
||||
<li class="list-group-item">{{ keyword.text_de }}</li>
|
||||
|
@ -33,6 +46,12 @@
|
|||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="container p-1 text-center" style="border-top: solid">
|
||||
<li class="list-group-item">
|
||||
{% format_time post.date "%F" as date %}
|
||||
{% trans "published" %}: {{ date }}
|
||||
</li>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
|
|
@ -11,6 +11,8 @@ https://docs.djangoproject.com/en/3.2/ref/settings/
|
|||
"""
|
||||
|
||||
# for getting envvars
|
||||
import logging
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
import os
|
||||
|
||||
# default django
|
||||
|
@ -100,7 +102,6 @@ DATABASES = {
|
|||
}
|
||||
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
|
||||
|
||||
|
@ -123,7 +124,6 @@ AUTH_PASSWORD_VALIDATORS = [
|
|||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/3.2/topics/i18n/
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
LANGUAGES = [
|
||||
("de", _("German")),
|
||||
|
@ -158,7 +158,7 @@ STATICFILES_FINDERS = [
|
|||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
]
|
||||
]
|
||||
|
||||
COMPRESS_PRECOMPILERS = (
|
||||
('text/x-scss', 'django_libsass.SassCompiler'),
|
||||
|
@ -173,7 +173,6 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|||
|
||||
# Logging configs
|
||||
|
||||
import logging
|
||||
|
||||
myServerFormatter = ServerFormatter
|
||||
myServerFormatter.default_time_format = "%Y-%M-%d %H:%M:%S"
|
||||
|
@ -294,7 +293,7 @@ LOGGING = {
|
|||
# Media stuff
|
||||
# this is where user uploaded files will go.
|
||||
# TODO change this for prod
|
||||
#MEDIA_ROOT = "/home/plex/Documents/code/python/gawa/media"
|
||||
# MEDIA_ROOT = "/home/plex/Documents/code/python/gawa/media"
|
||||
MEDIA_ROOT = "/app/media"
|
||||
MEDIA_URL = "/media/"
|
||||
FILE_UPLOAD_TEMP_DIR = "/tmp/gawa/upload"
|
||||
# FILE_UPLOAD_TEMP_DIR = "/tmp/gawa/upload"
|
||||
|
|
|
@ -14,14 +14,14 @@ Including another URLconf
|
|||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.conf.urls.i18n import i18n_patterns
|
||||
from django.conf.urls import url
|
||||
from django.contrib import admin
|
||||
from django.urls import include, re_path
|
||||
from django.urls import include, path
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
re_path(r'^i18n/', include('django.conf.urls.i18n')),
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
urlpatterns += i18n_patterns(
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 62 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -10,6 +10,7 @@ def regenerate(modeladmin, request, queryset):
|
|||
for obj in queryset:
|
||||
obj.regenerate()
|
||||
|
||||
|
||||
@admin.register(Keyword)
|
||||
class KeywordAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
|
@ -17,21 +18,25 @@ class KeywordAdmin(admin.ModelAdmin):
|
|||
"""
|
||||
list_display = ["text_en", "text_de"]
|
||||
|
||||
|
||||
@admin.register(StaticSite)
|
||||
class StaticSiteAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Admin Interface for StaticSite
|
||||
"""
|
||||
list_display = ["title_en", "subtitle_en", "title_de", "subtitle_de", "suburl"]
|
||||
list_display = ["title_en", "subtitle_en",
|
||||
"title_de", "subtitle_de", "suburl"]
|
||||
ordering = ['title_de', 'title_en']
|
||||
actions = [regenerate]
|
||||
|
||||
|
||||
@admin.register(Searchable)
|
||||
class SearchableAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Abstract Admin Interface for all Searchables
|
||||
"""
|
||||
list_display = ["title_en", "subtitle_en", "title_de", "subtitle_de", "suburl"]
|
||||
list_display = ["title_en", "subtitle_en",
|
||||
"title_de", "subtitle_de", "suburl"]
|
||||
ordering = ['title_de', 'title_en']
|
||||
actions = [regenerate]
|
||||
|
||||
|
@ -41,6 +46,7 @@ class LinkAdmin(admin.ModelAdmin):
|
|||
"""
|
||||
Admin Interface for Links
|
||||
"""
|
||||
list_display = ["title_en", "title_de", "url", "suburl", "favicon", "status", "personal"]
|
||||
list_display = ["title_en", "title_de", "url",
|
||||
"suburl", "favicon", "status", "personal"]
|
||||
ordering = ['status', 'title_de', 'title_en']
|
||||
actions = [regenerate]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class StartConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'start'
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
|
||||
class MainSearchForm(forms.Form):
|
||||
search = forms.CharField(
|
||||
max_length=100,
|
||||
|
|
|
@ -15,7 +15,8 @@ class LangBasedOnUrlMiddleware(MiddlewareMixin):
|
|||
def process_request(request):
|
||||
|
||||
if hasattr(request, 'session'):
|
||||
active_session_lang = request.session.get(translation.LANGUAGE_SESSION_KEY)
|
||||
active_session_lang = request.session.get(
|
||||
translation.LANGUAGE_SESSION_KEY)
|
||||
|
||||
if active_session_lang == request.LANGUAGE_CODE:
|
||||
return
|
||||
|
|
|
@ -1,12 +1,75 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 12:03
|
||||
# Generated by Django 3.2.21 on 2023-10-02 08:14
|
||||
|
||||
from django.db import migrations
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Keyword',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('slug', models.SlugField(unique=True)),
|
||||
('text_de', models.CharField(max_length=40)),
|
||||
('text_en', models.CharField(max_length=40)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Keyword',
|
||||
'verbose_name_plural': 'keywords',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Searchable',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title_de', models.CharField(default='Nicht übersetzt', max_length=50)),
|
||||
('title_en', models.CharField(default='Not translated', max_length=50)),
|
||||
('subtitle_de', models.CharField(blank=True, max_length=50)),
|
||||
('subtitle_en', models.CharField(blank=True, max_length=50)),
|
||||
('desc_de', models.TextField(blank=True, default='Keine Beschreibung', max_length=250)),
|
||||
('desc_en', models.TextField(blank=True, default='no description', max_length=250)),
|
||||
('date', models.DateTimeField(blank=True, null=True)),
|
||||
('update', models.DateTimeField(blank=True, null=True)),
|
||||
('suburl', models.CharField(blank=True, max_length=200, null=True)),
|
||||
('public', models.BooleanField(default=False)),
|
||||
('keywords', models.ManyToManyField(blank=True, to='start.Keyword')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Searchable',
|
||||
'verbose_name_plural': 'Searchables',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Link',
|
||||
fields=[
|
||||
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='start.searchable')),
|
||||
('url', models.URLField(primary_key=True, serialize=False, unique=True)),
|
||||
('favicon', models.ImageField(blank=True, null=True, upload_to='img/links/favicons')),
|
||||
('status', models.BooleanField(default=False)),
|
||||
('personal', models.BooleanField(default=False)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Link',
|
||||
'verbose_name_plural': 'Links',
|
||||
},
|
||||
bases=('start.searchable',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StaticSite',
|
||||
fields=[
|
||||
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='start.searchable')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'static site',
|
||||
'verbose_name_plural': 'static sites',
|
||||
},
|
||||
bases=('start.searchable',),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 12:03
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('start', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Keyword',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('text_de', models.CharField(max_length=40)),
|
||||
('text_en', models.CharField(max_length=40)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Searchable',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title_de', models.CharField(default='Titel DE', max_length=50)),
|
||||
('title_en', models.CharField(default='title en', max_length=50)),
|
||||
('subtitle_de', models.CharField(blank=True, max_length=50)),
|
||||
('subtitle_en', models.CharField(blank=True, max_length=50)),
|
||||
('desc_de', models.CharField(default='Beschreibung DE', max_length=250, unique=True)),
|
||||
('desc_en', models.CharField(default='Description EN', max_length=250, unique=True)),
|
||||
('date', models.DateField(blank=True, null=True)),
|
||||
('suburl', models.CharField(blank=True, max_length=200, null=True)),
|
||||
('keywords', models.ManyToManyField(to='start.Keyword')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='StaticSite',
|
||||
fields=[
|
||||
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='start.searchable')),
|
||||
],
|
||||
bases=('start.searchable',),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-03 23:13
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0002_keyword_searchable_staticsite'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='searchable',
|
||||
name='public',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
|
@ -1,35 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-04 21:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0003_searchable_public'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='keyword',
|
||||
options={'verbose_name': 'Keyword', 'verbose_name_plural': 'keywords'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='searchable',
|
||||
options={'verbose_name': 'Searchable', 'verbose_name_plural': 'Searchables'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='staticsite',
|
||||
options={'verbose_name': 'static site', 'verbose_name_plural': 'static sites'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='searchable',
|
||||
name='desc_de',
|
||||
field=models.CharField(default='Beschreibung DE', max_length=250),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='searchable',
|
||||
name='desc_en',
|
||||
field=models.CharField(default='Description EN', max_length=250),
|
||||
),
|
||||
]
|
|
@ -1,26 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-05 16:15
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0004_auto_20230604_2312'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Link',
|
||||
fields=[
|
||||
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='start.searchable')),
|
||||
('url', models.URLField(primary_key=True, serialize=False, unique=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Link',
|
||||
'verbose_name_plural': 'Links',
|
||||
},
|
||||
bases=('start.searchable',),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-05 16:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0005_link'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='searchable',
|
||||
name='title_en',
|
||||
field=models.CharField(default='title EN', max_length=50),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-05 17:48
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0006_alter_searchable_title_en'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='link',
|
||||
name='favicon',
|
||||
field=models.ImageField(blank=True, upload_to='img/links/favicons'),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-05 20:55
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0007_link_favicon'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='link',
|
||||
name='status',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-06-05 23:01
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0008_link_status'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='link',
|
||||
name='favicon',
|
||||
field=models.ImageField(blank=True, null=True, upload_to='img/links/favicons'),
|
||||
),
|
||||
]
|
|
@ -1,18 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-07-15 12:29
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0009_alter_link_favicon'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='link',
|
||||
name='personal',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 3.2.19 on 2023-07-15 12:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('start', '0010_link_personal'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='searchable',
|
||||
name='desc_de',
|
||||
field=models.TextField(default='Beschreibung DE', max_length=250),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='searchable',
|
||||
name='desc_en',
|
||||
field=models.TextField(default='Description EN', max_length=250),
|
||||
),
|
||||
]
|
|
@ -1,3 +1,6 @@
|
|||
import random
|
||||
import favicon
|
||||
import requests
|
||||
from django.db import models
|
||||
from django.db.models.options import override
|
||||
from django.utils.translation import gettext as _
|
||||
|
@ -8,24 +11,23 @@ from django.conf import settings
|
|||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
import requests
|
||||
import favicon
|
||||
import random
|
||||
|
||||
class Keyword(models.Model):
|
||||
"""
|
||||
this is the model that should contain searchable keywords
|
||||
"""
|
||||
slug = models.SlugField(unique=True)
|
||||
text_de = models.CharField(max_length=40)
|
||||
text_en = models.CharField(max_length=40)
|
||||
|
||||
def __str__(self):
|
||||
return f"{{<{self.__class__.__name__}>\"{self.text_en}\"}}"
|
||||
return f"{{<{self.__class__.__name__}>\"{self.slug}\"}}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Keyword")
|
||||
verbose_name_plural = _("keywords")
|
||||
|
||||
|
||||
class Searchable(models.Model):
|
||||
"""
|
||||
Abstract class for any model that should be searchable.
|
||||
|
@ -33,17 +35,19 @@ class Searchable(models.Model):
|
|||
|
||||
This class is not a real abstract class, I need to query it in the main search, so thats impossible
|
||||
"""
|
||||
title_de = models.CharField(max_length=50, default="Titel DE")
|
||||
title_en = models.CharField(max_length=50, default="title EN")
|
||||
title_de = models.CharField(max_length=50, default="Nicht übersetzt")
|
||||
title_en = models.CharField(max_length=50, default="Not translated")
|
||||
subtitle_de = models.CharField(max_length=50, blank=True)
|
||||
subtitle_en = models.CharField(max_length=50, blank=True)
|
||||
desc_de = models.TextField(max_length=250, unique=False, default="Beschreibung DE")
|
||||
desc_en = models.TextField(max_length=250, unique=False, default="Description EN")
|
||||
# may be empty/blank for some entries
|
||||
date = models.DateField(blank=True, null=True)
|
||||
keywords = models.ManyToManyField(Keyword)
|
||||
desc_de = models.TextField(
|
||||
blank=True, max_length=250, unique=False, default="Keine Beschreibung")
|
||||
desc_en = models.TextField(
|
||||
blank=True, max_length=250, unique=False, default="no description")
|
||||
date = models.DateTimeField(blank=True, null=True)
|
||||
update = models.DateTimeField(blank=True, null=True)
|
||||
keywords = models.ManyToManyField(Keyword, blank=True)
|
||||
suburl = models.CharField(max_length=200, blank=True, null=True)
|
||||
public = models.BooleanField(default=True)
|
||||
public = models.BooleanField(default=False)
|
||||
|
||||
@classmethod
|
||||
def regenerate_all_entries(cls):
|
||||
|
@ -55,18 +59,20 @@ class Searchable(models.Model):
|
|||
obj.regenerate()
|
||||
|
||||
def __str__(self):
|
||||
return f"{{<{self.__class__.__name__}>\"{self.title_en}\"}}"
|
||||
return f"{{<{self.__class__.__name__}>\"{self.slug}\"}}"
|
||||
|
||||
def regenerate(self):
|
||||
"""
|
||||
regenerate a object
|
||||
"""
|
||||
raise NotImplementedError(f"{self.__class__.__name__} does not implement regenerate")
|
||||
raise NotImplementedError(
|
||||
f"{self.__class__.__name__} does not implement regenerate")
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Searchable")
|
||||
verbose_name_plural = _("Searchables")
|
||||
|
||||
|
||||
class StaticSite(Searchable):
|
||||
"""
|
||||
This model represents any static site, such as start:index,
|
||||
|
@ -82,13 +88,14 @@ class StaticSite(Searchable):
|
|||
"""
|
||||
logger.info(f"regenerating {self.__class__.__name__} object: {self}")
|
||||
logger.warning(f"{self.__class__.__name__} cannot regenerate.")
|
||||
#self.save()
|
||||
# self.save()
|
||||
pass
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("static site")
|
||||
verbose_name_plural = _("static sites")
|
||||
|
||||
|
||||
class Link(Searchable):
|
||||
"""
|
||||
contains all my interesting links
|
||||
|
@ -121,11 +128,13 @@ class Link(Searchable):
|
|||
icons = favicon.get(self.url, timeout=2)
|
||||
except (ConnectionError) as ce:
|
||||
# just keep whatever was stored if we cant get a new favicon
|
||||
logger.warn(f"unable to download favicon for {self}: {ce.with_traceback(None)}")
|
||||
logger.warn(
|
||||
f"unable to download favicon for {self}: {ce.with_traceback(None)}")
|
||||
self.status = False
|
||||
|
||||
except Exception as e:
|
||||
logger.warn(f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
|
||||
logger.warn(
|
||||
f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
|
||||
self.status = False
|
||||
|
||||
else:
|
||||
|
@ -146,7 +155,8 @@ class Link(Searchable):
|
|||
self.favicon = None
|
||||
|
||||
except Exception as e:
|
||||
logger.warn(f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
|
||||
logger.warn(
|
||||
f"Unexpected Exception while downloading {self}: {e.with_traceback(None)}")
|
||||
self.favicon = None
|
||||
|
||||
self.save()
|
||||
|
|
|
@ -11,13 +11,9 @@
|
|||
{% compress css %}
|
||||
<link type="text/x-scss" href="/static/bs5/scss/bootstrap.scss" rel="stylesheet" media="screen">
|
||||
<link rel="stylesheet" href="/static/bsi1/font/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="/static/codehighlight.css">
|
||||
<link rel="stylesheet" href="/static/custom.css">
|
||||
{% endcompress %}
|
||||
<script>
|
||||
const setTheme = theme => {
|
||||
document.documentElement.setAttribute('data-bs-theme', theme)
|
||||
}
|
||||
setTheme(localStorage.getItem('theme'));
|
||||
</script>
|
||||
{% block headscripts %}
|
||||
{% endblock headscripts %}
|
||||
</head>
|
||||
|
@ -106,6 +102,7 @@
|
|||
</div>
|
||||
</footer>
|
||||
{% compress js %}
|
||||
<script src="/static/custom.js"></script>
|
||||
<script src="/static/bs5/dist/js/bootstrap.bundle.min.js"></script>
|
||||
{% endcompress %}
|
||||
</body>
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
<button type="button" class="btn btn-dark" id="toggleThemeButton">
|
||||
<i id="toggleThemeIcon" class="bi bi-sun"></i>
|
||||
</button>
|
||||
<script>
|
||||
'use strict'
|
||||
let i = document.getElementById("toggleThemeIcon").className = "bi bi-sun";
|
||||
const storedTheme = localStorage.getItem('theme');
|
||||
if (storedTheme == null) {
|
||||
localStorage.setItem("theme", "light");
|
||||
document.getElementById("toggleThemeIcon").className = "bi bi-sun-fill";
|
||||
setTheme("light");
|
||||
}
|
||||
else if (storedTheme == "dark") {
|
||||
localStorage.setItem("theme", "dark");
|
||||
document.getElementById("toggleThemeIcon").className = "bi bi-sun";
|
||||
setTheme("dark");
|
||||
}
|
||||
else if (storedTheme == "light") {
|
||||
localStorage.setItem("theme", "light");
|
||||
document.getElementById("toggleThemeIcon").className = "bi bi-sun-fill";
|
||||
setTheme("light");
|
||||
}
|
||||
</script>
|
|
@ -60,31 +60,12 @@
|
|||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
{% include 'dark_light_switch.html' %}
|
||||
<button type="button" class="btn btn-dark" id="toggleThemeButton">
|
||||
<i id="toggleThemeIcon" class="bi bi-sun"></i>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
{% include 'main_search_form.html' %}
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
'use strict'
|
||||
document.getElementById("toggleThemeButton").onclick = function () {
|
||||
const storedTheme = localStorage.getItem('theme');
|
||||
if (storedTheme == null) {
|
||||
localStorage.setItem("theme", "dark");
|
||||
document.getElementById("toggleThemeIcon").className = "bi bi-sun";
|
||||
setTheme("dark");
|
||||
}
|
||||
else if (storedTheme == "dark") {
|
||||
localStorage.setItem("theme", "light");
|
||||
document.getElementById("toggleThemeIcon").className = "bi bi-sun-fill";
|
||||
setTheme("light");
|
||||
}
|
||||
else if (storedTheme == "light") {
|
||||
localStorage.setItem("theme", "dark");
|
||||
document.getElementById("toggleThemeIcon").className = "bi bi-sun";
|
||||
setTheme("dark");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</nav>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.template import Library
|
||||
from django.urls import resolve, reverse
|
||||
from django.utils.translation import activate, get_language
|
||||
from datetime import datetime
|
||||
|
||||
import re
|
||||
|
||||
|
@ -9,6 +10,9 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
register = Library()
|
||||
|
||||
@register.simple_tag
|
||||
def format_time(timestamp: datetime, format: str = "%F %H:%M:%S %Z") -> str:
|
||||
return timestamp.strftime(format)
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def change_lang(context, lang="de", *args, **kwargs):
|
||||
|
@ -19,7 +23,9 @@ def change_lang(context, lang="de", *args, **kwargs):
|
|||
shamelessly stolen from stackoverflow:
|
||||
https://stackoverflow.com/a/41147772
|
||||
"""
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
path = context['request'].get_raw_uri()
|
||||
url = path
|
||||
try:
|
||||
|
@ -33,4 +39,5 @@ def change_lang(context, lang="de", *args, **kwargs):
|
|||
finally:
|
||||
activate(lang)
|
||||
return "%s" % url
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"passing error chain: {e}")
|
||||
|
|
|
@ -9,5 +9,6 @@ urlpatterns = [
|
|||
path("legal/", views.LegalInfo.as_view(), name="legal"),
|
||||
path("links/", views.Links.as_view(), name="links"),
|
||||
path("professional/", views.LegalInfo.as_view(), name="professional"),
|
||||
path('language/activate/<language_code>/', views.ActivateLanguage.as_view(), name='activate_language'),
|
||||
path('language/activate/<language_code>/',
|
||||
views.ActivateLanguage.as_view(), name='activate_language'),
|
||||
]
|
||||
|
|
|
@ -18,6 +18,7 @@ from abc import ABC
|
|||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SearchableView(View, ABC):
|
||||
"""
|
||||
This abstract view implements some traits of views that should show up
|
||||
|
@ -40,6 +41,7 @@ class Index(TemplateView, SearchableView):
|
|||
|
||||
template_name: str = "start/index.html"
|
||||
|
||||
|
||||
class Professional(TemplateView, SearchableView):
|
||||
"""
|
||||
Professional informations that might interest a professional employer
|
||||
|
@ -47,6 +49,7 @@ class Professional(TemplateView, SearchableView):
|
|||
# TODO
|
||||
template_name: str = "start/legalinfo.html"
|
||||
|
||||
|
||||
class LegalInfo(TemplateView, SearchableView):
|
||||
"""
|
||||
Legal info that the german authorities want.
|
||||
|
@ -54,6 +57,7 @@ class LegalInfo(TemplateView, SearchableView):
|
|||
# TODO
|
||||
template_name: str = "start/legalinfo.html"
|
||||
|
||||
|
||||
class ActivateLanguage(View):
|
||||
"""
|
||||
Set the language to whatever
|
||||
|
@ -68,6 +72,7 @@ class ActivateLanguage(View):
|
|||
request.session[translation.LANGUAGE_SESSION_KEY] = self.language_code
|
||||
return redirect(self.redirect_to)
|
||||
|
||||
|
||||
class MainSearch(ListView):
|
||||
"""
|
||||
Search for anything.
|
||||
|
@ -94,6 +99,7 @@ class MainSearch(ListView):
|
|||
return render(request, "errors/bad_request.html")
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class Links(ListView):
|
||||
"""
|
||||
This View contains links to various interesting sites.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
docker compose exec main python /app/manage.py makemigrations
|
||||
docker compose exec main python /app/manage.py migrate
|
|
@ -0,0 +1,10 @@
|
|||
Django>=3.0,<4.0
|
||||
psycopg2>=2.8
|
||||
mysqlclient>=1.4.3
|
||||
django_compressor>=2.2
|
||||
django-libsass>=0.7
|
||||
pillow>=9.0.0
|
||||
colorlog>=6.7.0
|
||||
favicon>=0.7.0
|
||||
markdown>=3.4.4
|
||||
Pygments>=2.16.1
|
Loading…
Reference in New Issue