Skip to content
This repository was archived by the owner on Mar 27, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ venv/
env/
ENV/
.env/
.env

# Testing
.coverage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ I’m finally focusing on what matters: **writing**.

![obsidian blog](https://miro.medium.com/v2/resize:fit:1400/1*Hfi8Lapum4YdQoFAzAiU2A.png)

My new ugly website. Source: [https://frodigo.com/Garage](https://frodigo.com/Garage)
My new ugly website. Source: [https://frodigo.com](https://frodigo.com)

So now I’m writing — and I’ve made a deal with myself: no replatforming for the next year.

Expand Down
2 changes: 0 additions & 2 deletions Blog/2025/Why teaching kids how to program is not easy.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,5 @@ Teaching programming to kids requires luck, considerable strength, and abundant

And may your child become an even better programmer than you!

If you are interested in learning how to teach kids programming, please check out my learning roadmap: [https://frodigo.com/Garage/Programming+for+Kids](https://frodigo.com/Garage/Programming+for+Kids)

---
*Published 07/04/2025* #blog #ProgrammingFundamentals #Python #BestPractices #ConceptExplanation #CaseStudy #Beginner
1 change: 0 additions & 1 deletion Now/History/1. 25-03-2025.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ My son has repeatedly asked me what I do in my work, so I showed him some code a

Connected resources:

- [Programming for Kids](Programming%20for%20Kids.md)
- [Why teaching kids how to program is not easy](Why%20teaching%20kids%20how%20to%20program%20is%20not%20easy.md)

---
Expand Down
3 changes: 3 additions & 0 deletions Projects/Testtrack/M1 - Django Learning/mysite/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
EMAIL_HOST_USER=
EMAIL_HOST_PASSWORD=
DEFAULT_FROM_EMAIL=
1 change: 1 addition & 0 deletions Projects/Testtrack/M1 - Django Learning/mysite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
9 changes: 8 additions & 1 deletion Projects/Testtrack/M1 - Django Learning/mysite/blog/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.contrib import admin
from .models import Post
from .models import Post, Comment


@admin.register(Post)
Expand All @@ -12,3 +12,10 @@ class PostAdmin(admin.ModelAdmin):
date_hierarchy = 'published_at'
ordering = ('status', 'published_at')
show_facets = admin.ShowFacets.ALWAYS


@admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display = ('name', 'email', 'post', 'created_at', 'active')
list_filter = ('active', 'created_at', 'updated_at')
search_fields = ('name', 'email', 'body')
23 changes: 23 additions & 0 deletions Projects/Testtrack/M1 - Django Learning/mysite/blog/feeds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import markdown
from django.contrib.syndication.views import Feed
from django.template.defaultfilters import truncatewords_html
from django.urls import reverse_lazy
from .models import Post


class LatestPostsFeed(Feed):
title = "My Blog"
link = reverse_lazy('blog:post_list')
description = "Updates on the latest blog posts."

def items(self):
return Post.published.all()[:5]

def item_title(self, item):
return item.title

def item_description(self, item):
return truncatewords_html(markdown.markdown(item.body), 30)

def item_pubdate(self, item):
return item.published_at
18 changes: 18 additions & 0 deletions Projects/Testtrack/M1 - Django Learning/mysite/blog/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django import forms
from .models import Comment


class EmailPostForm(forms.Form):
name = forms.CharField(max_length=25)
email = forms.EmailField()
to = forms.EmailField()
comments = forms.CharField(
required=False,
widget=forms.Textarea
)


class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body')
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 5.2.7 on 2025-10-06 05:33

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('blog', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='post',
name='slug',
field=models.SlugField(
max_length=250, unique_for_date='published_at'),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 5.2.7 on 2025-10-06 13:05

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('blog', '0002_alter_post_slug'),
]

operations = [
migrations.CreateModel(
name='Comment',
fields=[
('id', models.BigAutoField(auto_created=True,
primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=80)),
('email', models.EmailField(max_length=254)),
('body', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('active', models.BooleanField(default=True)),
('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
related_name='comments', to='blog.post')),
],
options={
'ordering': ('created_at',),
'indexes': [models.Index(fields=['created_at'], name='blog_commen_created_4e025c_idx')],
},
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 5.2.7 on 2025-10-07 11:52

import taggit.managers
from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('blog', '0003_comment'),
('taggit', '0006_rename_taggeditem_content_type_object_id_taggit_tagg_content_8fc721_idx'),
]

operations = [
migrations.AddField(
model_name='post',
name='tags',
field=taggit.managers.TaggableManager(
help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
),
]
42 changes: 41 additions & 1 deletion Projects/Testtrack/M1 - Django Learning/mysite/blog/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from django.db import models
from django.urls import reverse
from django.utils import timezone
from django.conf import settings
from taggit.managers import TaggableManager


class PublishedManager(models.Manager):
Expand All @@ -15,7 +17,10 @@ class Status(models.TextChoices):
PUBLISHED = 'PB', 'Published'

title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250)
slug = models.SlugField(
max_length=250,
unique_for_date='published_at'
)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
Expand All @@ -30,6 +35,7 @@ class Status(models.TextChoices):

objects = models.Manager()
published = PublishedManager()
tags = TaggableManager()

class Meta:
ordering = ('-published_at',)
Expand All @@ -39,3 +45,37 @@ class Meta:

def __str__(self):
return self.title

def get_absolute_url(self):
return reverse(
'blog:post_detail',
args=[
self.published_at.year,
self.published_at.month,
self.published_at.day,
self.slug
]
)


class Comment(models.Model):
post = models.ForeignKey(
Post,
on_delete=models.CASCADE,
related_name='comments'
)
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)

class Meta:
ordering = ('created_at',)
indexes = [
models.Index(fields=['created_at']),
]

def __str__(self):
return f'Comment by {self.name} on {self.post}'
13 changes: 13 additions & 0 deletions Projects/Testtrack/M1 - Django Learning/mysite/blog/sitemaps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from django.contrib.sitemaps import Sitemap
from .models import Post


class PostSitemap(Sitemap):
changefreq = 'weekly'
priority = 0.9

def items(self):
return Post.published.all()

def lastmod(self, obj):
return obj.updated_at
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{% load blog_tags %}
{% load static %}
<!DOCTYPE html>
<html lang="en">
Expand All @@ -9,11 +10,26 @@
</head>
<body>
<article id="content">
{% block content %}{% endblock %}
{% block content %}{% endblock %}
</article>
<aside id="sidebar">
<h2>My blog</h2>
<p> Hello dude!</p>
<h2>My blog</h2>
<p>Hello dude! I published {% total_posts %} posts so far.</p>
<p>
<a href="{% url "blog:post_feed" %}">Subscribe to my blog feed</a>
</p>
<h3>Latest posts</h3>
{% show_latest_posts 3 %}
<h3>Most commented posts</h3>
{% get_most_commented_posts as most_commented_posts %}
<ul>
{% for post in most_commented_posts %}
<li>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a> ({{ post.comments.count }})
</li>
{% empty %}
<li>No posts available.</li>
{% endfor %}
</aside>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{% extends "blog/base.html" %}

{% block title %}Add a comment{% endblock %}

{% block content %}
{% if comment %}
<h2>Your comment has been added.</h2>
<p><a href="{{ post.get_absolute_url }}">Back to post</a></p>
{% else %}
{% include "blog/post/includes/comment_form.html" %}
{% endif %}
{% endblock %}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% extends "blog/base.html" %}
{% load blog_tags %}

{% block title %}{{ post.title }}{% endblock %}

Expand All @@ -7,5 +8,34 @@ <h1>{{ post.title }}</h1>
<p class="date">
Published on {{ post.published_at }} by {{post.author}}
</p>
{{ post.body|linebreaks }}</p>
{{ post.body|markdown }}
<p>
<a href="{% url 'blog:post_share' post.pk %}">Share via email</a>
</p>
<h2>Similar posts</h2>
{% for post in similar_posts %}
<p>
<a href="{{ post.get_absolute_url }}">
{{ post.title }}
</a>
</p>
{% empty %}
<p>No similar posts found.</p>
{% endfor %}
{% with comments.count as total_comments %}
<h2>
{{ total_comments }} Comment{{ total_comments|pluralize }}
</h2>
{% endwith %}
{% for comment in comments %}
<div class="comment">
<p class="info">
Comment {{ forloop.counter }} by {{ comment.name }} on {{ comment.created_at }}
</p>
{{ comment.body|linebreaks }}
</div>
{% empty %}
<p>No comments yet.</p>
{% endfor %}
{% include "blog/post/includes/comment_form.html" %}
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<h2>Add new comment</h2>
<form action="{% url "blog:post_comment" post.id %}" method="post">
<div class="left">
{{ form.name.as_field_group }}
</div>
<div class="left">
{{ form.email.as_field_group }}
</div>
{{ form.body.as_field_group }}
{% csrf_token %}
<p>
<input type="submit" value="Add comment"/>
</p>
</form>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<ul>
{% for post in latest_posts %}
<li>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a> - {{ post.published_at }}
</li>
{% empty %}
<li>No recent posts available.</li>
{% endfor %}
</ul>
Loading
Loading