Converting to another web framework: Basic apps in Symfony and Django

Converting to another web framework: Basic apps in Symfony and Django
Reading Time: 10 minutes

Many times have I heard the following from a developer: “I am scared to change technologies”, “I am excited but I’m afraid it will be entirely different”, “I only know <insert web framework here>, I’ve never seen any <insert another web framework here> code in my life!”. Sounds familiar? This article will show you that different web frameworks are not in fact that different. With the advent of open source software, modern frameworks have inspired each other in adding and improving features for easier and more efficient usage. I will try to explain the abstract notions under MVC Web frameworks and how you can easily implement them through any framework and programming language needed.
The examples will be in Symfony2, a modern PHP web framework and Django, another such framework for Python. Both frameworks are widely used in companies today, for the development of small to medium-sized web applications and backends. In fact, we have a few interesting articles in Python (mostly Django, since it’s one of our favourite frameworks) and PHP.
You can learn about the basic similarities between these two frameworks, but even if your speciality is Rails, Spring or any other web framework, you can use this article to better understand your specialty and to let go of any fears about converting. For the sake of good examples, I will be using the user stories and application development from the Symfony2 Jobeet tutorial, along with bits and pieces from the Django Write your first app tutorial.

Installing a web framework is easy

You can always experiment with features of a new web framework release using the modern installers. Nowadays specialised installers (package managers, if you wish) will automatically download the framework version of your choice and will bootstrap a project for immediate running. Usually the steps go as such: install the programming language, the installer, edit a settings file then use a shell utility provided by your framework to run your project on a local server.
In Symfony, it goes like this:

sudo apt-get install php5
sudo curl -LsS -o /usr/local/bin/symfony
sudo chmod a+x /usr/local/bin/symfony
symfony new jobeet 2.8
php app/console server:run

Which leads you to a splash screen of your first Symfony application running on localhost . Sometimes, you need to go through additional steps like adding your timezone in the php.ini file, which takes a couple of minutes of your time. In case you haven’t noticed, our programming language is PHP (the php5 package), our installer is called symfony and we start our project using the 2.8 LTS version of the framework. Our shell utility is app/console, which we will use extensively throughout the development process using various commands. You will also find settings files like parameters.yml  and config.yml  in the app/config  path, where you can edit your defaults.
In Django, the installation is similar:

sudo apt-get install python python-pip python-django-common python-django
django-admin startproject jobeet_py
python runserver

Again, we have installed python, the pip and django-admin installers, and we have started a project (called We then run it using the shell utility (which we will use in Django development a lot) and we will see a welcome screen on localhost. Your settings file is in the root folder of your project, in .
The whole process is made this way because the programmers require confirmation that their settings and framework installation are correct. After making sure the framework is installed and properly configured, we can move to the next step.

Starting the application

Symfony organises code into bundles, while Django prefers the equivalent app naming. The first things to do after installing the framework itself is to start your own separate project, which will use but not rewrite elements from the framework.
Run this in your symfony project root folder and answer all questions using the default values.

php app/console generate:bundle --namespace=Ens/JobeetBundle --format=yml

It will generate a folder structure in your src  folder, under Ens/JobeetBundle . An automatic action is also added, but we will go into more detail on routes, actions and views later. For now, know that your custom code will go inside this newly-created structure. Don’t forget to clear your cache like explained in the Jobeet tutorial.
In Django, we do more or less the same thing, using our shell utility to create an app:

python startapp jobeet

You also need to add it to your installed apps in the  file.


And now you’re good to go.

Hello World! : The triad of URL, Controller, View

You have now reached the essential point of MVC Web Frameworks. Understanding how to tie in the functionality from accessing a URL to computing and visualising the desired information is the crucial part of web development. Doing so will enable you to study related topics such as external libraries and custom handling of requests with much ease. Web frameworks work by mapping URL paths to Controller actions, which can be functions or classes and are written by the programmer to contain logical handling of data. Most of the times, the Controller will also return a view, which is the user-friendly display of computed data (as HTML and CSS). Sounds simple? Well, the most confusing part of this aspect is that different frameworks tend to name these concepts differently. For example, Symfony calls them Route-Controller-View, while Django calls them URL-View-Template. Whatever they are named, these three, combined with the Model part, represent the fundamentals of web framework development.
What I want to do using both frameworks is to make the root URL /  display a simple page with a custom signature. Since projects may contain several sub-projects (bundles, apps), we delegate from the main URL configuration file to specialised ones, located in their corresponding sub-projects. First, let’s see how this looks in Symfony. Consider the main routing file app/config/routing.yml :

    resource: "@EnsJobeetBundle/Resources/config/routing.yml"
    prefix:   /

Here we defer routing of our Jobeet routes to the Jobeet Bundle. So next we create this new and specialised routing file in src/Ens/JobeetBundle/Resources/config/routing.yml :

    path:     /
    defaults: { _controller: EnsJobeetBundle:Default:index }

The components of a route definition are the path (here, root URL), the name of the route (here, ens_jobeet_homepage ) and the mapping to a controller action. Next, we write that controller action in src/Ens/JobeetBundle/DefaultController :

namespace Ens\JobeetBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
    public function indexAction()
        return $this->render('EnsJobeetBundle:Default:index.html.twig', array(
            'signature' => 'C3-PO, Human-cyborg relations.'

As you can see, our index action is pretty simple. For our “Hello World!” example, we don’t need to connect to the database, change any available data or generally compute much. We simply render the index view and pass along the signature  variable. The purpose is simply to demonstrate how variable transmission affects the view. So in our view, located at src/Ens/JobeetBundle/Resources/views/Default/index.html.twig we simply write:

Hello World!
I am {{ signature }}.

Therefore in our template we can use the Twig templating engine’s syntax for printing a variable. The double curly braces output the signature variable we previously defined in the controller.
The result? Upon going into the browser at the address  we will see a page that prints:

Hello World!
I am C3-PO, Human-cyborg relations..

In Django, the process is almost identical. As we do in Symfony, first we defer app-related URL definition to the app itself. In our main file, located in the root folder of our Django project, we add this delegation:

from django.conf.urls import patterns, include, url
from django.contrib import admin
urlpatterns = patterns(
    url(r'^', include('jobeet.urls')),

This indicates to our main URL definition file that it needs to add the patterns from the jobeet/  file. We edit this file to contain a index route and tie it to an action.

from django.conf.urls import url
from jobeet import views
urlpatterns = [
    url(r'^$', views.index, name='index'),

The defined URL pattern points the root URL to a function inside the jobeet/  file. Note the structure of imports, which considers the name of the app, then its contained files as importable. In our file we can now write:

from django.shortcuts import render
def index(request):
    return render(request, 'jobeet/index.html', {
        'signature': 'C3-PO, Human-Cyborg relations.'

Note the similarity between the two views, Symfony and Django. If the functionality is identical, the structure of the action will be similar in any chosen modern web framework. Again we use a rendering function to display a template file (which is HTML in nature) and pass it a custom variable. In Symfony, the context that we send to the view is an array used like a dictionary, while in Django we use Python’s dictionary construct in the same fashion.
The big surprise comes now. In jobeet/templates/jobeet/index.html  we can input the exact same text as in our Symfony Twig view. This is made possible by the fact that Twig and Django’s templating engines are similar to a great extent and use the same curly braces syntax when outputting the value of a variable. Furthermore, there are a lot of similarities in the way the two templating engines handle iteration, inheritance and so on. The differences are mostly minor inconveniences, such as Twig maintaining that routes should be expressed with an echoing ({{ path(‘index’) }} ) syntax, while Django uses a block syntax ({% url ‘index’ %} ). After creating your triad of elements (URL, Action function and Template), you can check in your browser that, if you run the Django app using the runserver command,  will again print your greeting from C3-PO.


I hope that this side-by-side comparison of some simple web framework features has helped you gain some insight into just how similar they can be. It is often that not our fear of what lies ahead, but our fear of the unknown that makes us reluctant to any technological changes. However, in our times, flexibility and adaptability are essential to developers which desire a long and prosperous career. In this article, I have shown you how to install the Symfony and Django frameworks, how to start your project and how to handle basic URL-Controller-View definition. Unfortunately, I have barely touched the tip of the iceberg. Interesting similarities and differences between web frameworks can be seen in model handling, CRUD approaches, third-party providers, open source community and so on. If you want us to write more articles about today’s web frameworks and what makes them great, make sure you leave us a comment. Not too keen about PHP and Python? If Javascript is your backend flavour, be sure to check out Paul’s articles on NodeJS (building APIs and creating Admin Panels)

We transform challenges into digital experiences

Get in touch to let us know what you’re looking for. Our policy includes 14 days risk-free!

Free project consultation