Fix error in file detection
- Author
- Maarten Vangeneugden
- Date
- June 27, 2021, 1:35 p.m.
- Hash
- 1e40d90bf6cad09f5bea5944ae63a1c2336e49fc
- Parent
- b51541052ba69b896a0e8c5286e8088bddd02c5d
- Modified files
- models.py
- templates/blog/feed.rss
- templates/blog/index.djhtml
models.py ¶
3 additions and 3 deletions.
View changes Hide changes
1 |
1 |
from django.utils import translation |
2 |
2 |
from django.template.defaultfilters import slugify |
3 |
3 |
from django.db import models |
4 |
4 |
import datetime |
5 |
5 |
import os |
6 |
6 |
|
7 |
7 |
def post_title_directory(instance, filename): |
8 |
8 |
""" Files will be uploaded to MEDIA_ROOT/blog/<year of publishing>/<blog |
9 |
9 |
title> |
10 |
10 |
The blog title is determined by the text before the first period (".") in |
11 |
11 |
the filename. So if the file has the name "Trains are bæ.en.md", the file |
12 |
12 |
will be stored in "blog/<this year>/Trains are bæ". Name your files |
13 |
13 |
properly! |
14 |
14 |
It should also be noted that all files are stored in the same folder if they |
15 |
15 |
belong to the same blogpost, regardless of language. The titles that are |
16 |
16 |
displayed to the user however, should be the titles of the files themselves, |
17 |
17 |
which should be in the native language. So if a blog post is titled |
18 |
18 |
"Universities of Belgium", its Dutch counterpart should be titled |
19 |
19 |
"Universiteiten van België", so the correct title can be derived from the |
20 |
20 |
filename. |
21 |
21 |
|
22 |
22 |
Recommended way to name the uploaded file: "<name of blog post in language |
23 |
23 |
it's written>.org". This removes the maximum amount of redundancy (e.g. the |
24 |
24 |
language of the file can be derived from the title, no ".fr.org" or something |
25 |
25 |
like that necessary), and can directly be used for the end user (the title |
26 |
26 |
is what should be displayed). |
27 |
27 |
""" |
28 |
28 |
english_file_name = os.path.basename(instance.english_file.name) # TODO: Test if this returns the file name! |
29 |
29 |
english_title = english_file_name.rpartition(".")[0] |
30 |
30 |
year = datetime.date.today().year |
31 |
31 |
|
32 |
32 |
return "blog/{0}/{1}/{2}".format(year, english_title, filename) |
33 |
33 |
|
34 |
34 |
class Post(models.Model): |
35 |
35 |
""" Represents a blog post. The title of the blog post is determnined by the name |
36 |
36 |
of the files. |
37 |
37 |
A blog post can be in 5 different languages: German, Spanish, English, French, |
38 |
38 |
and Dutch. For all these languages, a seperate field exists. Thus, a |
39 |
39 |
translated blog post has a seperate file for each translation, and is |
40 |
40 |
seperated from Django's internationalization/localization system. |
41 |
41 |
Only the English field is mandatory. The others may contain a value if a |
42 |
42 |
translated version exists, which will be displayed accordingly. |
43 |
43 |
""" |
44 |
44 |
published = models.DateTimeField(auto_now_add=True) |
45 |
45 |
english_file = models.FileField(upload_to=post_title_directory, blank=False) |
46 |
46 |
dutch_file = models.FileField(upload_to=post_title_directory, blank=False) |
47 |
47 |
french_file = models.FileField(upload_to=post_title_directory, blank=True) |
48 |
48 |
german_file = models.FileField(upload_to=post_title_directory, blank=True) |
49 |
49 |
spanish_file = models.FileField(upload_to=post_title_directory, blank=True) |
50 |
50 |
|
51 |
51 |
title_en = models.CharField(max_length=64, unique=True, blank=False) |
52 |
52 |
title_nl = models.CharField(max_length=64, unique=True, blank=False) |
53 |
53 |
title_fr = models.CharField(max_length=64, blank=True) |
54 |
54 |
title_de = models.CharField(max_length=64, blank=True) |
55 |
55 |
title_es = models.CharField(max_length=64, blank=True) |
56 |
56 |
# PostgreSQL sees two null values as not unique, therefore I can't ask for unique names. |
57 |
57 |
|
58 |
58 |
slug_en = models.SlugField(unique=True, blank=False, allow_unicode=True) |
59 |
59 |
slug_nl = models.SlugField(unique=True, blank=False, allow_unicode=True) |
60 |
60 |
slug_fr = models.SlugField(blank=True, allow_unicode=True) |
61 |
61 |
slug_de = models.SlugField(blank=True, allow_unicode=True) |
62 |
62 |
slug_es = models.SlugField(blank=True, allow_unicode=True) |
63 |
63 |
|
64 |
64 |
def __str__(self): |
65 |
65 |
return self.slug("en") |
66 |
66 |
|
67 |
67 |
def text_file(self, language_code=translation.get_language()): |
68 |
68 |
if language_code == "en": |
69 |
69 |
return self.english_file |
70 |
70 |
elif language_code == "nl": |
71 |
71 |
return self.dutch_file |
72 |
72 |
elif language_code == "de": |
73 |
73 |
if self.german_file is None: |
74 |
- | return self.english_file |
+ |
74 |
return self.english_file |
75 |
75 |
else: |
76 |
76 |
return self.german_file |
77 |
77 |
elif language_code == "fr": |
78 |
78 |
if self.french_file is None: |
79 |
- | return self.english_file |
+ |
79 |
return self.english_file |
80 |
80 |
else: |
81 |
81 |
return self.french_file |
82 |
82 |
elif language_code == "es": |
83 |
83 |
if self.spanish_file is None: |
84 |
- | return self.english_file |
+ |
84 |
return self.english_file |
85 |
85 |
else: |
86 |
86 |
return self.spanish_file |
87 |
87 |
return self.english_file |
88 |
88 |
|
89 |
89 |
def title(self, language_code=translation.get_language()): |
90 |
90 |
if language_code == "en": |
91 |
91 |
return self.title_en |
92 |
92 |
elif language_code == "nl": |
93 |
93 |
return self.title_nl |
94 |
94 |
elif language_code == "de": |
95 |
95 |
if self.title_de == "": |
96 |
96 |
return self.title_en |
97 |
97 |
else: |
98 |
98 |
return self.title_de |
99 |
99 |
elif language_code == "fr": |
100 |
100 |
if self.title_fr == "": |
101 |
101 |
return self.title_en |
102 |
102 |
else: |
103 |
103 |
return self.title_fr |
104 |
104 |
elif language_code == "es": |
105 |
105 |
if self.title_es == "": |
106 |
106 |
return self.title_en |
107 |
107 |
else: |
108 |
108 |
return self.title_es |
109 |
109 |
return self.title_en |
110 |
110 |
|
111 |
111 |
def slug(self, language_code=translation.get_language()): |
112 |
112 |
""" Returns a slug of the requested language, or None if no version exists in that language. """ |
113 |
113 |
if language_code == "en": |
114 |
114 |
return self.slug_en |
115 |
115 |
elif language_code == "nl": |
116 |
116 |
return self.slug_nl |
117 |
117 |
elif language_code == "de": |
118 |
118 |
if self.slug_de == "": |
119 |
119 |
return self.slug_en |
120 |
120 |
else: |
121 |
121 |
return self.slug_de |
122 |
122 |
elif language_code == "fr": |
123 |
123 |
if self.slug_fr == "": |
124 |
124 |
return self.slug_en |
125 |
125 |
else: |
126 |
126 |
return self.slug_fr |
127 |
127 |
elif language_code == "es": |
128 |
128 |
if self.slug_es == "": |
129 |
129 |
return self.slug_en |
130 |
130 |
else: |
131 |
131 |
return self.slug_es |
132 |
132 |
return self.slug_en |
133 |
133 |
|
134 |
134 |
class Comment(models.Model): |
135 |
135 |
""" Represents a comment on a blog post. |
136 |
136 |
Comments are not filtered by language; a |
137 |
137 |
comment made by someone reading the article in Dutch, that's written in |
138 |
138 |
Dutch, will show up (unedited) for somebody whom's reading the Spanish |
139 |
139 |
version. |
140 |
140 |
""" |
141 |
141 |
date = models.DateTimeField(auto_now_add=True) |
142 |
142 |
name = models.CharField(max_length=64) |
143 |
143 |
text = models.TextField(max_length=1000) # Should be more than enough. |
144 |
144 |
post = models.ForeignKey( |
145 |
145 |
Post, |
146 |
146 |
on_delete=models.CASCADE, |
147 |
147 |
null=False, |
148 |
148 |
) |
149 |
149 |
class meta: |
150 |
150 |
ordering = ['date'] # When printed, prints the oldest comment first. |
151 |
151 |
|
152 |
152 |
class FeedItem(models.Model): |
153 |
153 |
""" An item that shows up in the RSS feed.""" |
154 |
154 |
title = models.CharField(max_length=64) |
155 |
155 |
added = models.DateTimeField(auto_now_add=True) |
156 |
156 |
description = models.CharField(max_length=400) |
157 |
157 |
link = models.URLField() |
158 |
158 |
templates/blog/feed.rss ¶
4 additions and 1 deletion.
View changes Hide changes
1 |
1 |
<rss version="2.0"> |
2 |
- | <channel> |
+ |
2 |
|
+ |
3 |
<channel> |
3 |
4 |
<title>RSS-kanaal voor maartenv.be</title> |
+ |
5 |
<title>RSS-kanaal voor maartenv.be</title> |
4 |
6 |
<link>https://maartenv.be</link> |
5 |
7 |
<description>The official RSS feed for the personal website of Maarten V.</description> |
6 |
8 |
{% for item in items %} |
7 |
9 |
<item> |
8 |
10 |
<title>{{ item.title }}</title> |
9 |
11 |
<link>{{ item.link }}</link> |
10 |
12 |
<description>{{ item.description }}</description> |
+ |
13 |
<description>{{ item.description }}</description> |
11 |
14 |
{% language 'en' %} |
12 |
15 |
<pubDate>{{ item.added|date:'r' }}</pubDate> |
13 |
16 |
{% endlanguage %} |
14 |
17 |
</item> |
15 |
18 |
{% endfor %} |
16 |
19 |
</channel> |
17 |
20 |
</rss> |
18 |
21 |
templates/blog/index.djhtml ¶
2 additions and 3 deletions.
View changes Hide changes
1 |
1 |
{% load i18n %} |
2 |
2 |
{% load static %} |
3 |
3 |
|
4 |
4 |
{% block stylesheets %} |
5 |
5 |
{{ block.super }} |
6 |
6 |
<style> |
7 |
7 |
img { |
8 |
8 |
width: 80%; |
9 |
9 |
display: block; |
10 |
10 |
margin-left: auto; |
11 |
11 |
margin-right: auto; |
12 |
12 |
} |
13 |
13 |
video { |
14 |
14 |
width: 80%; |
15 |
15 |
} |
16 |
16 |
</style> |
17 |
17 |
{% endblock %} |
18 |
18 |
|
19 |
19 |
{% block title %}{% trans "Maarten's blog" %}{% endblock title %} |
20 |
20 |
|
21 |
21 |
{% block description %}{% blocktrans %}The always coherently put together, yet |
22 |
22 |
fuzzy blog of whatever sprouts in my mind.{% endblocktrans %} |
23 |
23 |
{% endblock description %} |
24 |
24 |
|
25 |
25 |
{% block header %} |
26 |
26 |
<header> |
27 |
27 |
<h1>{% trans "Notepad of a student" %}</h1> |
28 |
28 |
<label for="nav-drawer-toggle">≡</label> |
29 |
29 |
</header> |
30 |
30 |
{% endblock header %} |
31 |
31 |
|
32 |
32 |
{% block nav %} |
33 |
33 |
<input id="nav-drawer-toggle" type="checkbox" /> |
34 |
34 |
<nav> |
35 |
35 |
<label for="nav-drawer-toggle"><!--🡨-->🡠</label> |
36 |
36 |
<h2>{% trans "Navigation" %}</h2> |
37 |
37 |
{% for title, date, blog_text, link in posts %} |
38 |
38 |
<a class="nav-link" href="{{ link }}">{{ title }}</a> |
39 |
39 |
{% endfor %} |
40 |
40 |
<hr class="half" /> |
41 |
41 |
<a class="nav-link" href="{% url 'about-index' %}">{% trans "Front page" %}</a> |
42 |
42 |
</nav> |
43 |
43 |
{% endblock nav %} |
44 |
44 |
|
45 |
45 |
{% block main %} |
46 |
46 |
|
47 |
47 |
<section class="emphasis"> |
48 |
48 |
<h1>{% trans "Blog" %}</h1> |
49 |
49 |
<p> |
50 |
50 |
{% blocktrans %}Welcome to my blog. Here, I write |
51 |
51 |
about things that interest me. Politics, coding, |
52 |
52 |
studying, life, or anything else I fancy rambling |
53 |
53 |
about. If you're in luck, I may've written it in a |
54 |
54 |
language that you understand better than English. |
55 |
55 |
{% endblocktrans %} |
56 |
56 |
</p> |
57 |
57 |
</section> |
58 |
58 |
|
59 |
59 |
<!--<div class="fab"> |
60 |
- | <a href="{% url 'blog-feed' %}" id="feed-fab"> |
+ |
60 |
<a href="{% url 'blog-feed' %}" id="feed-fab"> |
61 |
61 |
<i class="large material-icons">rss_feed</i> |
62 |
- | <b>RSS</b> |
63 |
62 |
</a> |
64 |
63 |
</div>--> |
65 |
- | |
+ |
64 |
|
66 |
65 |
<section> |
67 |
66 |
<h1>Monthly</h1> |
68 |
67 |
<a class="btn fill" href="{% url "monthly-archive" %}"> {% trans "Open archive" %}</a> |
69 |
68 |
{% include "blog/monthly.html" %} |
70 |
69 |
</section> |
71 |
70 |
|
72 |
71 |
<div class="cards"> |
73 |
72 |
{% for title, date, blog_text, link in posts %} |
74 |
73 |
<div class="card"> |
75 |
74 |
<h3>{{ title }}</h3> |
76 |
75 |
<h4>{{ date|date:"DATE_FORMAT" }}</h4> |
77 |
76 |
<p>{{ blog_text|safe|truncatewords_html:100 }}</p> |
78 |
77 |
<a class="btn outline" href="{{link}}">📚 {% trans "Read on" %}</a> |
79 |
78 |
</div> |
80 |
79 |
{% endfor %} |
81 |
80 |
</div> |
82 |
81 |
|
83 |
82 |
{% endblock main %} |
84 |
83 |