10 Mar 2018

feedDjango community aggregator: Community blog posts

HOWTO: Working with Python, Unicode, and Arabic

When working with non-European languages such as Arabic and Chinese, a practical understanding of Unicode is necessary. My research group uses Java for larger applications, and although Java represents all strings in Unicode, it is often cumbersome to write small Java applications for the various data manipulation tasks that appear while preparing corpora for translation. Therefore, fluency in one of the dynamically-typed scripting languages can be immensely useful in this particular domain. I prefer Python for its intuitive Unicode support and minimalist syntax. This article provides sample Python code for several common use cases that require particular consideration of string encodings. Perl offers analogous capabilities, but Ruby's Unicode support is somewhat limited as of Ruby 1.9.

(Note that this document is valid for Python 2.5.x only; Python3k introduces numerous incompatibilities.)

Working with Strings

Python supports two methods of constructing Unicode strings. The unicode() built-in function constructs a string with a default encoding of utf-8. The u" shorthand notation is equivalent:

best = unicode('?????', encoding='utf-8')           #Preferred method
old = u'?????'                                  #Deprecated in Python3k

To convert between one encoding and another, use the string method encode():

ascii_string = 'My anglo-centric string...'
utf8_string = ascii_string.encode('utf-8')

#Concatenation works as expected
utf8_string = utf8_string + unicode('???? ??????', encoding='utf-8')

#print does not require additional parameters
print ascii_string
print utf8_string

#But this throws an exception
print utf8_string.encode('ascii')

Sometimes it is necessary to manipulate individual Unicode characters. This is particularly useful for non-printing characters like the right-to-left override (0x202E):

print unichr(1591)                  #0x0637 in the Unicode charts
print ord(u'?')
print unichr(ord(u'?'))         #unichr() and ord() are inversely related

Manipulating Files

The syntax for reading and writing Unicode files does not differ from that used for ASCII files. Opening Unicode files requires the codecs library, however:

IN_FILE = codecs.open('test.ar','r', encoding='utf-8')
OUT_FILE = codecs.open('out.ar', 'w', encoding='utf-8')

for line in IN_FILE:
    OUT_FILE.write(line.rstrip() + unicode('\n', encoding='utf-8'))


Python also supports Unicode files names. Simply pass in a Unicode string to the open() method. As a sanity check, you can discover your filesystem's default encoding by calling sys.getfilesystemencoding():

a = sys.getfilesystemencoding()
print "Filesystem encoding: " + a

arabic_filename = unicode('???_????', encoding='utf-8')
IN_FILE = codecs.open(arabic_filename, encoding='utf-8')

for line in IN_FILE:
    print line

Unicode Source Files

When strings exceed several characters-as they often do-it is better to write the Unicode literals into the source file. To force the Python interpreter to recognize the source code as utf-8, add a 'magic comment' to the first or second line of the source file:

# coding: utf-8
import sys

#Try this without the magic comment above and see what happens....
embedded_unicode = unicode('?????', encoding='utf-8')

print embedded_unicode

Regular Expressions

With the ability to embed Unicode literals into the source code, it is possible to write regular expressions for any natural language [2]. Simply indicate to the regex compiler that the pattern parameter is a

Unicode string:

TEST_FILE = codecs.open('test.ar','r', encoding='utf-8')

p = re.compile(unicode('^????', 'utf-8'), re.U)

for line in TEST_FILE:
    match = p.match(line)
    if match:
        print line.rstrip()
        print match.group().rstrip()


Unicode 5.1.0 book - The authoritative programmer's reference for Unicode. No need to memorize this one.

Unicode charts - Keep these within reach. The Arabic charts are especially useful for characters that do not appear on the keyboard.

This post was republished from http://www.spencegreen.com/

10 Mar 2018 6:00am GMT

08 Mar 2018

feedDjango community aggregator: Community blog posts

How Django URLs work with Regular Expressions

Let's better understand Django...

08 Mar 2018 7:52pm GMT

07 Mar 2018

feedDjango community aggregator: Community blog posts

Two new projects

Django and security are two of my favorite topics, and I think they go pretty well together. I've given a number of conference talks and tutorials on the theme of Django and security, and I'm one of the people on the receiving end of Django's security-reporting email address. But although I spend a lot of time thinking about security, and trying to improve the state of the world through code, and occasionally ranting on various ...

Read full entry

07 Mar 2018 7:49am GMT

Building a Modern Web Application with Django REST Framework and Vue: Building Views and REST API

Throughout this part of these tutorial series you will continue developing a CRUD (Create, Read, Update and Delete) application with a restful API back-end and a Vue front-end using Django, Django REST framework and Vue (with Axios as an HTTP client). In this part you'll specifically build the REST API and the front-end views to consume and display data from the API endpoints. You will also see how to integrate your Vue application with your Django back-end in production. As always you can find the source code of the demo project in this Github repository.

You can check the second article from this link


This article is composed of the following sections:

Building the REST API

Django REST framework is a powerful and easy to use package for building Web APIs.

Let's get started by building a simple REST API using Django REST framework.

Adding the Product Model

Django has a powerful ORM (Object Relational Mapper) that allows you to work with multiple database management systems without actually writing any SQL. All you need to do is to define models in Python classes and Django will take care of mapping Python classes to SQL queries.

The API is built around a simple product model so continuing with the project you've built in the previous part open the catalog/models.py file then add the following model

from django.db import models

class Product(models.Model):

    sku = models.CharField(max_length=13,help_text="Enter Stock Keeping Unit")    
    name = models.CharField(max_length=200, help_text="Enter product name")
    description = models.TextField(help_text="Enter product description")

    buyPrice = models.DecimalField(decimal_places=2, max_digits=20,help_text="Enter product price per unit")
    sellPrice = models.DecimalField(decimal_places=2, max_digits=20,help_text="Enter product price per unit")

    unit = models.CharField(max_length=10,help_text="Enter product unit")

    quantity = models.DecimalField(decimal_places=1, max_digits=20,help_text="Enter quantity")

    def get_absolute_url(self):
         Returns the url to access a particular instance of Product.
         return reverse('product-detail-view', args=[str(self.id)])

    def __str__(self):

        return self.sku

This is a Python class that extends the special Django class Model which is imported from the django.db.models built-in package. Every Django model needs to extends the Model class. You then specify the model fields using classes like CharField, TextField and DecimalField etc.

Now you need to migrate your database to add the new changes

python manage.py makemigrations
python manage.py migrate

Next let's add some seed data using a data migration

So first make an empty migration by running the following command:

python manage.py makemigrations catalog --empty

Next open your migration file in your app migrations folder (catalog/migrations) then create a function that will executed by the RunPython() method when you apply your migration

from django.db import migrations
from django.conf import settings

def create_data(apps, schema_editor):
    Product = apps.get_model('catalog', 'Product')
    Product(sku='sku1',name='Product 1', description='Product 1', buyPrice=100 , sellPrice=100,unit='kilogram', quantity=100).save()

class Migration(migrations.Migration):
    dependencies = [
        ('catalog', '0001_initial'),
    operations = [

You can then migrate your database to create the initial data

python manage.py migrate

Adding the Serializer Class

From Django REST framework docs here is the definition of a serializer

Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.

Create a serializers.py file inside your the catalog app folder then add the following code to create a serializer class for the product model

from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):

    class Meta:
        model = Product 
        fields = ('pk','sku', 'name', 'description', 'buyPrice','sellPrice','unit','quantity')

Adding the API Views

After adding the database model and the serializer class and also some seed data the next thing is to create the API views that will be responsible for creating, updating, deleting and fetching data from the database and send it back to users as JSON database when users request the appropriate API endpoint so go ahead and open the catalog/views.py file then start by adding the following imports

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Product 
from .serializers import * 

This code imports different classes from DRF package, paginator classes to add pagination and then the Product model and its serializer class.

Adding the Product List/Create API View

In your catalog/views.py add the following view function which can process either GET or POST requests to either return paginated list of products or create a product.

@api_view(['GET', 'POST'])
def product_list(request):
    List  products, or create a new product.
    if request.method == 'GET':
        data = []
        nextPage = 1
        previousPage = 1
        products = Product.objects.all()
        page = request.GET.get('page', 1)
        paginator = Paginator(products, 10)
            data = paginator.page(page)
        except PageNotAnInteger:
            data = paginator.page(1)
        except EmptyPage:
            data = paginator.page(paginator.num_pages)

        serializer = ProductSerializer(data,context={'request': request} ,many=True)
        if data.has_next():
            nextPage = data.next_page_number()
        if data.has_previous():
            previousPage = data.previous_page_number()

        return Response({'data': serializer.data , 'count': paginator.count, 'numpages' : paginator.num_pages, 'nextlink': '/api/products/?page=' + str(nextPage), 'prevlink': '/api/products/?page=' + str(previousPage)})

    elif request.method == 'POST':
        serializer = ProductSerializer(data=request.data)
        if serializer.is_valid():
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

This function first checks if it's a GET or POST request then preforms the processing based on the type of the request:

Adding the Product Detail API View

Now you need to add the view function that will be responsible for getting, updating or deleting a single product by id depending on the type of the HTTP request (GET, PUT or DELETE).

@api_view(['GET', 'PUT', 'DELETE'])
def product_detail(request, pk):
    Retrieve, update or delete a product instance.
        product = Product.objects.get(pk=pk)
    except Product.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = ProductSerializer(product,context={'request': request})
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = ProductSerializer(product, data=request.data,context={'request': request})
        if serializer.is_valid():
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        return Response(status=status.HTTP_204_NO_CONTENT)

This view method first checks if a product, with the primary key passed as a parameter, exists. If it does exist it returns a 404 response otherwise it checks for the request method:

Adding API Endpoints

Next you need to create the two API endpoints api/products/ for querying and creating products and api/products/<id> for displaying single product information, updating and deleting single products by their id.

Go ahead and open catalog/urls.py then add

from catalog import views

urlpatterns = [
    url(r'^api/products/$', views.product_list),
    url(r'^api/products/(?P<pk>[0-9]+)$', views.product_detail),


Creating the Service to Consume the API

Now that you have created the API you need to consume it from your app front-end built with Vue. You'll use the Axios HTTP client to make HTTP calls to the API.

For the sake of organizing the code you'll encapsulate all the code that communicates with the API in one single class that will be used from different views to make any calls to the API endpoints.

So inside vueapp/src create an http folder (or call it whatever you want) then create the APIService.js class

This class provides wrapper methods for the Axios get, post, put and delete methods. In each method the endpoint URL is constructed and an Authorization header is built with the format Bearer <TOKEN>. The token is retrieved from localhost using the static method getAuthToken() of AuthService.

The APIService.js class contains these methods

In APIService.js copy the following code

import axios from 'axios';
import AuthService from '../auth/AuthService';
const API_URL = 'http://localhost:8000';

export class APIService{


    /* The other methods go here */

This code imports axios and AuthService class then declares an API_URL constant pointing to the URL of the local Django server and finally declares and exports the APIService which contains different methods to interact with the Django API.

Let's now see the implementations of different methods of the APIService

Getting Products

Let's start with the getProducts() to query the API endpoint for available products. Copy the following code to your APIService.js file:

    getProducts() {
        const url = `${API_URL}/api/products/`;
        return axios.get(url, { headers: { Authorization: `Bearer ${AuthService.getAuthToken()}` }}).then(response => response.data);

The getProducts() method sends a GET request to the /api/products/ endpoint using axios.get() method with the Auth0 authorization header retrieved from the local storage.

Getting a Product by Id

Let's now see the implementation of the getProduct(pk) method for retrieving single products.

    getProduct(pk) {
        const url = `${API_URL}/api/products/${pk}`;
        return axios.get(url, { headers: { Authorization: `Bearer ${AuthService.getAuthToken()}` }}).then(response => response.data);

The getProduct(pk) method sends an authorized GET request to /api/products/<pk> endpoint for retrieving a single product by its id or primary key.

Getting Products by URL

The API you created returns links to access the previous and next pages of data so you need to add this method which retrieves the products for a specified page by its URL.

        const url = `${API_URL}${link}`;
        return axios.get(url, { headers: { Authorization: `Bearer ${AuthService.getAuthToken()}` }}).then(response => response.data);


Deleting a Product

Let's now add the function which handles calling the endpoint for deleting a single product

        const url = `${API_URL}/api/products/${product.pk}`;
        return axios.delete(url, { headers: { Authorization: `Bearer ${AuthService.getAuthToken()}` }});


The deleteProduct(product) sends a DELETE request to the /api/products/<pk> endpoint using the axios.delete() method.

Creating a Product

Next, let's add the method to create a product

        const url = `${API_URL}/api/products/`;
        const headers = {Authorization: `Bearer ${AuthService.getAuthToken()}`};
        return axios.post(url,product,{headers: headers});

The createProduct(product) function sends a POST request to the /api/products/ endpoint with an authorization token retrieved from the local storage using the axios.post() method.

Updating a Product

The last method is used for updating products

        const url = `${API_URL}/api/products/${product.pk}`;
        const headers = {Authorization: `Bearer ${AuthService.getAuthToken()}`};
        return axios.put(url,product,{headers: headers});

The updateProduct(product) sends a PUT request to the /api/products/<pk> endpoint with an authorization header using the axios.put() method.

Creating the Front End Views

Now it's time to create the front end views to display, create, update and delete products

The demo app you are going to build has the following views:

Building the App View

Let's start by adding the App.vue template. The generated Vue project already contains an App.vue file so simply update it to reflect the following template

    <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
      <a class="navbar-brand" href="#">Django - Auth0 - Vue</a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      <div class="collapse navbar-collapse" id="navbarCollapse">
        <ul class="navbar-nav mr-auto">

          <li class="nav-item">
          <a class="btn btn-primary" href="/">Home</a>
          <li class="nav-item">
          <a class="btn btn-primary" href="/product-list">Products</a>
          <li class="nav-item">
          <a class="btn btn-primary" href="/product-create">Create</a>

            class="btn btn-primary btn-margin"
              Log In

            class="btn btn-primary btn-margin"
              Log Out


    <div class="container">


This code a header styled with Bootstrap that contains links to different pages and button to login and logout then a <router-view> component which renders the matched component for the given path. See the docs for router-view.

You can notice that two variables (auth an instance of AuthService and authenticated a boolean variable that holds the state of the authentication) are bound to the router view component that will be passed to the other components.

The v-if directive is used to display the log in and log out buttons depending on the authenticated variable.

Next you need to add the JavaScript code for the App.vue component

import AuthService from './auth/AuthService'

const auth = new AuthService()

const { login, logout, authenticated, authNotifier } = auth

export default {
  name: 'app',
  data () {
    authNotifier.on('authChange', authState => {
      this.authenticated = authState.authenticated
    return {
  methods: {

In nutshell this code imports the AuthService and create an instance of it then adds the login and logout methods of the instance to the methods array so they become accessible in the template where you can bind them to the login and logout buttons.

Also this code watches the authentication state using the authNotifier object and sets the authenticated variable accordingly.

The authenticated and auth variables are returned from the data() method to become accessible from the template.

Also make sure to include Bootstrap 4 using the CSS @import

So download bootstrap 4 and unzip it in the assets folder then add a block with the following content

@import './assets/bootstrap.min.css';
body {
  min-height: 75rem;
  padding-top: 4.5rem;
  margin-left: 5px;

This is a screen shot of the header you should get

Adding the Home View

Next let's add the home view. Navigate inside the components folder then create and open the Home.vue file.

First copy the following template

    <main role="main">
      <div class="jumbotron">
        <h1>Django - Auth0 - Vue</h1>
        <p class="lead">This demo application uses Django and Django REST Framework for backend, Vue for the frontend and Auth0 for handling user's authentication</p>
        <a class="btn btn-lg btn-primary" href="" role="button">View tutorial</a>

    <h4 v-if="!authenticated">
      You are not logged in! Please <a class="btn btn-primary" @click="auth.login()">Log In</a> to continue.

If the user is not authenticated he will get the message You are not logged in! Please Login In with a button to be able to login (bound to the auth.login() method).

Aside from that this component displays a Bootstrap jumbotron with some information about the demo.

Next add the following JavaScript code in the same file

  export default {
    name: 'home',
    props: ['auth', 'authenticated'],

This component declares two props auth and authenticated which you have passed earlier from the parent component: <router-view :auth="auth" :authenticated="authenticated">.

This is what you should get at this point

After logging using Auth0 you'll get this

Adding the Product List View

Now let's create the view to display the paginated list of products fetched from the API endpoint. Go ahead and create the ProductList.vue file inside the components folder then open it.

Next copy the following code for the template part

<h1>Products ()</h1>
<table class="table table-bordered table-hover">
    <tr   v-for="product in products" @click="selectProduct(product)">
      <td> </td>
        <button class="btn btn-danger" @click="deleteProduct(product)"> X</button>
        <a class="btn btn-primary" v-bind:href="'/product-update/' + product.pk"> &#9998; </a>

<ul class="list-horizontal">
  <li><button class="btn btn-primary" @click="getPreviousPage()">Previous</button></li>
  <li v-for="page in pages">
    <a class="btn btn-primary" @click="getPage(page.link)"></a>
  <li><button class="btn btn-primary" @click="getNextPage()">Next</button></li>


<div class="card text-center" v-if="selectedProduct">
  <div class="card-header">
    # -- 
  <div class="card-block">
    <h4 class="card-title"></h4>
    <p class="card-text">

    <a class="btn btn-primary" v-bind:href="'/product-update/' + selectedProduct.pk"> &#9998; </a>
    <button class="btn btn-danger" @click="deleteProduct(selectedProduct)"> X</button>



This template displays the table of products and details about a selected product below the table.

Next you need to define different methods and variables used in this template so in the same file add the following code

import {APIService} from '../http/APIService';
import Loading from './Loading';
const API_URL = 'http://localhost:8000';
const apiService = new APIService();

export default {
  name: 'ProductList',
  data() {
    return {
      products: [],
      pages : [],
      loading: false,
  methods: {

      this.loading = true;    
      apiService.getProducts().then((page) => {
        this.products = page.data;
        this.numberOfProducts = page.count;
        this.numberOfPages = page.numpages;
        this.nextPageURL = page.nextlink;
        this.previousPageURL = page.prevlink;
          for(var i = 1 ; i <= this.numberOfPages ; i++)
            const link = `/api/products/?page=${i}`;
            this.pages.push({pageNumber: i , link: link})
        this.loading = false;
      this.loading = true;  
      apiService.getProductsByURL(link).then((page) => {
        this.products = page.data;
        this.nextPageURL = page.nextlink;
        this.previousPageURL = page.prevlink;
        this.loading = false;
      console.log('next' + this.nextPageURL);
      this.loading = true;  
      apiService.getProductsByURL(this.nextPageURL).then((page) => {
        this.products = page.data;
        this.nextPageURL = page.nextlink;
        this.previousPageURL = page.prevlink;
        this.loading = false;

      this.loading = true;  
      apiService.getProductsByURL(this.previousPageURL).then((page) => {
        this.products = page.data;
        this.nextPageURL = page.nextlink;
        this.previousPageURL = page.prevlink;
        this.loading = false;

      console.log("deleting product: " + JSON.stringify(product))
        if(r.status === 204)
          alert("Product deleted");

      this.selectedProduct = product;
  mounted() {



In nutshell this code creates an instance of the APIService class then wraps different methods to get and delete products and also to get previous and next pages of data.

This is a screen shot of what you should get

Adding the Product Create/Update View

This view is used to create and also update products by id so create a ProductCreate.vue file then open it and add the following template


        <div id="container" class="container">

            <div class="row">

                <div class="col-sm-8 offset-sm-2">
                <div class="alert alert-warning" v-show="showCreateMessage"  >
                  <button type="button" class="close" @click="hideMessage()">X</button>
                  <strong>Product successfully created!</strong>
                <div class="alert alert-warning" v-show="showUpdateMessage"  >
                  <button type="button" class="close" @click="hideMessage()">X</button>
                  <strong>Product successfully updated!</strong>

                <div class="alert alert-warning" v-show="showError"  >
                  <button type="button" class="close" @click="hideMessage()">X</button>
                    <h1>Create a Product</h1>
                    <div class="info-form">
                        <div class="form-group">
                          <label for="sku">Product SKU</label>
                          <input v-model="product.sku" type="text" class="form-control" id="sku" aria-describedby="skuHelp" placeholder="Enter SKU">
                          <small id="skuHelp" class="form-text text-muted">Enter your product's SKU</small>
                          <label for="name">Product Name</label>
                          <input v-model="product.name" type="text" class="form-control" id="name" aria-describedby="nameHelp" placeholder="Enter name">
                          <small id="nameHelp" class="form-text text-muted">Enter your product's name</small>

                          <label for="description">Product Description</label>
                          <textarea v-model="product.description" class="form-control" id="description" aria-describedby="descHelp" placeholder="Enter description"></textarea>
                          <small id="descHelp" class="form-text text-muted">Enter your product's description</small>

                          <label for="buyPrice">Product Cost</label>
                          <input v-model="product.buyPrice" type="text" class="form-control" id="buyPrice" aria-describedby="buyPriceHelp" placeholder="Enter the buying price">
                          <small id="buyPriceHelp" class="form-text text-muted">Enter your product's cost</small>

                          <label for="sellPrice">Product Price</label>
                          <input v-model="product.sellPrice" type="text" class="form-control" id="sellPrice" aria-describedby="sellPriceHelp" placeholder="Enter name">
                          <small id="sellPriceHelp" class="form-text text-muted">Enter your product's selling price</small>

                          <label for="unit">Product Unit</label>
                          <input v-model="product.unit" type="text" class="form-control" id="unit" aria-describedby="unitHelp" placeholder="Enter unit">
                          <small id="unitHelp" class="form-text text-muted">Enter your product's unit</small>

                          <label for="quantity">Product Quantity</label>
                          <input v-model="product.quantity" type="text" class="form-control" id="quantity" aria-describedby="quantityHelp" placeholder="Enter quantity">
                          <small id="quantityHelp" class="form-text text-muted">Enter your product's quantity</small>

                       <button class="btn btn-primary" v-if="!this.product.pk" @click="createProduct()" ><span v-if="!creating">Create</span><span v-if="creating">Creating... Please wait </span></button>
                       <button class="btn btn-primary" v-if="this.product.pk" @click="updateProduct()" ><span v-if="!updating">Update</span><span v-if="updating">Updating... Please wait </span></button>
                       <button class="btn btn-primary"  @click="newProduct()" >New..</button>



Next you need to add this code in the same file:

import {APIService} from '../http/APIService';

const apiService = new APIService();

export default {
  name: 'ProductCreate',
  components: {
  data() {
    return {
      showCreateMessage: false,
      showUpdateMessage: false,
      showError: false,
      product: {},
      products: '',
      creating: false,
      updating: false
  methods: {
      this.showCreateMessage = false;
      this.showUpdateMessage = false;
      this.showError = false;
      this.creating = true;
          if(result.status === 201){
            this.product = result.data;
            this.showCreateMessage = true;
          this.creating = false;          
        this.showError = true;
        this.creating = false;
      this.updating = true;
          if(result.status === 200){
            this.showUpdateMessage = true;

        this.showError = true;
        this.updating = false;
      this.product = {};

  mounted() {

        this.product = product;

This is a screen shot of what you should get

Adding the Callback View

In the previous parts you used the App.vue as the callback view for Auth0 now let's make a callback view which has the only task of processing the Auth0 response when the users authenticates via Auth0. Go ahead and create a Callback.vue component inside the components folder, next open it and add the following template

  <div class="spinner">
    <img src="../assets/loading.svg" alt="loading..."/>

If you put a loading.svg image inside your assets folder otherwise the loading... message will be shown.

Next add the following JavaScript code inside the same file

  export default {
    name: 'callback',
    props: ['auth'],
    data () {
      return {}

So this component declares an auth prop which will be passed from the router view then in the data() method calls the the handleAuthentication() method of auth (instance of AuthService) to process the callback result passed from Auth0 and stores the authentication token in the local storage.

Just like you did in the previous part you need to change your callback URL in Auth0 dashboard to point to http://localhost:8000/callback

Adding Routing with The Vue Router

After creating the necessary components let's add routing to the application. Go ahead and open the src/router/index.js file then add the following routes

/* other imports */
import ProductList from '@/components/ProductList'
import ProductCreate from '@/components/ProductCreate'
import Callback from '@/components/Callback'
import Home from '@/components/Home'
/* other imports */

const routes = [
    path: '/',
    name: 'Home',
    component: Home
    path: '/product-list',
    name: 'ProductList',
    component: ProductList
    path: '/product-create',
    name: 'ProductCreate',
    component: ProductCreate
    path: '/product-update/:pk',
    name: 'ProductUpdate',
    component: ProductCreate
    path: '/callback',
    name: 'Callback',
    component: Callback
const router = new Router({
  mode: 'history',

In modern browsers you can use HTML5 History API for routing client side applications without using URL hashes. The Vue router supports this mode by adding mode: 'history'.

The router index.js file imports all the components that you want to use for your application and exports an array of routes. Each route is a JavaScript object may have some or all of these properties: the route name, the path, a meta object and the component to navigate to when the path is matched.

Adding the Authentication Guard

Certain routes need to be protected from users which don't have passed Auth0 authentication.

The Vue router provides a way to add meta data to each route where you can any meta data to be used for some task. In this example you'll add a meta field to mark the route as requiring authentication.

    path: '/product-list',
    name: 'ProductList',
    component: ProductList,
    meta: { requiresAuth : true }
    path: '/product-create',
    name: 'ProductCreate',
    component: ProductCreate,
    meta: { requiresAuth : true }    

After adding the requiresAuth meta tag you need to use navigation guards to check if the user is allowed to access a particular route i.e if he's authenticated . So you need to add the global guard router.beforeEach()

router.beforeEach((to, from, next) => {

Before navigating to each route this code checks if the route has a requiresAuth meta field then use the AuthService.authenticated() method to check if the user is authenticated and redirects to / if it's not the case.

Getting Ready for Production

In the previous part you have seen how you can integrate Django and Vue in development phase where you can have two development servers (Django and Vue). In this section you will learn how integrate Django with Vue in production.

So in vueapp/build/webpack.prod.conf.js import webpack-bundle-tracker

const BundleTracker = require('webpack-bundle-tracker')

Then add BundleTracker to plugins

   plugins: [
    new BundleTracker({filename: '../webpack-stats-prod.json'})

This tells BundleTracker to generate webpack-stats-prod.json in the root folder.

In vueapp/config/index.js change static to assets (because commonly Django uses the /static/ URL for serving static files so you don't want to have URLs with /static/static/ paths). You also need to set the assets public path to /static/ so Webpack can generate URLs because Django serves static files over the /static/ URL.

build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),

    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'assets', 
    assetsPublicPath: '/static/',

Run the following command for generating the build files

npm run build

You will get a vueapp/dist folder that contains the build files.

Next in settings.py add

    os.path.join(BASE_DIR, 'vueapp/dist'),

STATIC_ROOT = os.path.join(BASE_DIR, 'public')

STATICFILES_DIRS contains folders where Django can find static files. These folders will be later copied to where STATIC_ROOT points after collecting the static files using the collectstatic command

So go ahead and run this command to collect all static files in the project and put them in the public folder

python manage.py collectstatic

A public folder will be created and all static files will be copied there.

In production Webpack will produce many chunks of your bundle for performance reasons so you'll need to change your Django template to include all the chunks

Open catalog/templates/index.html then update the template like the following

{% load render_bundle from webpack_loader %}

<html  lang="en">
<meta  charset="UTF-8">
<title>Django - Auth0 - Vue</title>
{% render_bundle 'app' 'css' %}

<div  id=app>

{% render_bundle 'manifest' %}
{% render_bundle 'vendor' %}
{% render_bundle 'app' 'js' %}

You can try if that works for you using the Django server without the need to deploy to a production server. On e difference from the development setup is that you don't need to run the Vue dev server since you have the built files of your front-end app served by Django.


You have reached the final of these series in which you have created a CRUD application with Django, Django REST framework and Vue. I hope you have enjoyed and thanks for reading!

07 Mar 2018 6:00am GMT

Building Modern Applications with Django, Vue.js and Auth0: Part 1

I originally created this tutorial series for Auth0 blog and are published here with the permission from the technical author at Auth0

Throughout this series, you'll be using Django, Django REST framework, and Vue.js to develop an application with a REST API back-end and a Vue.js front-end. The API will be consumed by the Vue.js front-end with the help of the Axios client library and JWT authentication will be handled by Auth0.

You are going to start by installing all the project's requirements, then you will bootstrap the Django and the Vue.js sub-projects.

You can find the final source code of the demo project that you will create in this GitHub repository.


This article is composed of the following sections:

Introduction to Python and Django

Python is a general-purpose programming language and it's among the most popular programming languages in the world. It's readable, efficient, and easy to learn. Python is also a portable language available for major operating systems such as Linux, Windows, and Mac.

For web developers, Python has many great tools and frameworks that make developers more productive and able to build prototypes in no time. The most popular framework for web development in the Python landscape is Django. Django is advertised as the framework for perfectionists with tight deadlines because of its ability to allow developers to quickly build prototypes.

Django uses the power of Python to offer developers a great set of features such as class-based views and a powerful ORM that you can use to model your database requirements without writing any single line of SQL. The Django ORM abstracts away all the complexities of working with databases and, most importantly, doesn't intimidate you when your client has not decided yet on the database system to use. You can start developing using an SQLite database (which doesn't need any special installation) then you can switch to the right database system later on when your client has settled on the right RDBMS (Relational Database Management System) to use.

Django also comes with a powerful migration system that allows you to migrate your database safely and without losing your data when you make changes to the database structure later on.

Another advantage of using Django is that it has a big and an evolving community. This community has created open source packages for common web development problems, so you don't need to reinvent the wheel when building your project.

Django has an excellent and complete documentation of all the features of the framework supplemented by a set of tutorials created by the community.

Django is also suitable for beginners and you don't have to be an expert in every feature of the framework to start building your web application.

Introduction to Vue.js and Vue.js Features

Vue.js is a progressive framework for building user interfaces with JavaScript. You can use Vue.js in the view layer of your application or you can use it to build Single Page Applications (SPAs) by combining it with some other front-end tools.

Vue.js took the best of both Angular.js and React into one library. For example, just like React, Vue.js uses a virtual DOM and a component-based approach. It also uses similar syntax to the Angular.js directives (e.g. v-if and v-for)

Vue.js has many features, such as:

Bootstrapping the Back-End Project

Before you can create the back-end project, you need to install some requirements on your development machine. For Django, you need to have Python 3, PIP, and venv installed.

Please note that you don't need to install a full-fledged database management system to develop with Django. You can use an SQLite database which allows you to have a file-based database that doesn't require any special installation.

Installing the Requirements

Let's start with Python 3. Chances are that you already have Python 3 installed on your machine. If not, then the process is simple. You just need to head over to the official downloads page and pick the installer for your operating system.

You can check if you have Python 3 installed by running the following command from your terminal or command prompt:

python3 --version

The venv module (part of the Python 3 standard library) allows you to create lightweight virtual environments for your projects. This allows you to have an isolated environments for each Python project (i.e. dependencies are isolated for each project and from the system-wide packages).

Setting up an isolated environment provides you with more control over the installed Python packages. You can have different versions of the same package without having to worry about any conflicts, which allows you to work with different Python projects with different package versions. Also, since each environment can have its own Python binary, this allows you to create various environments with different Python versions.

Once you create a virtual environment, venv will take care of installing the latest Python binary.

Next, you need to install pip, a package manager for Python that, by default, installs packages from the Python Package Index (PyPI).

You can verify if pip is installed on your development machine by running the following command:

# pip or pip3, depending on the environment
pip --version

You should have pip installed if you have installed Python using the official python.org installer (or via Homebrew in MAC). Also, if you are inside a venv environment, pip is already installed. For Linux, you may need to install it separately. If that's your environment, take a look at this guide and this page.

Creating a Virtual Environment

Once you have all the back-end requirements installed, you will have to create a virtual environment for installing your project's dependencies. Head back to your terminal and run the following commands:

# create a directory to your project
mkdir django-vue

# move the cursor to it
cd django-vue

# initialize a virtual env on it
python3 -m venv ./env

Next, you need to activate the virtual environment using source:

source ./env/bin/activate

Bootstrapping Django

You can now install Django using pip:

pip install django

Make sure you are inside the django-vue folder:

cd django-vue

The next step is to create the Django project using this command:

django-admin startproject djangovue 

Now, navigate inside your Django project and execute the following commands to create the first Django application (You can name it catalog or whatever you want):

cd djangovue
python manage.py startapp catalog

You also need to add this app to the list of installed apps. Open your settings.py file and add the app:


This is how the directory structure looks like at this point

django vue project structure

You can then migrate your database and start the development server:

python manage.py migrate
python manage.py runserver

If you navigate to in a web browser, you will see the following homepage:

Django starter page

Bootstrapping the Front-end Project

Vue.js has a CLI utility that allows developers to quickly generate SPAs. The CLI offers pre-configured build setups for a modern frontend workflow and takes only a few minutes to scaffold a basic project boilerplate. This boilerplate is shipped with features such as hot-reloading, lint-on-save, and production-ready builds.

Before you can install the Vue.js CLI, you need to have a development environment with Node.js 6.x or newer and NPM version 3 or newer. You can install both of them by heading to the official Node.js website and download the right installer for your operating system. For development machines, it's recommended to use NVM.

Next, head over to your terminal or command prompt and run the following command:

npm install -g vue-cli

You may need to add sudo to the NPM command to install commands globally depending on your NPM configuration.

After installing the Vue.js CLI, you will use it to generate a new Vue.js application based on the Webpack template. Inside the Django project's root, run the following command:

# initialize Vue.js with the Webpack template
vue init webpack frontend

Vue.js will ask a bunch of questions while creating your project. You can answer them as follows:

Then, to run the initial Vue.js project, you can run the following code:

# change working directory to the front-end
cd frontend

# run the NPM dev script
npm run dev

After that, you should be able to visit the Vue.js application in your browser by navigating to

Vue.js basic application

This is how the project directory structure looks like at this point

django vue directory structure

Introduction to JWT

JWT stands for JSON Web Token and it's simply a JSON (JavaScript Object Notation) object that contains claims. Here it is the official definition in the RFC 7519:

JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties. The claims in a JWT are encoded as a JSON object that is used as the payload of a JSON Web Signature (JWS) structure or as the plaintext of a JSON Web Encryption (JWE) structure, enabling the claims to be digitally signed or integrity protected with a Message Authentication Code (MAC) and/or encrypted.

JWTs are composed of three parts: a header, a payload, and a signature. The header contains information such as the algorithm used while signing the payload and the header (e.g RS256) and the payload holds the claims. To learn more about JWTs, take a look at this reference.

Creating an Auth0 Resource/API

Before you can use Auth0 authentication with your application, you first need to create an Auth0 account. If you haven't so yet, sign up for a free account now. After that, head over to the API section of the Auth0 dashboard and click on the CREATE API button.

You'll be presented with a form to fill in your API details: the name, the identifier, and the signing algorithm.

Auth0 Create API Form

You can use the following properties while filling this form:

After that, click on the Create button. You'll be taken to a page where you can further customize your API settings.

That's it! You are now ready to integrate your Django application with Auth0

Integrating Django with Auth0

In this section, you will see how to secure the Django REST API with Auth0.

In the next part, you will build the API, but before that, you will add JWT authentication to your back-end using Auth0.

For this reason, you will need to install the Django REST framework. You will also need to install the djangorestframework-jwt package for handling JWT authentication. You will set up djangorestframework-jwt to use Auth0 for signing the JWT tokens.

To do that, head back to your terminal, make sure the virtual environment we previously created is activated, and then run the following commands in the project root to install all packages using pip:

pip install djangorestframework
pip install djangorestframework-jwt
pip install cryptography
pip install python-jose

You may need to install python3-dev if you get problems while installing the cryptography package.

Next, you'll need to add these packages to the list of installed apps in settings.py


You will also need to add the REST_FRAMEWORK application definition to settings.py:


Next, make sure to import the following dependencies in your settings.py file:

import json
from six.moves.urllib import request
from cryptography.x509 import load_pem_x509_certificate
from cryptography.hazmat.backends import default_backend

Then, add the following code at the end of this file:


    jsonurl = request.urlopen('https://' + AUTH0_DOMAIN + '/.well-known/jwks.json')
    jwks = json.loads(jsonurl.read().decode('utf-8'))
    cert = '-----BEGIN CERTIFICATE-----\n' + jwks['keys'][0]['x5c'][0] + '\n-----END CERTIFICATE-----'
    certificate = load_pem_x509_certificate(cert.encode('utf-8'), default_backend())
    PUBLIC_KEY = certificate.public_key()
    JWT_ISSUER = 'https://' + AUTH0_DOMAIN + '/'

def jwt_get_username_from_payload_handler(payload):
    return 'auth0user'

    'JWT_PAYLOAD_GET_USERNAME_HANDLER': jwt_get_username_from_payload_handler,
    'JWT_ALGORITHM': 'RS256',

Make sure to replace <YOUR_AUTH0_DOMAIN> with your own Auth0 domain and <YOUR_API_IDENTIFIER> with the identifier used while creating the Auth0 API.

The public key is retrieved from https://YOUR_AUTH0_DOMAIN/.well-known/jwks.json using the request.urlopen() method. This key is then assigned to PUBLIC_KEY in JWT_AUTH (the settings object for djangorestframework-jwt).

JWT_ISSUER is your Auth0 domain name prefixed by https.

JWT_ALGORITHM needs to be set to RS256. That means that you also need to make sure your Auth0 API is using RS256.

The JWT_AUTH_HEADER_PREFIX is set to Bearer. This is the default prefix used by most frameworks (djangorestframework-jwt uses a JWT prefix by default).

You also have set JWT_PAYLOAD_GET_USERNAME_HANDLER to a custom method. This tells djangorestframework-jwt to use your custom method in order to map the username from the access_token payload to the Django user.

For most cases, you don't need to store users in your database since Auth0 handles all of that for you including advanced features such as profiles. You can use a custom function that checks if a general (can be fake) user that you create exists and map it to all Auth0 users.

To do that, head over to your application and create a user with any valid username such as auth0user. You can do that through Django admin interface or in a migration by adding the following code:

# create an empty data migration
python manage.py makemigrations --empty catalog

This will generate the catalog/migrations/0001_initial.py file. In this file, you can replace the content with the following code:

from django.db import migrations
from django.conf import settings

def create_data(apps, schema_editor):
    User = apps.get_model(settings.AUTH_USER_MODEL)
    user = User(pk=1, username="auth0user", is_active=True , email="admin@techiediaries.com")

class Migration(migrations.Migration):
    dependencies = [
    operations = [

For more information about migrations, see the official docs.

Next, just run migrate to create your initial data:

python manage.py migrate

This is the custom method that maps the JWT payload with the auth0user user:

def jwt_get_username_from_payload_handler(payload):
    return 'auth0user'

Please, note that you can return the username of any existing user in the database because you are not going to use this for anything besides the sole purpose of letting djangorestframework-jwt successfully authenticate the user.

Adding Django Views

To make sure the JWT authentication via Auth0 is working, you can add these two view functions in catalog/views.py:

from rest_framework.decorators import api_view
from django.http import HttpResponse

def public(request):
    return HttpResponse("You don't need to be authenticated to see this")

def private(request):
    return HttpResponse("You should not see this message if not authenticated!")

Also, make sure to create the corresponding URLs in urls.py. You can replace the whole contents of this file with this:

from django.conf.urls import url
from catalog import views

urlpatterns = [
    url(r'^api/public/', views.public),
    url(r'^api/private/', views.private)

If you rerun your Django project now (python manage.py runserver), you will have access only to the URL. The other one (/api/private/) will need an access token to be accessed.

Enabling CORS on Django

As you are going to create a Vue.js application to consume the Django endpoints, you will need to enable CORS on your Django project. To do that, you can install the django-cors-headers utility as follows:

pip install django-cors-headers

After that, you have to add this utility to your installed apps in the settings.py file:

    # ...

Then, you have to add the CorsMiddleware in this same file:

    # ...

The last thing you will need to do is to configure what origins will be accepted in your Django application:


You can add this configuration as the last item in the settings.py file.

Integrating Auth0 with The Vue.js Front-end

In this section, you will see how you can add Auth0 authentication to your front-end Vue.js application. You will also add a button to use the access token, retrieved from Auth0, to allow users to fetch the message from the /api/private/ endpoint.

Creating an Auth0 Client

To represent your Vue.js front-end application on Auth0, you will need to create an Auth0 client. To do that, go to your Auth0 dashboard and click on the New Client button.

You will be presented with a page where you can enter the name of the client and the type of the client. You can fill the name of the application as Django Vue.js App and choose the Single Page Web Applications type.

Creating an Auth0 Client

After filling this form, click on the Create button. This will redirect you to a page where you can find the Settings tab.

Configuring the Callback URL

You will need to whitelist the callback URL for your app (http://localhost:8080/) in the Allowed Callback URLs field of your new Auth0 client. This can be done in the Settings tab. In this tab, find the field mentioned and add http://localhost:8080/ to it. Then click on the Save button.

Creating the Authentication Service

Now. you will focus on integrating Auth0 in your Vue.js application. To do that, you will have to install the auth0.js and the eventemitter3 libraries:

# change directory to frontend
cd frontend

# install dependencies
npm install --save auth0-js
npm install --save eventemitter3

You also need to install Axios to send AJAX requests to the Django back-end:

npm install --save axios

After installing these three dependencies, create a new file under ./frontend/src/auth/. You will call this file as AuthService.js and add the following code:

import auth0 from 'auth0-js'
import EventEmitter from 'eventemitter3'
import router from './../router'

export default class AuthService {
  authenticated = this.isAuthenticated();
  authNotifier = new EventEmitter();

  constructor () {
    this.login = this.login.bind(this)
    this.setSession = this.setSession.bind(this)
    this.logout = this.logout.bind(this)
    this.isAuthenticated = this.isAuthenticated.bind(this)
    this.handleAuthentication = this.handleAuthentication.bind(this)

  // create an instance of auth0.WebAuth with your
  // API and Client credentials
  auth0 = new auth0.WebAuth({
    domain: '<YOUR_AUTH0_DOMAIN>',
    clientID: '<YOUR_CLIENT_ID>',
    redirectUri: '<YOUR_CALLBACK_URL>',
    audience: '<YOUR_AUDIENCE>',
    responseType: 'token id_token',
    scope: 'openid profile'

  // this method calls the authorize() method
  // which triggers the Auth0 login page
  login () {

  // this method calls the parseHash() method of Auth0
  // to get authentication information from the callback URL
  handleAuthentication () {
    this.auth0.parseHash((err, authResult) => {
      if (authResult && authResult.accessToken && authResult.idToken) {
      } else if (err) {
        alert(`Error: ${err.error}. Check the console for further details.`)

  // stores the user's access_token, id_token, and a time at
  // which the access_token will expire in the local storage
  setSession (authResult) {
    // Set the time that the access token will expire at
    let expiresAt = JSON.stringify(
      authResult.expiresIn * 1000 + new Date().getTime()
    localStorage.setItem('access_token', authResult.accessToken)
    localStorage.setItem('id_token', authResult.idToken)
    localStorage.setItem('expires_at', expiresAt)
    this.authNotifier.emit('authChange', {authenticated: true})

  // remove the access and ID tokens from the
  // local storage and emits the authChange event
  logout () {
    this.authNotifier.emit('authChange', false)
    // navigate to the home route

  // checks if the user is authenticated
  isAuthenticated () {
    // Check whether the current time is past the
    // access token's expiry time
    let expiresAt = JSON.parse(localStorage.getItem('expires_at'))
    return new Date().getTime() < expiresAt

  // a static method to get the access token
  static getAuthToken () {
    return localStorage.getItem('access_token')

  // a method to get the User profile
  getUserProfile (cb) {
    const accessToken = localStorage.getItem('access_token')
    if (accessToken) return this.auth0.client.userInfo(accessToken, cb)
    else return null

You will need to replace <YOUR_AUTH0_DOMAIN>, <YOUR_CLIENT_ID>, <YOUR_CALLBACK_URL> ('http://localhost:8080'), and <YOUR_AUDIENCE> with the values from your client and API settings. The audience property refers to the identifier of your Auth0 API (i.e. if you followed the instructions, it will be http://djangovuejs.digituz.com.br).

Creating the Homepage

Now, you are going to refactor your Vue.js homepage to allow users to authenticate via Auth0 and to fetch public and private messages. To do that, open ./frontend/src/App.vue and replace the <template> code with this:

      class="btn btn-primary btn-margin"
      Log In

      class="btn btn-primary btn-margin"
      Call Private

      class="btn btn-primary btn-margin"
      Log Out

Creating the Methods

Still in your ./frontend/src/App.vue, replace the <script> tag with this:

import AuthService from './auth/AuthService'
import axios from 'axios'

const API_URL = 'http://localhost:8000'

This imports the AuthService from ./auth/AuthService and the axios library. After that, it declares the API_URL constant which holds the URL of the back-end server.

After the API_URL constant, create an instance of AuthService:

const auth = new AuthService()

Then, below the auth definition, start defining the app component:

export default {
  name: 'app',
  data () {
    this.authenticated = false

    auth.authNotifier.on('authChange', authState => {
      this.authenticated = authState.authenticated

    return {
      authenticated: false,
      message: ''

In this code, you are listening for the authChange event emitted by AuthService when the authentication state changes. You then assign the result to the authenticated variable. You also set the message variable to be empty. This variable will hold the response from your protected endpoint.

The last thing you need to do is to define the methods property of the app component:

export default {
  // name: 'app',
  // data () { ... },
  methods: {
    // this method calls the AuthService login() method
    login () {
    handleAuthentication () {
    logout () {
    privateMessage () {
      const url = `${API_URL}/api/private/`
      return axios.get(url, {headers: {Authorization: `Bearer ${AuthService.getAuthToken()}`}}).then((response) => {
        this.message = response.data || ''

The login(), handleAuthentication(), and logout() methods are simply wrappers for the corresponding methods in AuthService.

In the private() method, you are now using the axios.get() method to send a GET request to http://localhost:8000/api/private/. Since this endpoint is protected by Auth0, you also added an Authorization header. The access token is retrieved from the local storage using AuthService.getAuthToken() method.

Testing the Django, Vue.js, and Auth0 Integration

Now that everything is correctly configured, you can test the integration among Django, Vue.js, and Auth0. To do that, go back to the root directory of your project and run the following commands:

# run Django in the background
python manage.py runserver &

# move to the frontend directory
cd frontend

# run Vue.js in the background &
npm run dev &

After running both the back-end and the front-end projects, you can head to the Vue.js homepage (http://localhost:8080/) to test it.

In the homepage, you will see the Log In button. Clicking on it will redirect you to the Auth0 login page.

Auth0 login page

After authenticating, you will be redirected to your Vue.js application, where the Call Private and the Log Out buttons will appear. Clicking on the Call Private button will issue a GET request to the Django framework, alongside with an access token, and will fetch the secured message.

Django Vue

Conclusion and Next Steps

In this article, you have bootstrapped both the Django back-end project and the Vue.js front-end application. You have also added JWT authentication to your back-end using Auth0. In the next part, you will see how to create the REST API using Django REST framework and then how to consume it from the Vue.js front-end using Axios. You will also see how to create our project front-end views.

You can find the source code for this part in this Github repository(master branch)

These are some screenshots from the demo project we are going to continue building in the next parts:

The final Django + Vue.js application

Stay tuned!

07 Mar 2018 6:00am GMT

06 Mar 2018

feedDjango community aggregator: Community blog posts

Django REST Framework Read & Write Serializers

Django REST Framework (DRF) is a terrific tool for creating very flexible REST APIs. It has a lot of built-in features like pagination, search, filters, throttling, and many other things developers usually don't like to worry about. And it also lets you easily customize everything so you can make your API work the way you want. There are many gene

06 Mar 2018 3:04pm GMT

28 Feb 2018

feedDjango community aggregator: Community blog posts

csso and django-pipeline

This is a quick-and-dirty how-to on how to use csso to handle the minification/compression of CSS in django-pipeline.

First create a file called compressors.py somewhere in your project. Make it something like this:

import subprocess
from pipeline.compressors import CompressorBase
from django.conf import settings

class CSSOCompressor(CompressorBase):

    def compress_css(self, css):
        proc = subprocess.Popen(
        css_out = proc.communicate(
        # was_size = len(css)
        # new_size = len(css_out)
        # print('FROM {} to {} Saved {}  ({!r})'.format(
        #     was_size,
        #     new_size,
        #     was_size - new_size,
        #     css_out[:50]
        # ))
        return css_out

In your settings.py where you configure django-pipeline make it something like this:


    # These two important lines. 
    'CSSO_BINARY': path('node_modules/.bin/csso'),
    # Adjust the dotted path name to where you put your compressors.py
    'CSS_COMPRESSOR': 'peterbecom.compressors.CSSOCompressor',

    'JS_COMPRESSOR': ...

Next, install csso-cli in your project root (where you have the package.json). It's a bit confusing. The main package is called csso but to have a command line app you need to install csso-cli and when that's been installed you'll have a command line app called csso.

$ yarn add csso-cli


$ npm i --save csso-cli

Check that it installed:

$ ./node_modules/.bin/csso --version

And that's it!


So csso has an advanced feature to restructure the CSS and not just remove whitespace and not needed semicolons. It costs a bit of time to do that so if you want to squeeze the extra milliseconds out, enable it. Trading time for space.
See this benchmark for a comparison with and without --restructure-off in csso.

Why csso you might ask

Check out the latest result from css-minification-benchmark. It's not super easy to read by it seems the best performing one in terms of space (bytes) is crass written by my friend and former colleague @mattbasta. However, by far the fastest is csso when using --restructre-off. Minifiying font-awesome.css with crass takes 326.52 ms versus 3.84 ms in csso.

But what's great about csso is Roman @lahmatiy Dvornov. I call him a friend too for all the help and work he's done on minimalcss (not a CSS minification tool by the way). Roman really understands CSS and csso is actively maintained by him and other smart people who actually get into the scary weeds of CSS browser hacks. That gives me more confidence to recommend csso. Also, squeezing a couple bytes extra out of your .min.css files isn't important when gzip comes into play. It's better that the minification tool is solid and stable.

Check out Roman's slides which, even if you don't read it all, goes to show that CSS minification is so much more than just regex replacing whitespace.
Also crass admits as one of its disadvantages: "Certain "CSS hacks" that use invalid syntax are unsupported".

28 Feb 2018 8:17pm GMT

27 Feb 2018

feedDjango community aggregator: Community blog posts

How to add Wagtail page programmatically via Python script


Two Wagtail CMS page classes:

class Section(Page):
    subtitle = models.Charfield(max_length=128)

class News(Page):
    content = models.Textfield()


Using a python script, add a News page item under the Section page titled "Latest news."


1) Get parent page instance:

parent_page = Page.objects.get(title='Latest news' ...

Read now

27 Feb 2018 2:12pm GMT

26 Feb 2018

feedDjango community aggregator: Community blog posts

Basics of Django Rest Framework

What Is Django Rest Framework?

Django Rest Framework (DRF) is a library which works with standard Django models to build a flexible and powerful API for your project.

Basic Architecture

A DRF API is composed of 3 layers: the serializer, the viewset, and the router.


Django models intuitively represent data stored in your database, but an API will need to transmit information in a less complex structure. While your data will be represented as instances of your Model classes in your Python code, it needs to be translated into a format like JSON in order to be communicated over an API.

The DRF serializer handles this translation. When a user submits information (such as creating a new instance) through the API, the serializer takes the data, validates it, and converts it into something Django can slot into a Model instance. Similarly, when a user accesses information via the API the relevant instances are fed into the serializer, which parses them into a format that can easily be fed out as JSON to the user.

The most common form that a DRF serializer will take is one that is tied directly to a Django model:

class ThingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Thing
        fields = ('name', )

Setting fields allows you to specify exactly which fields are accessible using this serializer. Alternatively, exclude can be set instead of fields, which will include all of the model's fields except those listed in exclude.

Serializers are an incredibly flexible and powerful component of DRF. While attaching a serializer to a model is the most common use, serializers can be used to make any kind of Python data structure available via the API according to defined parameters.


A given serializer will parse information in both directions (reads and writes), but the ViewSet is where the available operations are defined. The most common ViewSet is the ModelViewSet, which has the following built-in operations:

Each of these associated functions can be overwritten if different behavior is desired, but the standard functionality works with minimal code, as follows:

class ThingViewSet(viewsets.ModelViewSet):
    queryset = Thing.objects.all()
    serializer_class = ThingSerializer

If you need more customization, you can use generic viewsets instead of the ModelViewSet or even individual custom views.


Finally, the router provides the surface layer of your API. To avoid creating endless "list", "detail" and "edit" URLs, the DRF routers bundle all the URLs needed for a given viewset into one line per viewset, like so:

# Initialize the DRF router; only once per urls.py file from rest_framework import routers`
router = routers.DefaultRouter()

# Register the viewset
router.register(r'thing', main_api.ThingViewSet)

Then, all of the viewsets you registered with the router can be added to the usual url_patterns:

url_patterns += url(r'^', include(router.urls))

And you're up and running! Your API can now be accessed just like any of your other django pages. Next, you'll want to make sure people can find out how to use it.


While all code benefits from good documentation, this is even more crucial for a public-facing API, since APIs can't be browsed the same way a user interface can. Fortunately, DRF can use the logic of your API code to automatically generate an entire tree of API documentation, with just a single addition to your Django url_patterns:

url(r'^docs/', include_docs_urls(title='My API')),

Where next?

With just that simple code, you can add an API layer to an existing Django project. Leveraging the power of an API enables you to build great add-ons to your existing apps, or empowers your users to build their own niche functionality that exponentially increases the value of what you already provide. For more information about getting started with APIs and Django Rest Framework, check out this talk.

26 Feb 2018 8:30pm GMT

Container Runtimes Part 2: Anatomy of a Low-Level Container Runtime

This is the second in a four-part series on container runtimes. In part 1, I gave an overview of container runtimes and discussed the differences between low-level and high-level runtimes. In this post I will go into detail on low- level container runtimes. Low-level runtimes have a limited feature set and typically perform the low- level tasks for running a container. Most developers shouldn't use them for their day-to-day work. Low-level runtimes are usually implemented as simple tools or libraries that developers of higher level runtimes and tools can use for the low-level features. W[...]

26 Feb 2018 8:00am GMT

25 Feb 2018

feedDjango community aggregator: Community blog posts

Synchronizing Django model definitions

Cloned crystals

This is about a small problem we faced with the models used for customers in YPlan, now Time Out Checkout.

Customers are stored in two models: Customer for active customers, and RemovedCustomer for inactive customers. When a customer closes their account, a subset of the fields are copied to RemovedCustomer, to comply with data retention policies, and then the original Customer is wiped. The two models are defined something like this:

class Customer(models.Model):
    name = models.CharField(max_length=128, blank=True)
    email = models.CharField(max_length=128, null=True, unique=True)
    # etc.

class RemovedCustomer(models.Model):
    name = models.CharField(max_length=128, blank=True)
    email = models.CharField(max_length=128, null=True)
    # etc.

name and email are two of the fields copied on closure - they're nearly identical, except RemovedCustomer.email is not unique, because the same email address could be used for multiple accounts that get removed one after another.

The problem we faced was keeping the definitions of these fields synchronized, differences like unique asides. Initially the two model classes were declared in the usual way, as above, with the field definitions copy-pasted. This meant that changes to one model needed copying to the other. Unfortunately this got forgotten when a field on Customer had its max_length extended, so it wasn't copied to RemovedCustomer, and the account close function broke for customers using the new longer max_length as their data couldn't be copied into RemovedCustomer.

The solution was obvious: we wanted a way to declare that this field should be the same as that field, allowing for overrides like unique for email. Django doesn't have any built-in function to do this, but it's not hard to make your own, given a few nice things about Python classes and Django models.

Firstly, there is nothing special about constructing a field in a Django model's class body. Python class bodies are code contexts like any other, populating a dict that goes on to become the class. Any model 'magic' from Django happens after the class body finishes executing, when its Model metaclass rearranges the fields in the class dict and does other processing. Therefore we don't need to use field classes to create field objects - we can use a function that returns one instead, for example:

class RemovedCustomer(models.Model):
    name = plz_clone_field(Customer, 'name')

Secondly, Django fields are fairly easy to clone. They can't be copied with copy.deepcopy(), because they get 'attached' to the model class by the model meta 'magic'. However, they do have a handy method called deconstruct(), used for serializing in migrations, which returns a 4-tuple that describes how to reconstruct the field object. Using this we can create a fresh clone of a field, doing something like:

name, klass_path, fargs, fkwargs = field.deconstruct()
field_class = import_string(klass_path)
new_field = field_class(*fargs, **fkwargs)

In our code we created a simple function clone_field based on this snippet. Given a model class, the name of a field to clone from it, and any keyword-arg overrides, it returns a clone of that field. Using it for our models above, it looks like:

def clone_field(model_class, name, **kwargs):
    name, klass_path, fargs, fkwargs = model_class._meta.get_field(name).deconstruct()
    field_class = import_string(klass_path)
    return field_class(*fargs, **fkwargs)

class RemovedCustomer(models.Model):
    name = clone_field(Customer, 'name')
    email = clone_field(Customer, 'email', unique=False)

This elegantly declares what to copy with any differences. Because this happens at class definition time, it can't affect any of the model meta 'magic', as the fields 'look' as if they were normally constructed. And this prevents the bug we saw - a change in, e.g., max_length for Customer.name would be synchronized to RemovedCustomer.name automatically, and Django migrations would detect it for both models equally.

Pretty neat!

25 Feb 2018 11:35am GMT

24 Feb 2018

feedDjango community aggregator: Community blog posts

Raspberry Pi Awesome // Install Scripts for Python 3, OpenCV, Dli & Others

I've found setting up my Raspb...

24 Feb 2018 9:36pm GMT

22 Feb 2018

feedDjango community aggregator: Community blog posts

On Django's longevity

"Django is about to be a teenager."

I don't remember exactly who said that, but it came up in a discussion of potential followup events to 2015's "Django Birthday", held in Lawrence, Kansas, to celebrate the tenth anniversary of Django's initial public release. There might still be some parties to throw - maybe a Django sweet sixteen - but regardless of what the future holds, the summer of 2018 will mark thirteen years since ...

Read full entry

22 Feb 2018 7:06pm GMT

Raspberry Pi Network Server Guide with Django & SSH

In this post, we'll be setting...

22 Feb 2018 6:56pm GMT

OpenCV & Python // Web Camera Quick Test

This post assumes you have eit...

22 Feb 2018 5:41pm GMT

Install OpenCV 3 for Python on Windows

OpenCV, aka Open Computer Visi...

22 Feb 2018 5:26pm GMT