Stephen Amedi Imbira
Posted on May 14, 2024
In the realm of Django development, models, views, URLs, and templates form the cornerstone of every project. These elements converge to sculpt a full-stack Python based web framework, meticulously adhering to the MTV design pattern. However, this project does not employ Django templates for the presentation layer. Instead, it uses Vue 3, a powerful JavaScript framework for building dynamic user interfaces. This innovative solution splits the roles of client and server, revolutionizing the traditional approach to web development.
Setting up Django
Installing Django with pipenv
Setting up Django involves installing it with pipenv, the preferred package management system for creating a virtual environment. To install Django with pipenv, simply run the following command at the shell:
pipenv install django
In addition to installing Django, you’ll also need to install the following packages: djangorestframework and djangocorsheaders. To do so, continue in your terminal or command prompt and execute the following commands.
pipenv install djangorestframework
pipenv install djangocorsheaders
Activate virtual environment
pipenv shell
Creating your first project
Django provides a command that allows you to create an initial project file structure. Run the following command in your shell prompt. Remember to add the dot at the end, so that Django can create the server files in the same folder.
django-admin startproject server .
To initialize the database migrations for your Django project, execute the following command in your terminal or command prompt: it ensures that your database schema aligns with your project’s models and configurations.
python manage.py migrate
To create a new Django app named "blog," navigate to your project directory in the terminal or command prompt and execute the following command:
python manage.py startapp blog
To create the blog data model in your Django project, you can define a model named Article in your models.py Here’s how you can do it:
from django.db import models
from django.contrib.auth.models import User
class Article(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
def __str__(self):
return self.title
In this model, we’ve defined an Article class that inherits from Django’s models.Model. It includes two fields: title field which is a character field with a maximum length of 200 characters, and body which is a text field to store the content of the article.
Activating the Application
To activate the newly created "blog" application, along with the third party apps we installed, navigate to your project's settings file (usually located at settings.py) and add blog to the INSTALLED_APPS list. Ensure that it follows the specified format, including third-party apps such as rest_framework and corsheaders. Here's how your INSTALLED_APPS list should look:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# Third party apps
'rest_framework',
'corsheaders',
# Local apps
'blog',
]
Creating and Applying Migrations
To create and apply migrations for your Django project, execute the following commands in your terminal or command prompt:
python manage.py makemigrations
python manage.py migrate
Create a superuser
To create a superuser for accessing the Django administration site, execute the following command in your terminal or command prompt:
python manage.py createsuperuser
This command will prompt you to enter a username, email (optional), and password for the superuser account. Once created, you can use these credentials to log in to the Django administration site and manage your blog application.
Django administration site
Now that the Blog model is synchronized with the database, we can establish a straightforward administration site to manage blog posts.
As depicted in the diagram, the Article model is prominently displayed within the admin site.
Let's proceed by adding two articles using the admin site.
Building List and Detail Views
These views define endpoints for listing all articles and retrieving a specific article. The article_list view fetches all articles from the database and serializes them. The article_detail view retrieves a single article based on its id.
from django.shortcuts import get_object_or_404
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Article
from .serializers import ArticleSerializer
@api_view()
def article_list(request):
all_posts = Article.objects.all()
serializer = ArticleSerializer(all_posts, many=True)
return Response(serializer.data)
@api_view()
def article_detail(request, id):
post = get_object_or_404(Article, id=id)
serializer = ArticleSerializer(post)
return Response(serializer.data)
Making sure the APIs are working
To verify that the APIs are functioning correctly, you can utilize django rest framework’s built-in UI.
Setting up the Vue.js
Installing Vue 3
To set up Vue.js for your project, begin by installing Vue 3 using npm. Execute the following command in your terminal or command prompt:
npm create vue@latest
During the installation process, make sure to select 'Yes' when prompted to add Vue Router. This will incorporate Vue Router into your Vue 3 project, enabling client-side routing for seamless navigation within your application.
cd frontend
npm install
To install Axios, a popular HTTP client for making requests in Vue.js applications, execute the following command in your terminal or command prompt:
npm install axios
In this main.js file, Axios is registered as $axios in the global properties of the Vue app. This allows Axios to be easily accessible from within Vue components using this.$axios. The app is then mounted to the DOM element with the ID app, completing the setup.
import './assets/main.css'
import './assets/main.scss'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import axios from 'axios'
const app = createApp(App)
app.config.globalProperties.$http = axios
app.use(router)
app.mount('#app')
*Fetching data and displaying API data with Vue.js
*
<template>
<div class="container-fluid">
<div class="container mt-6">
<article class="media box has-background-light" v-for="(post, index) in posts" :key="index">
<div class="media-content">
<div class="content">
<p>
<p class="title is-4">
<RouterLink :to="{ name: 'full', params: { id: post.id } }">{{ post.title }}</RouterLink>
</p>
{{ truncateWords(post.body, 30) }}
</p>
</div>
</div>
<div class="media-right">
<figure class="image is-128x128">
<img src="../assets/profile.jfif" alt="">
</figure>
</div>
</article>
</div>
</div>
</template>
<script>
export default {
data() {
return {
posts: []
}
},
methods: {
async getPosts() {
try {
const response = await this.$http.get('http://127.0.0.1:8000/articles/');
this.posts = response.data;
console.log(this.posts)
} catch (error) {
console.log(error)
}
},
truncateWords(text, limit) {
const words = text.split(' ');
if (words.length > limit) {
return words.slice(0, limit).join(' ') + '...';
}
return text;
}
},
created() {
this.getPosts();
},
}
</script>
Setting up the Vue Router
In this setup, Vue Router is configured to use the HTML5 history mode for routing. Two routes are defined: one for the home page (/) which corresponds to the ListView component, and another for viewing detailed articles (/articles/:id)which corresponds to the DetailedView component.
import { createRouter, createWebHistory } from 'vue-router'
import ListView from '../views/ListView.vue'
import DetailedView from '../views/DetailedView.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: ListView
},
{
path: '/articles/:id',
name: 'full',
component: DetailedView
}
]
})
export default router
Detailed
<template>
<div class="container">
<h1 class="title">{{ article.title }}</h1>
<p>{{ article.body }}</p>
</div>
</template>
<script>
export default {
data() {
return {
article: null
}
},
created() {
this.fetchArticle();
},
methods: {
async fetchArticle() {
try {
const id = this.$route.params.id;
const response = await this.$http.get(`http://127.0.0.1:8000/articles/${id}/`)
this.article = response.data;
} catch (error) {
console.log(error)
}
}
}
}
</script>
Posted on May 14, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.