Let's assume you own a website or you want to build one and you want to add a blog to it. So you go to Google and google "How to add a blog to your website." After going through the results, you can't find a better option that enables you to add a blog to your site for free or without using WordPress.
A few weeks ago I found myself in this situation and as I went on doing my research, I discovered that you can use dev to API to display articles published there on your website without someone getting redirected to Dev To when they want to read the articles.
My website uses Django for the backend and for that reason, I googled "how to display dev to posts on your website using Django." I went through the results returned by the search but none gave me a solution to the problem I wanted to solve.
After days of trial and error trying to figure out how to do that, I was able to display dev to posts on my website.
Here is how I did it.
Set Up
First things first, make sure you have python installed in your system.
Installing Django
To install Django we will use Pipenv
which is used to manage virtual environments. You can install Pipenv to your system using this guide.
Let’s create a new directory and install Django. First, navigate to the Desktop, create a new directory Articles
, and enter it with cd
.
$ cd ~/Desktop
$ mkdir Articles
$ cd Articles
Now use Pipenv to install Django.
$ pipenv install django
Then create a virtual environment using pipenv shell
$ pipenv shell
You should now see parentheses around the name of your current directory on your command line which indicates the virtual environment is activated.
(Articles) $
Create a new Django project called Blog
with the following command. Don’t forget that period . at the end.
(Articles) $ django-admin startproject Blog .
Run the command below and then visit http://127.0.0.1:8000/. You should see Django welcome page.
(Articles) $ python manage.py runserver
Now it’s time to create our Django app. From the command line, quit the server with Control+c
. Then use the startapp
command followed by the name of our app, which will be posts
.
(Articles) $ python manage.py startapp posts
Open the settings.py
file and scroll down to INSTALLED_APPS
where you’ll see six built-in Django apps already there. Add our new posts
app at the bottom:
# Blog/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'posts', # new
]
Models, Views, URLs, Templates
1. Models
First, we will create a model for our project so that we can store the articles fetched by the Dev To API into a database.
Models.py
from django.db import models
import datetime
class Article(models.Model):
title = models.TextField(blank=True)
description = models.TextField(blank=True)
cover_image = models.TextField(blank=True)
article_body = models.TextField(blank=True)
published_at = models.DateTimeField(default=datetime.date.today, blank=True, null=True)
def __str__(self):
return self.title
Run migrations with the commands below
(Articles) $ python manage.py makemigrations
(Articles) $ python manage.py migrate
To register our model, open admin.py
and it should look like this.
Admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Article
class ArticleAdmin(admin.ModelAdmin):
list_display = ('id', 'title')
admin.site.register(Article, ArticleAdmin)
Then create a superuser in order to be able to login to the admin and view data stored in our database.
(Articles) $ python manage.py createsuperuser
2. views
Since we will be making requests to Dev To API, we will need to install requests
python library.
$ pipenv install requests
Now visit dev to API website and read about getting an API key together with various API endpoints.
Once on the website, scroll down and on your bottom left select authentification
to learn how to get an API key
.
Then below authentification
, select articles
. Scroll down the drop-down menu and select User's published articles
.
On your right, you can now see Request samples
.
Now this is how your views.py
file should look like.
views.py
from django.shortcuts import render
import requests
from .models import Article
def get_articles(request):
all_articles = {}
API_KEY = 'Your_API_KEY'
url = 'https://dev.to/api/articles/me/published'
headers = {'api-key': API_KEY}
response = requests.get(url, headers=headers)
data = response.json()
for i, item in enumerate (data):
article_data = Article(
title = data[i]['title'],
description = data[i]['description'],
cover_image = data[i]['cover_image'],
article_body = data[i]['body_markdown'],
published_at = data[i]['published_at']
)
article_data.save()
all_articles = Article.objects.all().order_by('-published_at').distinct('published_at')
return render (request, "blog.html", {"all_articles": all_articles})
In order to display Article Body
, we will need to create another view
. In this view
, we are querying article by id
.
def blogBody(request, id):
article = Article.objects.get(id = id)
return render (request, "blogBody.html", {"article": article})
Your views.py
file should now look like this.
from django.shortcuts import render
import requests
from .models import Article
def get_articles(request):
all_articles = {}
API_KEY = 'Your_API_KEY'
url = 'https://dev.to/api/articles/me/published'
headers = {'api-key': API_KEY}
response = requests.get(url, headers=headers)
data = response.json()
for i, item in enumerate (data):
article_data = Article(
title = data[i]['title'],
description = data[i]['description'],
cover_image = data[i]['cover_image'],
article_body = data[i]['body_markdown'],
published_at = data[i]['published_at']
)
article_data.save()
all_articles = Article.objects.all().order_by('-published_at').distinct('published_at')
return render (request, "blog.html", {"all_articles": all_articles})
def blogBody(request, id):
article = Article.objects.get(id = id)
return render (request, "blogBody.html", {"article": article})
3. URLs
Now we need to configure our urls
. Within the posts app
, create a new urls.py
file.
urls.py
from django.urls import path
from .views import get_articles, blogBody
urlpatterns = [
path("blog", blog, name="blog"),
path("article/<int:id>", blogBody, name="article"),
]
The last step is to update our Blog/urls.py
file. It’s common to have multiple apps within a single Django project, like pages here, and they each need their own dedicated URL path.
Update the existing Blog/urls.py
file as follows:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path("", include("posts.urls"))
]
4. Templates
Create a directory called templates
and an HTML file called blog.html
and blogBody.html
.
(Articles) $ mkdir templates
(Articles) $ touch templates/blog.html
(Articles) $ touch templates/blogBody.html
Next, we need to update Blog/settings.py
to tell Django the location of our new templates directory. This is a one-line change to the setting 'DIRS'
under TEMPLATES
.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #new
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Our blog.html
file should now look like this:
{% for article in get_articles %}
<img src="{{article.cover_image}}" alt="">
<h4>{{article.title}}</h4>
<p>{{article.description}}</p>
<a href="{% url 'article' article.id %}">Read More...</a>
{% endfor %}
Article Body
When we make the API
call, the article body is fetched as article markdown
. The markdown is received from the API as a string. This means it will look like the raw content you enter on DEV To, rather than the preview/published version (i.e. with all the markdown syntax like ## for headings).
To display it on your website as it appears on DEV To, you'll need to add an extra step to turn the string markdown into HTML. There are a lot of markdown parsing libraries that can do this for you but in this project, we will use a markdown parsing library for Django called Markdown
.
To use Markdown
we will need to install it into our project.
$ pipenv install markdown
We will create a custom template filter that uses Markdown
. Create a templatetags
directory within our posts app and then a markdown_extras.py
file.
(Articles) $ mkdir posts/templatetags
(Articles) $ touch posts/templatetags/markdown_extras.py
The file itself will import the markdown
package and use the fenced code block extension.
# posts/templatetags/markdown_extras.py
from django import template
from django.template.defaultfilters import stringfilter
import markdown as md
register = template.Library()
@register.filter()
@stringfilter
def markdown(value):
return md.markdown(value, extensions=['markdown.extensions.fenced_code'])
Now we load the custom filter into our template so that content written in Markdown will be outputted as HTML.
Our blogBody.html
file should now look like this:
{% load markdown_extras %}
<h4>{{article.title}}</h4>
<img src="{{article.cover_image}}" alt="">
<span>{{article.published_at }}</span>
<p>{{article.article_body | markdown | safe}}</p>
Conclusion
Articles should now appear on your website just like they appear on Dev To.
Hope you find this article helpful. All the best in your coding.
Top comments (3)
These were some of your earliest works in technical writing. Very simple and straight to the point. Very well done.
Thanks.
Now that I have the knowledge on how to do this, I just need to get the skill. I am new to website development and most of the steps in this, sadly went over my head. Maybe one day when I have more knowledge I can implement this. Even though I didn't follow the whole thing, it was still a well written tutorial.