[Django]-Version number in Django applications

8👍

It seems the settings file would be a reasonable location to store the version number. I don’t believe there is any Django accepted way to store a version number of your personal application. It seems like an application specific variable that you should define.

For more information on getting the version number out of svn: Getting SVN revision number into a program automatically

31👍

I was looking for this exact same question, and found your question. The answer you accepted is not quite satisfactory to me.

I am working with django debugtoolbar, in there you can also show all versions of the apps used. I was wondering how to get the versions of my custom applications to show there as well.

Looking a bit further I found this question and answer:
How to check the version of a installed application in Django in running time?

This answer however does not tell me where to put this __version__

So I looked in to an open application, which does show up in django toolbar.
I looked in to the django restframework code, there I found out:

the version is put in the __init__.py file

(see https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/init.py)

and it is put here as:

__version__ = '2.2.7'
VERSION = __version__  # synonym

And after this, in his setup.py, he gets this version from this __init__.py :
see: https://github.com/tomchristie/django-rest-framework/blob/master/setup.py

like this:

import re

def get_version(package):
    """
    Return package version as listed in `__version__` in `init.py`.
    """
    init_py = open(os.path.join(package, '__init__.py')).read()
    return re.match("__version__ = ['\"]([^'\"]+)['\"]", init_py).group(1)

version = get_version('rest_framework')

When using buildout and zestreleaser:

By the way, I am using buildout and zest.releaser for building and versioning.

In this case, above is a bit different (but basically the same idea):

see http://zestreleaser.readthedocs.org/en/latest/versions.html#using-the-version-number-in-setup-py-and-as-version

The version in setup.py is automatically numbered by setup.py, so in __init__.py you do:

import pkg_resources

__version__ = pkg_resources.get_distribution("fill in yourpackage name").version
VERSION = __version__  # synonym

28👍

There are many places where you can store your app version number and a few methods that allow you to show it in django templates. A lot depends on the release tool you’re using and your own preferences.

Below is the approach I’m using in my current project.

Put the version number into version.txt

I’m storing the app version number in the version.txt file. It’s one of the locations the zest.releaser release tool (that I’m using) takes into account while doing a release.

The whole content of version.txt is just the app version number, for example: 1.0.1.dev0

Read the number to a variable in settings.py

...    
with open(version_file_path) as v_file:
    APP_VERSION_NUMBER = v_file.read()
...

Create a custom context processor

This paragraph and the following ownes are based on the wonderful answer by bcchun to Can I access constants in settings.py from templates in Django?

A custom context processor will allow you to add the app version number to the context of every rendered template. You won’t have to add it manually every time you render a template (and usually you’ll want to have the version number somewhere in the footer of every page).

Create context_processors.py file in your app directory:

from django.conf import settings

def selected_settings(request):
    # return the version value as a dictionary
    # you may add other values here as well
    return {'APP_VERSION_NUMBER': settings.APP_VERSION_NUMBER}

Add the context processor to settings.py

TEMPLATES = [{
    ...
    'OPTIONS': {
        'context_processors': [
            ...
            'your_app.context_processors.selected_settings'
        ],
    },
 }]

Use RequestContext or render in views

RequestContext and render populate the context with variables supplied by context_processors you set in settings.py.

Example:

def some_view(request):
    return render(request, 'content.html')
    

Use it in a template

...
<div>{% trans 'App version' %}:{{APP_VERSION_NUMBER}}</div>
....

12👍

For me the best result/approach is to use the __init__.py on the project folder, such as

.
├── project_name
│   ├── __init__.py

and later check using the standar way, as said in (PEP396)

>>> import project_name
>>> project_name.__version__
'1.0.0'

10👍

I solved this by adding a templatetag to my django project:

in proj/templatetags, added version.py:

from django import template
import time
import os

register = template.Library()

@register.simple_tag
def version_date():
    return time.strftime('%m/%d/%Y', time.gmtime(os.path.getmtime('../.git')))

Then, in my base.html (or whichever template), adding:

{% load version %}
<span class='version'>Last Updated: {% version_date %}</span>

8👍

If using GIT for source versioning, you might want manual promotion of stable
releases, and automatic numbering for development commits.

One why to obtain this in a Django project is:

In “PROJECT/_ init _.py” define:

__version__ = '1.0.1'
__build__ = ''

Then in setting.py do:

import os
import subprocess
import PROJECT

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

try:
    PROJECT.__build__ = subprocess.check_output(["git", "describe", "--tags", "--always"], cwd=BASE_DIR).decode('utf-8').strip()
except:
    PROJECT.__build__ = PROJECT.__version__ + " ?"

Thus, PROJECT._ build _ will show:

v1.0.1 in stable releases

and

v1.0.1-N-g8d2ec45 

when the most recent tag doesn’t point to the last commit (where N counts the number of additional commits after tag, followed by commit signature)

2👍

Not for Django applications, per se, but for Python modules, yes. See PEP 396, PEP 386 and the verlib library (easy_install verlib).

(I’d elaborate, but I just now discovered this, myself.)

1👍

Version info is typically maintained in git commit tags. Else, even git commits and last updated time is a good indicator of which version is running and when it was deployed.

For those using django-rest-framework and only having an API, you can return both of these; “last updated” as well as “last git commit” using an /api/version endpoint:

In views.py:

import os
import time
import subprocess
import json

class VersionViewSet(ViewSet):
    def list(self, request):
        # ['git', 'describe', '--tags'] # use this for named tags (version etc)
        # ['git', 'describe', '--all', '--long'] # use this for any commit
        # git log -1 --pretty=format:"Last commit %h by %an, %ar ("%s")"
        # {"commit_hash": "%h", "full_commit_hash": "%H", "author_name": "%an", "commit_date": "%aD", "comment": "%s"}
        FILE_DIR = os.path.dirname(os.path.abspath(__file__))
        git_command = ['git', 'log', '-1', '--pretty={"commit_hash": "%h", "full_commit_hash": "%H", "author_name": "%an", "commit_date": "%aD", "comment": "%s"}']
        git_identifier = subprocess.check_output(git_command, cwd=FILE_DIR).decode('utf-8').strip()
        git_identifier = json.loads(git_identifier)
        last_updated = time.strftime('%a, %-e %b %Y, %I:%M:%S %p (%Z)', time.localtime(os.path.getmtime('.git'))).strip()
        return Response({
            "last_updated": last_updated,
            "git_commit": git_identifier
        }, status=200)

In urls.py:

from myapp.views import VersionViewSet

router = routers.DefaultRouter()
...
router.register(r'version', VersionViewSet, base_name='version')

This creates the endpoint in line with the other endpoints in your API.

Output will be seen like this at http://www.example.com/api/version/:

HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "last_updated": "Mon, 6 May 2019, 11:19:58 PM (IST)",
    "git_commit": {
        "commit_hash": "e265270",
        "full_commit_hash": "e265270dda196f4878f4fa194187a3748609dde0",
        "author_name": "Authorname",
        "commit_date": "Mon, 6 May 2019 23:19:51 +0530",
        "comment": "The git commit message or subject or title here"
    }
}
👤Pranab

1👍

I use this option __import__('project').VERSION or __import__('project').__version__. The version is put in the __init__.py file as everybody said, for example:

proyect_name
  | __init__.py

# __init__.py file
VERSION = '1.0.0' # or __version__ = '1.0.0'

Now from everywhere you can get it:

# Error tracking settings
sentry_sdk.init(
    ...
    release=__import__('cjvc_project').VERSION
)

0👍

I used a context processor and it looks like this:

import sys
sys.path.append('..')

from content_services import __version__


def get_app_version(request):
    """
    Get the app version
    :param request:
    :return:
    """
    return {'APP_VERSION': __version__}

Since the project name is content_services I have to change the sys path up 1 level so I can import it.

👤radtek

0👍

In case you use Git and version tagging you can display the application version in admin site header.

Create a version.py file in the project or any app module:

import os
import subprocess

FILE_DIR = os.path.dirname(os.path.abspath(__file__))


def get_version_from_git():
    try:
        return subprocess.check_output(['git', 'describe', '--tags'],
                                       cwd=FILE_DIR).decode('utf-8').strip()
    except:
        return '?'


VERSION = get_version_from_git()

Add the version to admin site header in urls.py:

from django.contrib import admin
from django.utils.safestring import mark_safe

from utils import version

...

admin.site.site_header = mark_safe('MyApp admin <span style="font-size: x-small">'
                                   f'({version.VERSION})</span>')

If you need to provide the version to external tools like Django Debug Toolbar, you can expose the version in project __init__.py as suggested above:

from utils import version

__version__ = version.VERSION
VERSION = __version__  # synonym
👤mrts

Leave a comment