Wednesday, 2 November 2016

Deploy django channels app on Nginx with Daphne, Asgi and Supervisor


So finally you have successfully created a django app that is utilizing the new cutting-edge technology django channels. Before that absorbing the power of web sockets in django is somewhat a a bane in your life. But after the channels revelation, the bad days are no more.

Though channels are very major and wonderful addition in django family, But it still in initial phases so resources for it is also very few. But instead of all of these thing, if you got success in the integration of channels in your project, that's not a last job, you still need to serve your app across the internet so that your audience can see it.

In order to achieve this, your old friend WSGI wont works. Since channels required Asgi for its capability to serve over the internet. Again Since this is quite a new technology so there isn't enough resources that will guide you for this deployment at least at the time I am right this.

When I was deploying my django channel app, it almost took my good time because of this lackness of online resources and reviews. So I have decided to share my all the efforts in black and white for others, through which I have successfully made deployment on Nginx with Daphne and Asgi as well as involving supervisor with this.




If you are still not familiar with Daphne and Asgi, I recommend you to visit this wonderfully tutorial by Abu Ashraf Masnun, that will provide you good understanding of both of these channels backers.

Here I will also show you how you can use supervisor to automate server up down without your manual interference.

asgi.py

To run Daphne, it just needs to be supplied with a channel backend, in much the same way a WSGI server needs to be given an application. Create asgi.py file that looks like this in the same directory where there is wsgi.py:
import os 

from channels.asgi import get_channel_layer 




os.environ.setdefault("DJANGO_SETTINGS_MODULE", "your_project.settings") channel_layer = get_channel_layer()

Install Supervisor

Since we are using supervisor to automate our server process so, Install supervisor in your machine. In ubuntu for this I have done

apt-get install supervisor
After this we need to configure the supervisor for our program, you. I am keeping my program conf separated from the supervisor base configurations i.e used [include] to include external configurations, but you can also add directly to this file. Add the following lines in /etc/supervisor/supervisord.conf

; supervisor config file
[unix_http_server]
file=/var/run/supervisor.sock   ; (the path to the socket file)
chmod=0700                       ; sockef file mode (default 0700)
[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor            ; ('AUTO' child log dir, default $TEMP)
; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL  for a unix socket
; The [include] section can just contain the "files" setting.  This
; setting can list multiple files (separated by whitespace or
; newlines).  It can also contain wildcards.  The filenames are
; interpreted as relative to this file.  Included files *cannot*
; include files themselves.
[include]
files = /etc/supervisor/conf.d/*.conf
stdout_logfile=/var/log/django-supervisor.log
stderr_logfile=/var/log/django-supervisor.log 
And then create your configuration file program.conf in /etc/supervisor/conf.d/ as:

[program:server_workers]
command=/my_venvs/django-venv/bin/python /home/django/your_project/manage.py runworker
directory=/home/django/your_project/
stdout_logfile=/home/django/logs/gunicorn_supervisor.log            ; Where to write log messages
stderr_logfile=home/django/logs/gunicorn_supervisor.log
autostart=true
autorestart=true
redirect_stderr=true
stopasgroup=true
[program:server_interface]
command=/my_venvs/django-venv/bin/daphne -b 127.0.0.1 -p 8000 your_project.asgi:channel_layer
directory=/home/django/your_project/
stdout_logfile=/home/django/logs/daphne.log            ; Where to write log messages
stderr_logfile=home/django/logs/daphne.log
autostart=true
autorestart=true
stopasgroup=true
Make sure to replace python path, project path, daphne path, logs files path according to your project in this configurations.

Till now we have configured our supervisor script to run Daphne server and the workers that interact with Daphne server.

Nginx 

The last step in our server deployment is to setup Nginx to divert all traffic to Daphne 

Create confuration file of your site in /etc/nginx/sites-available/ and paste the following configurations: project.conf

# Enable upgrading of connection (and websocket proxying) depending on the
# presence of the upgrade field in the client request header
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# Create an upstream alias to where we've set daphne to bind to
upstream your_project {
server 127.0.0.1:8000;
}

server {
    listen 80;
    server_name YOUR_SERVER_IP;

    client_max_body_size 4G;

    access_log /home/django/logs/nginx-access.log;
    error_log /home/django/logs/nginx-error.log;


    location /static/ {
        root  /home/public_html;
    }

    location /media/ {
        alias   /home/public_html/media/;
    }

    location / {
        # an HTTP header important enough to have its own Wikipedia entry:
        #   http://en.wikipedia.org/wiki/X-Forwarded-For
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # enable this if and only if you use HTTPS, this helps Rack
        # set the proper protocol for doing redirects:
        # proxy_set_header X-Forwarded-Proto https;

        # pass the Host: header from the client right along so redirects
        # can be set properly within the Rack application
        proxy_set_header Host $http_host;

        # we don't want nginx trying to do something clever with
        # redirects, we set the Host: header above already.
        proxy_redirect off;

        # set "proxy_buffering off" *only* for Rainbows! when doing
        # Comet/long-poll stuff.  It's also safe to set if you're
        # using only serving fast clients with Unicorn + nginx.
        # Otherwise you _want_ nginx to buffer responses to slow
        # clients, really.
        # proxy_buffering off;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # Try to serve static files from nginx, no point in making an
        # *application* server like Unicorn/Rainbows! serve static files.
        if (!-f $request_filename) {
            proxy_pass http://your_project;
            break;
        }
    }

    # Error pages
    error_page 500 502 503 504 /500.html;
    location = /500.html {
        root /home/public_html/static/;
    }
}
Again make sure to replace all the settings according to your understanding for example replace YOUR_SERVER_IP with the address of yours. Similarly replace static file paths as well as project names etc.

Now the final step is to create the symlink of your site configuration from sites-available to sites-enabled, here's how to do this in ubuntu:

cd sites-enabledsudo ln -s ../sites-available/project.conf .

That's it: 

If everything goes fine as mentioned above, you will now be able to see your site in your browser. If this helps you don't forget to appreciate me via comments :)
Furthermore, if found anything wrong in this tutorial please help others by commenting it.
Thanks 


Wednesday, 26 October 2016

Best way to create See Own Customers rule in Odoo


Odoo does not provide by default a rule to limit users to see their own customers, at least at the time when I am writing this article. So many people are asking the question in different odoo forums, how they can limit users to see their own customer similar to the See Own Leads group rules of the Sale.

For the answer of this question, many have suggested  to create a record rule from Odoo Settings --> Technical --> Security --> Record Rules like ir.ui.view.custom object. Set the object as res.partner and Add related domain in Domain section as:



['|', ('user_id', '=', user.id), ('user_id', '=', False)]

like in the answers in this post and this and this

This is valid domain but I am not the one who suggest this domain on record rule for such use case, since the problem with this is that the res.partner object is not just for customers, its also has records for companies, users as well as suppliers. So what this domain does is it limit all that other records too. It is also possible that you will also got such access errors on different other objects as I got in sale module while approaching sale dashboard:





The requested operation cannot be completed due to security restrictions. Please contact your system administrator.
(Document type: res.users, Operation: read)


Hence we need a way to exclude all other than customer record from this domain.

This domain will I think is best suited if you want to limit just customers:


['|', '|', '|', ('user_id', '=', user.id), ('user_id', '=', False), ('create_uid', '=', user.id), ('customer','=',False)]

and to apply this via code :


<record model="ir.rule" id="custom_rule_see_own_customer">
    <field name="name">custom.rule.see.own.customer</field>
    <field name="model_id" ref="base.model_res_partner"/>
    <field name="domain_force">ABOVE DOMAIN HERE</field>
    <field name="groups" eval="[(4,ref('base.group_sale_salesman'))]"/>
    <field name="perm_read" eval="True"/>
    <field name="perm_write" eval="True"/> 
    <field name="perm_unlink" eval="True"/> 
    <field name="perm_create" eval="True"/>
</record>

Sunday, 21 August 2016

Hardware Approach vs API: Choosing the best and right SMS API gateway in Pakistan



Recently I got a chance to work in a project, in which there was a requirement to integrate the two way messaging mechanism in web system. So the very first thing that came to my mind was which sms messaging method to go for? There are the choices for hardware approach and the API approach. Hardware approach is that in which usually modems are used as a communication medium is very popular for many organisations that are been using this sms mechanism in their systems for now long time. There is a relative easiest way to achieved similar thing is using the cloud based API services. In this gateway providers rather than to setup hardware on client system provide cloud based APIs to be integrated with the clients systems. For me this API based approach is more suitable, so I opted it over hardware approach.

The second thing on which I have to made decision was, which SMS API gateway to choose? There are plenty of such gateway providers in the web, choosing your best and right option is really a hectic job, at least it was for me. I have different conditions from the customer of my system related to pricing, time, durable etc. , to whom I have to address. So I prepared a comparison table that helped to select my best and right SMS API gateway. The system on which I was working was for Pakistan so my primary concern of work is only for Pakistani audience, but you can also get good sort of knowledge for any region.

Solution/PlatformCoverageLocal Number2 wayAPIEase of integrationpricing
TwilioyesnoyesyesyesLow
ClickatellyesnoyesyesnoAverage
plivo*noyesyesyeslow
Sinch*noyesyesyesAverage / very low ⁰¹
smsglobal*noyesyesyesAverage ⁰¹
nexmo-noyesyesyesAverage
Hardware ApproachyesyesyesnonoHigh

* Need Credentials to test / Not Free / Failed to test
⁰¹ Depending on the scale of use





Saturday, 13 August 2016

How to reset all migrations in django > 1.7 in windows and linux?

Django has a awesome way to handle changes in the database, which help us to track the structure of the database and keep us safe from manual interactions with the database. Databases changes are mapped according to the model definitions. If you worked in other python frameworks like Odoo or web2py then you can definitely realize what a great thing it is. Here is how they are defining these migrations:
Migrations are Django’s way of propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema
But often times this facility becomes tension and we stuck in such a situation where it fails to caters our need and the only way we have is to reset all the migrations and start the migration from the initial. For such a situation in Windows and Linux these may can help you.

For Windows:

del project_dir/app_dir/migrations/*
echo.>project_dir/app_dir/migrations/__init__.py
python manage.py makemigrations
python manage.py migrate



For Linux :

$/home/project-dir@user: find . -path *migrations* -name "*.py" -not -path "*__init__*"
python manage.py makemigrations
python manage.py migrate


ref: http://stackoverflow.com/a/30016412/3832653

Wednesday, 16 September 2015

How to configure hierarchy Sales Team Structure in Odoo / OpenERP

Often times while following OpenERP/Odoo for sales management, it is our requirement to have a proper team hierarchy with the secure desired flow of information. For that Odoo provides us the ability to create our own sales teams with the desired access control for the flow of information in the team hierarchy. In this tutorial we will use use the default Odoo provided roles or group. For the one who wants to customize the access control as per his/her requirement, he/she have to create their own security rules etc.

One of major concerns for the Odoo users is to easily configure the sales team, since Odoo have the poorest documentation [as per the online sorcerers :) ]. So to configure your sales teams properly, likely this tutorial will helps you.

In this tutorial I am considering this sales team hierarchy:
  • Sales Manager (Team Leader)
    • Sales Person 
      • Sales And Quotations

Setting proper sales team configurations can solve the mentioned problems.
Sales Teams can be configured by the following steps:
  • Create Sales Teams: Go to Sales Tab Configuration Sales Teams.  Give the newly created sales team some desired name like Team A.
  • Set Team Leader (Sale Manger) for Sales Team. From Sales Configuration Sales Team. Make sure that the Team Leader has proper access rights (instructions are given below for setting access rights.
  • Assigning Team members of that Sales team. Add some users as a team member to new sales team. Each user should have proper access rights. (Instructions are given below).
  • Set Sales Person and Sales Team on Quotations and Sales Orders. Now as our sales team is created, it’s time to associate some sales and quotation to our sales team. To do this one should set Sales Person and Sales Team while creating new Quotations and Sale order. Set Sales Team from the Other Information Tab.

How to set access rights For Team Leader & Sales Person: 

To configure access rights: settings users user access rights

  • For Team Leader set sales value to Manager 
  • For Team Leader set sales value to See Own Leads

Tuesday, 15 September 2015

The Anatomy of Bika-LIMS

Python, Zope, CMF, Plone, Bika how does that all fit together?
 

Bika-LIMS Architecture:

The architecture of Bika-LIMS can be analyzed from this figure:

Figure 1 Bika-LIMS architecture

What is Zope:

Zope is one of the most scalable web application servers in the market.


Figure 2 The Zope Application Server

What is Plone?

Plone is a content management system (CMS) which you can use to build a web site. With Plone, ordinary people can contribute content to a web site without the help of a computer geek. Plone runs over the Web, too, so you don't need to install any special software on your computer. The word content is meant to be general, because you can publish so many types information,




Where Bika-LIMS stands?

Bika-LIMS is an add-ons built for the Plone framework. Or we can say that the Bika-LIMS is Plone site. That means in order to understand the Bika-LIMS, we must have to understand Plone framework.

Plone is all about Content and Theme:

Theming Plone:

Theming a Plone site has two major parts:

· Structural theming: the construction of the HTML skeleton of a page and getting the right content elements into the right spots. Also, the provision of the CSS and Javascript elements to finish the presentation and provide dynamic behaviors.

Templating, which itself has two aspects:

  • Viewlet templates, which we might think of as the micro formatting of the page. Remember when we looked at the viewlet map of a page? (Look again via @@manage-viewlets.) All those viewlets are provided via individual, editable templates.
  • Content type view templates, Whenever we create a new content type or modify an existing one, we’ll typically want to create or modify a view template.

Structural theming is best accomplished via the Diazo theme engine. Diazo provides a rule based mechanism for mapping content provided by Plone into one or more master page designs.

Templating is accomplished by editing page template files which allow us to mix object content from the ZODB with HTML. Plone uses its own (actually Zope’s) Template Attribute Language (TAL) for this purpose.

Content-types in Plone:

A content type is a variety of object that can store information and is editable by users. We have different content types to reflect the different kinds of information about which we need to collect and display information. Pages, folders, events, news items, files (binary) and images are all content types.

There are two content-frameworks in Plone: Archetypes and Dexterity. Dexterity is the new way to create content types and is default in Plone 5. And Archetype is the default way to create content types in Plone 4.

Since the scope of this document is to understand the Bika-LIMS and the Bika-LIMS is based on Plone 4. So we will just understand the archetype framework here. The comparation between the two frameworks can be seen from http://plone-training.readthedocs.org/en/latest/dexterity.html#dexterity-and-archetypes-a-comparison

The makings of a Plone content type:

Every Plone content type has the following parts:
  • Schema: A definition of fields that comprise a content type; properties of an object.
  • FTI: The “Factory Type Information” configures the content type in Plone, assigns it a name, an icon, additional features and possible views to it.
  • Views: A view is a representation of the object and the content of its fields that may be rendered in response to a request. You may have one or more views for an object. Some may be visual — intended for display as web pages — others may be intended to satisfy AJAX requests and be in formats like JSON or XML.

Archetypes Content-types:

Archetype is a framework designed to facilitate the building of applications for Plone and CMF. Its main purpose is to provide a common method for building content objects, based on schema definitions.

  • o Schema in Archetypes: Schema only in Python
  • o Archetypes: Permissions per field hard, custom forms even harder.
  • o If you have to program for old sites you need to know Archetypes!

To learn more about Archetypes visit https://plone.org/products/archetypes/documentation/old/ArchetypesDeveloperGuide/index_html

Major Archetypes present in Bika-LIMS can be seen from the project database ERD:






References:
http://www.bikalabs.com/softwarecenter/bika
http://www.bikalabs.org/
https://plone.org/
http://www.zope.org/