<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>django &amp;mdash; Ignored By Dinosaurs 🦕</title>
    <link>https://www.ignoredbydinosaurs.com/tag:django</link>
    <description></description>
    <pubDate>Sun, 14 Jun 2026 00:02:55 -0400</pubDate>
    <item>
      <title>Prev/Next as linked lists in Django</title>
      <link>https://www.ignoredbydinosaurs.com/284-prevnext-linked-lists-django</link>
      <description>&lt;![CDATA[Problemspace&#xA;&#xA;I want to be able to link a set of posts together in an order. If there is a next post relative to the one I&#39;m on, I want a button to show up that says &#34;next post&#34; and links to it. If there is a previous post relative to the one that I&#39;m on, I want a button that says &#34;previous post&#34; and links back to it. Pretty simple, conceptually. Basically I want to reproduce parts of the Drupal book.module as minimally as possible. &#xA;&#xA;So my first naive attempt was to add 2 ForeignKey fields to the Post model - &#34;previous&#34; and &#34;next&#34;.&#xA;&#xA;~py&#xA;class Post(models.Model):&#xA;&#xA;&#x9;title = models.CharField(maxlength=255)&#xA;&#x9;body = models.TextField()&#xA;&#x9;summary = models.TextField(null=True, blank=True)&#xA;&#x9;slug = models.SlugField(maxlength=255)&#xA;&#x9;pubdate = models.DateTimeField(&#39;Published at&#39;)&#xA;&#x9;published = models.BooleanField()&#xA;&#x9;tags = models.ManyToManyField(Tag)&#xA;&#x9;created = models.DateTimeField(autonowadd=True)&#xA;&#x9;updated = models.DateTimeField(autonow=True)&#xA;&#x9;previouspost = models.ForeignKey(&#xA;&#x9;&#x9;&#39;self&#39;,&#xA;&#x9;&#x9;relatedname=&#39;previouspost&#39;,&#xA;&#x9;&#x9;blank=True,&#xA;&#x9;&#x9;null=True,&#xA;&#x9;&#x9;ondelete=None&#xA;&#x9;)&#xA;&#x9;nextpost = models.ForeignKey(&#xA;&#x9;&#x9;&#39;self&#39;,&#xA;&#x9;&#x9;relatedname=&#39;nextpost&#39;,&#xA;&#x9;&#x9;blank=True,&#xA;&#x9;&#x9;null=True,&#xA;&#x9;&#x9;ondelete=None&#xA;&#x9;)&#xA;~&#xA;&#xA;This worked on the front end but immediately raised a stink alarm, for a couple of reasons.&#xA;&#xA;You&#39;d have to go and save this info twice for it to really work. Once on the current post and again on the referred post to link it back. == Workflow suck&#xA;&#xA;The truth about this ordering would be stored in two places, so it&#39;d be really easy to mess something up and get out of sync.&#xA;&#xA;This is essentially a doubly-linked list if you&#39;re keeping score, with the encumbant maintenance problems.&#xA;&#xA;So I thought to perhaps override the save() method in order to hook into the operation and automatically populate the correct field on the referred item, but then of course, I&#39;d have to do all kinds of gymnastics to watch for if that field were to be removed at some point and remove the corresponding field on the referred item, etc. I mean, it&#39;s a blog who gives a shit, but I&#39;ve been doing this for long enough now that I can&#39;t help myself.&#xA;&#xA;Another option in this same vein is to use the Django &#34;signals&#34; subsystem to hook into the same functionality, but the smell remains.&#xA;&#xA;After coming home from DrupalCon it occurred to me that really all I need is the one pointer, since I should be able to derive the pointer back. I just had to figure out how to do it...&#xA;&#xA;relatedname()&#xA;&#xA;This is a pretty obvious use case - automatically deriving any pointers back to the current item. It just requires one extra DB query to ask &#34;give me any items where the previouspostid is this item&#39;s id&#34;.&#xA;&#xA;The key is the relatedname argument to the model. &#xA;&#xA;I think this is automatically set for a normal ForeignKey field, but on models where the foreign key points back to the same model it&#39;s required. Judging from the docs, I was trying all manner of post.postset, etc but it&#39;s actually just post.previouspost, which is counter-intuitive since what you&#39;re actually getting back from that is the &#34;next&#34; post. I chose to keep the &#34;previous&#34; field since you could just add the previous post as you&#39;re authoring the current one.&#xA;&#xA;Current post model looks like this --&#xA;&#xA;~py&#xA;class Post(models.Model):&#xA;&#xA;&#x9;title = models.CharField(maxlength=255)&#xA;&#x9;body = models.TextField()&#xA;&#x9;summary = models.TextField(null=True, blank=True)&#xA;&#x9;slug = models.SlugField(maxlength=255)&#xA;&#x9;pubdate = models.DateTimeField(&#39;Published at&#39;)&#xA;&#x9;published = models.BooleanField()&#xA;&#x9;tags = models.ManyToManyField(Tag)&#xA;&#x9;created = models.DateTimeField(autonowadd=True)&#xA;&#x9;updated = models.DateTimeField(autonow=True)&#xA;&#x9;previous = models.OneToOneField(&#xA;&#x9;&#x9;&#39;self&#39;,&#xA;&#x9;&#x9;relatedname=&#39;previouspost&#39;,&#xA;&#x9;&#x9;blank=True,&#xA;&#x9;&#x9;null=True,&#xA;&#x9;&#x9;ondelete=None&#xA;&#x9;)&#xA;~&#xA;&#xA;And the prev/next fields look like this --&#xA;&#xA;~html&#xA;{% if post.previous %}&#xA; &#xA;← previous: {{ post.previous.title }}&#xA;&#xA;{% endif %}&#xA;{% with nextpost=post.previouspost %}&#xA; {% if nextpost %}&#xA; &#xA;next: {{ nextpost.title }} →&#xA;&#xA; {% endif %}&#xA;{% endwith %}&#xA;~&#xA;&#xA;note&#xA;&#xA;This might not technically be a linked list in the strictest sense, since a singly-linked list has pointers to the next node in the chain. I&#39;ve implemented it here as a &#34;previous&#34; pointer, since it makes more sense in the edit workflow. Since it makes more sense, hopefully we&#39;ll make more cents!&#xA;&#xA;Stay tuned for the next episode where I decide that I&#39;d like to have a Table of Contents and rip this whole thing out and do it over again.&#xA;&#xA;#generaldevelopment #django]]&gt;</description>
      <content:encoded><![CDATA[<h2 id="problemspace">Problemspace</h2>

<p>I want to be able to link a set of posts together in an order. If there is a next post relative to the one I&#39;m on, I want a button to show up that says “next post” and links to it. If there is a previous post relative to the one that I&#39;m on, I want a button that says “previous post” and links back to it. Pretty simple, conceptually. Basically I want to reproduce parts of the Drupal book.module as minimally as possible.</p>

<p>So my first naive attempt was to add 2 <a href="https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.ForeignKey">ForeignKey fields</a> to the Post model – “previous” and “next”.</p>

<pre><code class="language-py">class Post(models.Model):

	title = models.CharField(max_length=255)
	body = models.TextField()
	summary = models.TextField(null=True, blank=True)
	slug = models.SlugField(max_length=255)
	pub_date = models.DateTimeField(&#39;Published at&#39;)
	published = models.BooleanField()
	tags = models.ManyToManyField(Tag)
	created = models.DateTimeField(auto_now_add=True)
	updated = models.DateTimeField(auto_now=True)
	previous_post = models.ForeignKey(
		&#39;self&#39;,
		related_name=&#39;previous_post&#39;,
		blank=True,
		null=True,
		on_delete=None
	)
	next_post = models.ForeignKey(
		&#39;self&#39;,
		related_name=&#39;next_post&#39;,
		blank=True,
		null=True,
		on_delete=None
	)
</code></pre>

<p>This worked on the front end but immediately raised a stink alarm, for a couple of reasons.</p>
<ul><li><p>You&#39;d have to go and save this info twice for it to really work. Once on the current post and again on the referred post to link it back. == Workflow suck</p></li>

<li><p>The truth about this ordering would be stored in two places, so it&#39;d be really easy to mess something up and get out of sync.</p></li></ul>

<p>This is essentially a <a href="https://en.wikipedia.org/wiki/Doubly_linked_list">doubly-linked list</a> if you&#39;re keeping score, with the encumbant maintenance problems.</p>

<p>So I thought to perhaps override the <code>save()</code> method in order to hook into the operation and automatically populate the correct field on the referred item, but then of course, I&#39;d have to do all kinds of gymnastics to watch for if that field were to be removed at some point and remove the corresponding field on the referred item, etc. I mean, it&#39;s a blog who gives a shit, but I&#39;ve been doing this for long enough now that I can&#39;t help myself.</p>

<p>Another option in this same vein is to use the Django “signals” subsystem to hook into the same functionality, but the smell remains.</p>

<p>After coming home from DrupalCon it occurred to me that really all I need is the one pointer, since I should be able to derive the pointer back. I just had to figure out how to do it...</p>

<h3 id="related-name"><code>related_name()</code></h3>

<p>This is a pretty obvious use case – automatically deriving any pointers back to the current item. It just requires one extra DB query to ask “give me any items where the previous<em>post</em>id is this item&#39;s id”.</p>

<p>The key is the <a href="https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.ForeignKey.related_name"><code>related_name</code></a> argument to the model.</p>

<p>I think this is automatically set for a normal ForeignKey field, but on models where the foreign key points back to the same model it&#39;s required. Judging from the docs, I was trying all manner of <code>post.post_set</code>, etc but it&#39;s actually just <code>post.previous_post</code>, which is counter-intuitive since what you&#39;re actually getting back from that is the “next” post. I chose to keep the “previous” field since you could just add the previous post as you&#39;re authoring the current one.</p>

<p>Current post model looks like this —</p>

<pre><code class="language-py">class Post(models.Model):

	title = models.CharField(max_length=255)
	body = models.TextField()
	summary = models.TextField(null=True, blank=True)
	slug = models.SlugField(max_length=255)
	pub_date = models.DateTimeField(&#39;Published at&#39;)
	published = models.BooleanField()
	tags = models.ManyToManyField(Tag)
	created = models.DateTimeField(auto_now_add=True)
	updated = models.DateTimeField(auto_now=True)
	previous = models.OneToOneField(
		&#39;self&#39;,
		related_name=&#39;previous_post&#39;,
		blank=True,
		null=True,
		on_delete=None
	)
</code></pre>

<p>And the prev/next fields look like this —</p>

<pre><code class="language-html">{% if post.previous %}
 
[← previous: {{ post.previous.title }}]({% url )

{% endif %}
{% with next_post=post.previous_post %}
 {% if next_post %}
 
[next: {{ next_post.title }} →]({% url )


 {% endif %}
{% endwith %}
</code></pre>

<p><strong>note</strong></p>

<p>This might not technically be a linked list in the strictest sense, since a singly-linked list has pointers to the <em>next</em> node in the chain. I&#39;ve implemented it here as a “previous” pointer, since it makes more sense in the edit workflow. Since it makes more sense, hopefully we&#39;ll make more cents!</p>

<p>Stay tuned for the next episode where I decide that I&#39;d like to have a Table of Contents and rip this whole thing out and do it over again.</p>

<p><a href="https://www.ignoredbydinosaurs.com/tag:generaldevelopment" class="hashtag"><span>#</span><span class="p-category">generaldevelopment</span></a> <a href="https://www.ignoredbydinosaurs.com/tag:django" class="hashtag"><span>#</span><span class="p-category">django</span></a></p>
]]></content:encoded>
      <guid>https://www.ignoredbydinosaurs.com/284-prevnext-linked-lists-django</guid>
      <pubDate>Mon, 06 Jun 2016 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Easy markdown and syntax highlighting in Django</title>
      <link>https://www.ignoredbydinosaurs.com/275-easy-markdown-and-syntax-highlighting-django</link>
      <description>&lt;![CDATA[Hi there, I&#39;m new to Django. I love the contributed ecosystem, but all of the options that I found there for dealing with Markdown were just too heavy. I didn&#39;t need a Wysiwyg editor, I just wanted an output filter. As it turns out this is exceptionally easy to do!&#xA;&#xA;---&#xA;&#xA;Python has a really amazing lib situation, so I just found the smallest python Markdown lib that I could, it&#39;s called &#34;mistune&#34;. Do a pip install mistune.&#xA;&#xA;So within your app, let&#39;s call it &#34;blog&#34;, create a directory called templatetags. By the way, this is all pretty easy to parse out of their killer documentation. Create a file in there called markdownify.py. &#xA;&#xA;~python&#xA; # blog/templatetags/markdownify.py&#xA;from django import template&#xA;import mistune&#xA; &#xA;register = template.library()&#xA; &#xA;@register.filter&#xA;def markdown(value):&#xA;&#x9;markdown = mistune.Markdown()&#xA;&#x9;return markdown(value)&#xA;&#xA;~&#xA;&#xA;It is as simple as that. In whatever template you&#39;ll actually want to be rendering markdown, you&#39;ll need to include this templatetag with &#xA;&#xA;~python&#xA; {% load markdownify %}&#xA;~&#xA;&#xA;at the top of the template. Then you&#39;ll just pipe the output that you want to render like you do in every other template lib ---&#xA;&#xA;~html&#xA;{{ post.body | markdown | safe }}&#xA;~&#xA;&#xA;The full example of the template that renders this page is here.&#xA;&#xA;---&#xA;&#xA;But wait, there&#39;s more!&#xA;&#xA;How about syntax highlighting? We&#39;re programmers after all, and Python just happens to have the great-granddaddy of all syntax highlighting libs in Pygments. I&#39;ve known of Pygments for years, since it used to be a requirement of one of the Ruby libs to Markdown rendering (if you wanted synta highlighting). In other words, even Ruby leaned on Pygments for a great number of years.&#xA;&#xA;So pip install pygments. Then scroll down the page on the Mistune docs and follow along. You&#39;ll be adding some code to the markdownify.py file.&#xA;&#xA;~python&#xA;from django import template&#xA;import mistune&#xA;from pygments import highlight&#xA;from pygments.lexers import getlexerbyname&#xA;from pygments.formatters import HtmlFormatter&#xA;&#xA;register = template.Library()&#xA;&#xA;class HighlightRenderer(mistune.Renderer):&#xA;    def blockcode(self, code, lang):&#xA;        if not lang:&#xA;            return f&#34;&#34;&#34;&#xA;{mistune.escape(code)}&#xA;            &#34;&#34;&#34;&#xA;        lexer = getlexerbyname(lang, stripall=True)&#xA;        formatter = HtmlFormatter()&#xA;        return highlight(code, lexer, formatter)&#xA;&#xA;@register.filter&#xA;def markdown(value):&#xA;    renderer = HighlightRenderer()&#xA;    markdown = mistune.Markdown(renderer=renderer)&#xA;    return markdown(value)&#xA;~&#xA;&#xA;That HighlightRenderer class is directly out of the Mistune docs, so thank you Mistune Author! That is seriously all it takes, but you&#39;ll need a stylesheet, of which there are plenty. I searched for &#34;pygments stylesheets&#34; and came across this project, so you&#39;ll need to pick one of those themes and get it into your project somewhere. By default, the zenburn theme is expecting the wrapper div to have a CSS class of &#39;codehilite&#39; instead of what it needs - &#39;highlight&#39;, so a quick search and replace and I had syntax highlighting in less than 5 minutes.&#xA;&#xA;---&#xA;&#xA;\edit Sept 2016\&#xA;&#xA;So once you manage your way through all this, you&#39;ll be able to use &#34;fenced code blocks&#34; in your posts. They look like this --&#xA;&#xA;~&#xA;&lt;?php &#xA;&#xA;function foo() {&#xA; /// ...&#xA;}&#xA;~&#xA;&#xA;becomes&#xA;&#xA;&lt;?php &#xA;&#xA;function foo() {&#xA; /// ...&#xA;}&#xA;&#xA;You can use either a trio of tildes ~ or backticks \` to open and close one of those code blocks, and I typically just pass the file extension and it generally works. You can also write out the full name of the language.&#xA;&#xA;~&#xA;def method():&#xA;    return &#34;foo&#34;&#xA;~&#xA;&#xA;becomes&#xA;&#xA;def method():&#xA;    return &#34;foo&#34;&#xA;&#xA;Just be advised that it is possible to fatally hose your website if you happen to pass a language for which Pygments doesn&#39;t have a &#34;lexer&#34;, meaning that it has no idea how to highlight the syntax of that language. That happened to me with some Varnish config files that I tried to highlight with a .vcl extension on them. I don&#39;t remember how I fixed it but I&#39;m pretty sure it required going directly to the database to change the post since my site was toast. You are warned.&#xA;&#xA;#python #django]]&gt;</description>
      <content:encoded><![CDATA[<p>Hi there, I&#39;m new to Django. I love the contributed ecosystem, but all of the options that I found there for dealing with Markdown were just too heavy. I didn&#39;t need a Wysiwyg editor, I just wanted an output filter. As it turns out this is exceptionally easy to do!</p>

<hr>

<p>Python has a really amazing lib situation, so I just found the smallest python Markdown lib that I could, it&#39;s called <a href="https://mistune.readthedocs.org/en/latest/">“mistune”</a>. Do a <code>pip install mistune</code>.</p>

<p>So within your app, let&#39;s call it “blog”, create a directory called <code>templatetags</code>. By the way, this is all pretty easy to parse out of <a href="https://docs.djangoproject.com/en/1.9/howto/custom-template-tags/">their killer documentation</a>. Create a file in there called <code>markdownify.py</code>.</p>

<pre><code class="language-python"> # blog/templatetags/markdownify.py
from django import template
import mistune
 
register = template.library()
 
@register.filter
def markdown(value):
	markdown = mistune.Markdown()
	return markdown(value)

</code></pre>

<p>It is as simple as that. In whatever template you&#39;ll actually want to be rendering markdown, you&#39;ll need to include this templatetag with</p>

<pre><code class="language-python"> {% load markdownify %}
</code></pre>

<p>at the top of the template. Then you&#39;ll just pipe the output that you want to render like you do in every other template lib —-</p>

<pre><code class="language-html">{{ post.body | markdown | safe }}
</code></pre>

<p>The full example of <a href="https://github.com/JGrubb/django-blog/blob/master/blog/templates/blog/post_detail.html">the template that renders this page</a> is here.</p>

<hr>

<h3 id="but-wait-there-s-more">But wait, there&#39;s more!</h3>

<p>How about syntax highlighting? We&#39;re programmers after all, and Python just happens to have the great-granddaddy of all syntax highlighting libs in <a href="http://pygments.org/">Pygments</a>. I&#39;ve known of Pygments for years, since it used to be a requirement of one of the Ruby libs to Markdown rendering (if you wanted synta highlighting). In other words, even Ruby leaned on Pygments for a great number of years.</p>

<p>So <code>pip install pygments</code>. Then scroll down the page on the Mistune docs and follow along. You&#39;ll be adding some code to the <code>markdownify.py</code> file.</p>

<pre><code class="language-python">from django import template
import mistune
from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter

register = template.Library()

class HighlightRenderer(mistune.Renderer):
    def block_code(self, code, lang):
        if not lang:
            return f&#34;&#34;&#34;
```
{mistune.escape(code)}
```
            &#34;&#34;&#34;
        lexer = get_lexer_by_name(lang, stripall=True)
        formatter = HtmlFormatter()
        return highlight(code, lexer, formatter)

@register.filter
def markdown(value):
    renderer = HighlightRenderer()
    markdown = mistune.Markdown(renderer=renderer)
    return markdown(value)
</code></pre>

<p>That <code>HighlightRenderer</code> class is directly out of the Mistune docs, so thank you Mistune Author! That is seriously all it takes, but you&#39;ll need a stylesheet, of which there are plenty. I searched for “pygments stylesheets” and came across <a href="https://github.com/richleland/pygments-css">this project</a>, so you&#39;ll need to pick one of those themes and get it into your project somewhere. By default, the zenburn theme is expecting the wrapper div to have a CSS class of &#39;codehilite&#39; instead of what it needs – &#39;highlight&#39;, so a quick search and replace and I had syntax highlighting in less than 5 minutes.</p>

<hr>

<p>*edit Sept 2016*</p>

<p>So once you manage your way through all this, you&#39;ll be able to use “<a href="https://help.github.com/articles/creating-and-highlighting-code-blocks/">fenced code blocks</a>” in your posts. They look like this —</p>

<pre><code>```php
&lt;?php 

function foo() {
 /// ...
}
```
</code></pre>

<p>becomes</p>

<pre><code class="language-php">&lt;?php 

function foo() {
 /// ...
}
</code></pre>

<p>You can use either a trio of tildes <code>~</code> or backticks ` to open and close one of those code blocks, and I typically just pass the file extension and it generally works. You can also write out the full name of the language.</p>

<pre><code>```py
def method():
    return &#34;foo&#34;
```
</code></pre>

<p>becomes</p>

<pre><code class="language-python">def method():
    return &#34;foo&#34;
</code></pre>

<p>Just be advised that it is possible to fatally hose your website if you happen to pass a language for which Pygments doesn&#39;t have a “lexer”, meaning that it has no idea how to highlight the syntax of that language. That happened to me with some Varnish config files that I tried to highlight with a <code>.vcl</code> extension on them. I don&#39;t remember how I fixed it but I&#39;m pretty sure it required going directly to the database to change the post since my site was toast. You are warned.</p>

<p><a href="https://www.ignoredbydinosaurs.com/tag:python" class="hashtag"><span>#</span><span class="p-category">python</span></a> <a href="https://www.ignoredbydinosaurs.com/tag:django" class="hashtag"><span>#</span><span class="p-category">django</span></a></p>
]]></content:encoded>
      <guid>https://www.ignoredbydinosaurs.com/275-easy-markdown-and-syntax-highlighting-django</guid>
      <pubDate>Wed, 23 Mar 2016 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>Goodbye Rails, Hello Django</title>
      <link>https://www.ignoredbydinosaurs.com/272-goodbye-rails-hello-django</link>
      <description>&lt;![CDATA[So here it is. The last version of this blog - a Rails frontend to a Postgres backend - actually stood for almost 2 and a half years. I think that&#39;s probably a record. &#xA;&#xA;In keeping with my decided new theme for this blog however, I&#39;ve decided to rewrite the thing in Django. Not that you can&#39;t google it yourself, but Django is (at a high level) basically the Python version of Rails. Actually, it&#39;s basically the Python version of every MVC web framework. It&#39;s been around for 10 years, so it is far from the hot-new-thing. I&#39;ve finally been doing this for long enough that I shy away from the hot-new-thing and actively seek out boring, tested solutions to problems. &#xA;&#xA;At work we&#39;ve begun a small project that we were targeting to build on Drupal 8. Faced with the timeframe, the relative lack of basic modules for building Drupal 8 sites, and the learning curve for the code that we&#39;d inevitably have to write on our own I pitched the idea to my team to try something completely different. I prefaced it with &#34;this is a terrible idea, so raise your hand at any point&#34;, but surprisingly they were all amenable. We all spent a day going through the amazing tutorial and the amazing documentation and they were still on board. So I decided to rebuild this blog to take the training wheels off and give us all some reference code for some of the simple features that weren&#39;t walked through in the tutorial - taxonomy, sitemaps, extending templates, etc.&#xA;&#xA;Amazingly it took me all of 4 hours to rebuild the whole thing and migrate the data from one PG schema into the one that Django wants to use. Django is even easier to use than Rails - a fact that blew my mind once I started playing with it. &#xA;&#xA;The deployment story however, is a shit show. I spent as many days trying to get this thing up on a Digital Ocean server as I spent hours building the application in the first place. I&#39;m hoping to find that there is an easier, more modern means for serving Python apps in 2016 after some more digging. &#xA;&#xA;Anyway, thanks for stopping by!&#xA;&#xA;#generaldevelopment #python #django]]&gt;</description>
      <content:encoded><![CDATA[<p>So here it is. The last version of this blog – a Rails frontend to a Postgres backend – actually stood for almost 2 and a half years. I think that&#39;s probably a record.</p>

<p>In keeping with my decided new theme for this blog however, I&#39;ve decided to rewrite the thing in Django. Not that you can&#39;t google it yourself, but Django is (at a high level) basically the Python version of Rails. Actually, it&#39;s basically the Python version of every MVC web framework. It&#39;s been around for 10 years, so it is far from the hot-new-thing. I&#39;ve finally been doing this for long enough that I shy away from the hot-new-thing and actively seek out boring, tested solutions to problems.</p>

<p>At work we&#39;ve begun a small project that we were targeting to build on Drupal 8. Faced with the timeframe, the relative lack of basic modules for building Drupal 8 sites, and the learning curve for the code that we&#39;d inevitably have to write on our own I pitched the idea to my team to try something completely different. I prefaced it with “this is a terrible idea, so raise your hand at any point”, but surprisingly they were all amenable. We all spent a day going through the amazing tutorial and the amazing documentation and they were still on board. So I decided to rebuild this blog to take the training wheels off and give us all some reference code for some of the simple features that weren&#39;t walked through in the tutorial – taxonomy, sitemaps, extending templates, etc.</p>

<p>Amazingly it took me all of 4 hours to rebuild the whole thing and migrate the data from one PG schema into the one that Django wants to use. Django is even easier to use than Rails – a fact that blew my mind once I started playing with it.</p>

<p>The deployment story however, is a shit show. I spent as many days trying to get this thing up on a Digital Ocean server as I spent hours building the application in the first place. I&#39;m hoping to find that there is an easier, more modern means for serving Python apps in 2016 after some more digging.</p>

<p>Anyway, thanks for stopping by!</p>

<p><a href="https://www.ignoredbydinosaurs.com/tag:generaldevelopment" class="hashtag"><span>#</span><span class="p-category">generaldevelopment</span></a> <a href="https://www.ignoredbydinosaurs.com/tag:python" class="hashtag"><span>#</span><span class="p-category">python</span></a> <a href="https://www.ignoredbydinosaurs.com/tag:django" class="hashtag"><span>#</span><span class="p-category">django</span></a></p>
]]></content:encoded>
      <guid>https://www.ignoredbydinosaurs.com/272-goodbye-rails-hello-django</guid>
      <pubDate>Sat, 19 Mar 2016 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title>A URL strategy</title>
      <link>https://www.ignoredbydinosaurs.com/258-a-url-strategy</link>
      <description>&lt;![CDATA[I&#39;ve got this decoupled CMS brewing in my head, and wanted to jot down what I think would be a kind of cool method for generating URLs and URL redirects and making sure everything stays in sync without having to maintain a giant table of redirects (ala Drupal).&#xA;&#xA;The basic scheme would look like this -- site.com/{itemtype}/{itemid}/{itemslug}. The type parameter could probably be optional, but it&#39;s there for now. An example URL could be ignoredbydinoaurs.com/posts/123/the-totally-awesome-seo-juice. &#xA;&#xA;Of course, in whatever framework you&#39;re working in, those url segments are going to be broken down into tokens passed into whatever controller function is running the query. So your query would/could look like this in the controller &#xA;&#xA;~rb&#xA;&#xA;def show&#xA;&#x9;@post = Post.find(params[:id])&#xA;&#x9;if @post.slug != params[:slug]&#xA;&#x9;redirectto &#34;/#{@post.type}/#{post.id}/#{@post.slug}&#34;, :status =  :movedpermanently&#xA;&#x9;end&#xA;end&#xA;&#xA;~&#xA;&#xA;This has the advantage of never going out of sync with a redirect table, and never opening up the possibility of having an alias and a redirect create a loop. This happens often in Drupal, so with this scheme, you&#39;re only looking up based on an item&#39;s ID, which should never change. If somehow a URL has made it out in the the wild that is not the preferred URL, nothing breaks, it just gracefully performs a redirect to the proper URL.&#xA;&#xA;The only significant portion of the URL is the ID, everything else is decoration or SEO juice.&#xA;&#xA;---&#xA;&#xA;Somewhat off topic, but if you had a use cases where you were running multiple sites out of this CMS, and you had editors that frequently shared content, or wrote up each other&#39;s content for a sister site, then the primary key of of the article can stay consistent across different publications. &#xA;&#xA;&#34;How would different editors utilize each other&#39;s content in that case? Like, how would different pubs have the same article with a different summary on this instance from that instance?&#34;&#xA;&#xA;PostgreSQL schemas, that&#39;s how. I&#39;ll write that up, probably sometime in 2017.&#xA;&#xA;---&#xA;&#xA;2016, Django update&#xA;&#xA;This wasn&#39;t exactly hard to do, but I was surprised to find that nobody really wrote up how to simply issue a redirect like this in a Django view (controller to the rest of the world). Assuming that get() or getqueryset() was the answer, but I was wrong. This was the help piece of info that I needed. Did I mention how much I love Django&#39;s docs?&#xA;&#xA;This is the method that drives this very page.&#xA;&#xA;~python&#xA;&#xA;class DetailView(generic.DetailView):&#xA;&#x9;model = Post&#xA;&#x9;&#xA;&#x9;def dispatch(self, request, args, kwargs):&#xA;&#x9;object = getobjector_404(Post, pk=self.kwargs[&#39;pk&#39;])&#xA;&#x9;if object.slug != self.kwargs[&#39;slug&#39;]:&#xA;&#x9;return redirect(object, permanent=True)&#xA;&#x9;# else, delegate up&#xA;&#x9;return super(DetailView, self).dispatch(request, args, **kwargs)&#xA;&#xA;~&#xA;&#xA;#generaldevelopment #rails #django]]&gt;</description>
      <content:encoded><![CDATA[<p>I&#39;ve got this decoupled CMS brewing in my head, and wanted to jot down what I think would be a kind of cool method for generating URLs and URL redirects and making sure everything stays in sync without having to maintain a giant table of redirects (ala Drupal).</p>

<p>The basic scheme would look like this — <code>site.com/{item_type}/{item_id}/{item_slug}</code>. The type parameter could probably be optional, but it&#39;s there for now. An example URL could be <code>ignoredbydinoaurs.com/posts/123/the-totally-awesome-seo-juice</code>.</p>

<p>Of course, in whatever framework you&#39;re working in, those url segments are going to be broken down into tokens passed into whatever controller function is running the query. So your query would/could look like this in the controller</p>

<pre><code class="language-rb">
def show
	@post = Post.find(params[:id])
	if @post.slug != params[:slug]
	redirect_to &#34;/#{@post.type}/#{post.id}/#{@post.slug}&#34;, :status =&gt; :moved_permanently
	end
end

</code></pre>

<p>This has the advantage of never going out of sync with a redirect table, and never opening up the possibility of having an alias and a redirect create a loop. This happens often in Drupal, so with this scheme, you&#39;re only looking up based on an item&#39;s ID, which should never change. If somehow a URL has made it out in the the wild that is not the preferred URL, nothing breaks, it just gracefully performs a redirect to the proper URL.</p>

<p>The only significant portion of the URL is the ID, everything else is decoration or SEO juice.</p>

<hr>

<p>Somewhat off topic, but if you had a use cases where you were running multiple sites out of this CMS, and you had editors that frequently shared content, or wrote up each other&#39;s content for a sister site, then the primary key of of the article can stay consistent across different publications.</p>

<p>“How would different editors utilize each other&#39;s content in that case? Like, how would different pubs have the same article with a different summary on this instance from that instance?”</p>

<p>PostgreSQL schemas, that&#39;s how. I&#39;ll write that up, probably sometime in 2017.</p>

<hr>

<p><strong>2016, Django update</strong></p>

<p>This wasn&#39;t exactly hard to do, but I was surprised to find that nobody really wrote up how to simply issue a redirect like this in a Django view (controller to the rest of the world). Assuming that <code>get()</code> or <code>get_queryset()</code> was the answer, but I was wrong. <a href="https://docs.djangoproject.com/es/1.9/ref/class-based-views/generic-display/#detailview">This was the help piece of info</a> that I needed. Did I mention how much I love Django&#39;s docs?</p>

<p>This is the method that drives this very page.</p>

<pre><code class="language-python">
class DetailView(generic.DetailView):
	model = Post
	
	def dispatch(self, request, *args, **kwargs):
	object = get_object_or_404(Post, pk=self.kwargs[&#39;pk&#39;])
	if object.slug != self.kwargs[&#39;slug&#39;]:
	return redirect(object, permanent=True)
	# else, delegate up
	return super(DetailView, self).dispatch(request, *args, **kwargs)

</code></pre>

<p><a href="https://www.ignoredbydinosaurs.com/tag:generaldevelopment" class="hashtag"><span>#</span><span class="p-category">generaldevelopment</span></a> <a href="https://www.ignoredbydinosaurs.com/tag:rails" class="hashtag"><span>#</span><span class="p-category">rails</span></a> <a href="https://www.ignoredbydinosaurs.com/tag:django" class="hashtag"><span>#</span><span class="p-category">django</span></a></p>
]]></content:encoded>
      <guid>https://www.ignoredbydinosaurs.com/258-a-url-strategy</guid>
      <pubDate>Tue, 28 Apr 2015 00:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>