Blog | Emin Mastizadahttps://mastizada.com/blog/2024-03-28T11:11:17.376385+00:00BlogFlask on Apache with mod_wsgi2018-05-23T20:46:48+00:002024-03-28T11:10:55.391729+00:00Emin Mastizadahttps://mastizada.com/blog/author/mastizada/https://mastizada.com/blog/flask-on-apache-with-mod_wsgi/<p>Nowadays making a proxy from an nginx to a gunicorn socket running on supervisor or systemd makes things so easier that most of us even forgot how deployment was before. Recently I was asked to deploy a flask application on already working Apache2 instance. In this blog post I will describe steps and problems using mod_wsgi on Apache.</p>
<p>First of all, install python, pip and mod_wsgi: <code>apt install python3-dev python3-pip libapache2-mod-wsgi</code></p>
<p>Restart <code>apache2</code> service and verify that wsgi module is loaded: <code>sudo apache2ctl -M|grep -i wsgi</code></p>
<p>Create a <code>projectname.wsgi</code> file in your project:</p>
<pre>import sys<br/>sys.path.insert(0, '/path/to/project')<br/><br/>from app import app as application<br/>application.root_path = '/path/to/project'</pre>
<p>The first thing will add your python files to the python path, that is needed to find the app.py file (where your flask app is located). The second part will tell the application where the root is, it is required for loading templates.</p>
<p>Create a configuration file (<code>projectname.conf</code> - .conf extension is required for the new version of Apache) for your project under <code>/etc/apache2/sites-available</code>:</p>
<pre><VirtualHost *:<PORT>><br/> ServerName <DOMAIN.NAME><br/> WSGIDaemonProcess <projectname> user=<user> group=www-data threads=2<br/> WSGIScriptAlias / /path/to/project/projectname.wsgi<br/> <Directory /path/to/project><br/> WSGIProcessGroup <projectname><br/> WSGIApplicationGroup %{GLOBAL}<br/> Order deny,allow<br/> Allow from all<br/> </Directory><br/> Alias "/static/" "/path/to/project/static/"<br/> <Directory /path/to/project/static/><br/> Order allow,deny<br/> Allow from all<br/> </Directory><br/> ErrorLog /path/to/logs/error.log<br/> CustomLog /path/to/logs/access.log combined<br/></VirtualHost></pre>
<p>Link the configuration file to the enabled folder:</p>
<p><code>cd ../sites-enabled</code> & <code>ln -s ../sites-available/projectname.conf projectname.conf</code>.</p>
<p>Reload apache2 service and check if the website is online.</p>
<p>Most notable difference between gunicorn is that you will not be able to open files from the relative path. You can use <code>current_app.root_path</code> to access path and it is true for all plugins too (in my case, one of the plugins was storing a session file in the project root). Also defining <code>PROJECT_ROOT</code> can be helpful: <code>PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))</code></p>Date/Time Localization in Django (python-side)2017-03-12T06:40:15+00:002024-03-28T11:11:17.376385+00:00Emin Mastizadahttps://mastizada.com/blog/author/mastizada/https://mastizada.com/blog/datetime-localization-in-django-python-side/<p>There are two sides in localization in Django framework: Templates and Python-side.</p>
<p>There are a lot of good stuff about template side in <a href="https://docs.djangoproject.com/en/1.10/topics/i18n/" target="_blank" title="Internationalization and localization">Django</a> <a href="https://docs.djangoproject.com/en/1.10/topics/i18n/formatting/" target="_blank" title="Format localization">Documentation</a>, how ever what if you need to get time using <strong>datetime</strong> module?</p>
<p>Lets go over <code>date.today</code> using "%B %Y" <a href="https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior" target="_blank" title="Python datetime formats">format</a>:</p>
<pre>>>> from datetime import date<br/>>>> today = date.today()<br/>>>> print(today.strftime("%B %Y"))<br/>March 2017</pre>
<p>What if I need this for subject of an e-mail or sms message that will be sent from django app?</p>
<p>Let's assume that we have <code>user</code> object, and it has <code>CharField</code> language with value 'ru'. First of all, we will need to activate language:</p>
<pre>>>> from django.utils.translation import activate<br/>>>> activate(user.language)</pre>
<p>Our e-mail subject will be "Topics for March 2017" and in Russian "Темы для Март 2017":</p>
<pre>>>> from django.utils.translation import ugettext_lazy as _<br/>>>> subject = _("Topics for {date}").format(date=today.strftime("%B %Y"))<br/>>>> print(subject)<br/>Темы для March 2017</pre>
<p>As you can see, month stays in English. In that case one possible solution can be to parse month name ("March"), use it's translation and add only year from <code>today.year</code>:</p>
<pre>>>> month_name = _(today.strftime("%B"))<br/>>>> subject = _("Topics for {month}, {year}").format(month=month_name, year=today.year)<br/>>>> print(subject)<br/>Темы для Март, 2017</pre>
<p>Another way is to use django.utils.formats function:</p>
<pre>>>> from django.utils import formats<br/>>>> date = formats.date_format(today, format="YEAR_MONTH_FORMAT", use_l10n=True)<br/>>>> subject = _("Topics for {date}").format(date=date)<br/>>>> print(subject)<br/>Темы для Март 2017 г.</pre>
<p>If you have <code>USE_L10N = True</code> in settings, no need for <code>use_l10n</code> attribute.</p>
<p>Second way is more practical and first gives you better control for localization (like adding extra words for different locales).</p>
<p>You can <a href="https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#std:templatefilter-date" target="_blank" title="all allowed date format strings">find here all allowed date format strings</a>.</p>
<p></p>
<p>Hope it helped you and if you have a better idea to solve that problem, please, write them in comments.</p>