Номер версии в приложениях Django
Я работаю над приложением Django, и я хочу отобразить версию приложения (так, чтобы люди, которые обнаружили ошибки, знали версию приложения и могли предоставлять лучшие отчеты об ошибках).
Существует ли общепринятый способ хранения номера версии в Django (я имею в виду версию моего приложения, а не Django)?
Ответы
Ответ 1
Кажется, что файл настроек будет разумным местом для хранения номера версии. Я не верю, что есть какой-либо Django способ хранения номера версии вашего личного приложения. Это похоже на конкретную переменную приложения, которую вы должны определить.
Для получения дополнительной информации о получении номера версии из svn: Автоматическое получение номера версии SVN в программе
Ответ 2
Я искал точно такой же вопрос и нашел ваш вопрос. Ответ, который вы приняли, не совсем удовлетворителен для меня.
Я работаю с django debugtoolbar, там вы также можете показать все версии используемых приложений. Мне было интересно, как сделать так, чтобы версии моих пользовательских приложений отображались там же.
Глядя немного дальше, я нашел этот вопрос и ответ: как проверить версию установленного приложения в Django во время выполнения?
Этот ответ, однако, не говорит мне, где поставить этот __version__
Поэтому я заглянул в открытое приложение, которое отображается на панели инструментов Django. Я заглянул в код django restframework, там я узнал:
версия помещается в файл __init__.py
(см. https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/init.py)
и это ставится здесь как:
__version__ = '2.2.7'
VERSION = __version__ # synonym
И после этого в своем файле setup.py он получает эту версию из этого __init__.py
: см. Https://github.com/tomchristie/django-rest-framework/blob/master/setup.py.
как это:
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')
При использовании buildout и zestreleaser:
Кстати, я использую buildout и zest.releaser для сборки и управления версиями.
В этом случае выше немного отличается (но в основном та же идея):
см. http://zestreleaser.readthedocs.org/en/latest/versions.html#using-the-version-number-in-setup-py-and-as-version
Версия в setup.py автоматически нумеруется setup.py, поэтому в __init__.py
вы делаете:
import pkg_resources
__version__ = pkg_resources.get_distribution("fill in yourpackage name").version
VERSION = __version__ # synonym
Ответ 3
Есть много мест, где вы можете хранить номер версии вашего приложения, и несколько методов, которые позволяют отображать его в шаблонах django. Многое зависит от используемого вами релиз-инструмента и ваших собственных предпочтений.
Ниже представлен подход, который я использую в своем текущем проекте.
Поместите номер версии в version.txt
Я храню номер версии приложения в файле version.txt. Это одно из мест, которое использует инструмент выпуска zest.releaser (который я использую) при выпуске.
Все содержимое файла version.txt представляет собой номер версии приложения, например: 1.0.1.dev0
Читайте номер переменной в settings.py
...
with open(version_file_path) as v_file:
APP_VERSION_NUMBER = v_file.read()
...
Создать пользовательский контекстный процессор
Этот параграф и следующие материалы основаны на замечательном ответе bcchun на " Могу ли я получить доступ к константам в settings.py из шаблонов в Django?"
Пользовательский контекстный процессор позволит вам добавить номер версии приложения в контекст каждого отображаемого шаблона. Вам не нужно будет добавлять его вручную каждый раз, когда вы создаете шаблон (и обычно вам нужно, чтобы номер версии находился где-то в нижнем колонтитуле каждой страницы).
Создайте файл context_processors.py в каталоге вашего приложения:
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}
Добавьте контекстный процессор в settings.py
TEMPLATES = [{
...
'OPTIONS': {
'context_processors': [
...
'your_app.context_processors.selected_settings'
],
},
}]
Используйте RequestContext
или render
в представлениях
RequestContext и render
заполняют контекст переменными, предоставленными context_processors, который вы установили в settings.py.
Пример:
def some_view(request):
return render(request, 'content.html')
Используйте это в шаблоне
...
<div>{% trans 'App version' %}:{{APP_VERSION_NUMBER}}</div>
....
Ответ 4
Я решил это, добавив templatetag к моему проекту django:
в proj/templatetags, добавлен 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')))
Затем, в моем base.html(или любом шаблоне), добавив:
{% load version %}
<span class='version'>Last Updated: {% version_date %}</span>
Ответ 5
Для меня лучший результат/подход - использовать init.py в папке проекта, например
.
├── project_name
│ ├── __init__.py
а затем проверить, используя стандартный способ, как указано в (PEP396)
>>> import proyect_name
>>> proyect_name.__version__
'1.0.0'
Ответ 6
Не для приложений Django, как таковых, но для модулей Python, да. См. PEP 396, PEP 386 и verlib библиотека (easy_install verlib).
(Идентификация сложная, но я только что обнаружил это сам).
Ответ 7
При использовании GIT для управления версиями исходного кода может потребоваться ручное продвижение стабильных выпусков и автоматическая нумерация для коммитов разработки.
Одна из причин получения этого в проекте Django:
В "PROJECT/_ init _.py" определите:
__version__ = '1.0.1'
__build__ = ''
Затем в setting.py сделайте:
import os
import subprocess
import PROJECT
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..',))
try:
PROJECT.__build__ = subprocess.check_output(["git", "describe", "--tags", "--always"], cwd=BASE_DIR).decode('utf-8').strip()
except:
PROJECT.__build__ = PROJECT.__version__ + " ?"
Таким образом, PROJECT._ build_ покажет:
v1.0.1 in stable releases
а также
v1.0.1-N-g8d2ec45
когда самый последний тег не указывает на последний коммит (где N подсчитывает количество дополнительных коммитов после тега, за которыми следует подпись коммита)
Ответ 8
Я использовал контекстный процессор, и это выглядит так:
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__}
Поскольку имя проекта - content_services
мне нужно изменить путь sys на 1 уровень, чтобы я мог его импортировать.
Ответ 9
Если вы используете Git и теги версий, вы можете отобразить версию приложения в заголовке сайта администратора.
Создайте файл version.py
в проекте или любом модуле приложения:
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()
Добавьте версию в заголовок сайта администратора в 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>')
Если вам нужно предоставить версию для внешних инструментов, таких как Django Debug Toolbar, вы можете предоставить версию в проекте __init__.py
как указано выше:
from utils import version
__version__ = version.VERSION
VERSION = __version__ # synonym
Ответ 10
Информация о версии обычно поддерживается в тегах git commit. Иначе, даже коммиты git и время последнего обновления являются хорошим индикатором того, какая версия запущена и когда она была развернута.
Для тех, кто использует django-rest-framework
и имеет только API, вы можете вернуть оба из них; "последнее обновление", а также "последний git commit" с использованием конечной точки /api/version
:
В 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)
В urls.py
:
from myapp.views import VersionViewSet
router = routers.DefaultRouter()
...
router.register(r'version', VersionViewSet, base_name='version')
Это создает конечную точку в соответствии с другими конечными точками в вашем API.
Вывод будет виден следующим образом на 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"
}
}
Ответ 11
Я использую эту опцию __import__('project').VERSION
или __import__('project').__version__
. Версия помещается в файл __init__.py
как все говорили, например:
proyect_name
| __init__.py
# __init__.py file
VERSION = '1.0.0' # or __version__ = '1.0.0'
Теперь отовсюду вы можете получить это:
# Error tracking settings
sentry_sdk.init(
...
release=__import__('cjvc_project').VERSION
)