Tuesday, March 24, 2015

Places where Django fails






I love Django, but some times i get difficulties while playing with django.This blog is describe about palce where django fails.

Ajax with Django is hard:

Most of the Django Community has decided that bundling Javascript helpers with a python framework is bad idea. Though I can understand the reasoning, (argued here and rebuttal), that Javascript is so basic that you can not be expected to not know it, I can not agree with it. SQL is as basic as Javascript, and yet we have ORM for abstracting away the common and the tedious
Of Course, with simplejson, and a good Javascript library, you can build Ajax apps fast and with only a minimal amout of fuss. And yet switching between Python and Javascript, twice every hour is a huge time drain. Eg. I put commas after the last element in Python arrays, with JS this would work in FF, but fail with weird errors in IE.

Lack of identity map:


If you get the same row from the DB twice using Model.objects.get, you will get two different objects. Apart from the performance problems of two DB queries, when only one should have done, when you update one of them, the other does not get updated, and you will have interesting things happening in your application. And if you update both of them, you might write two inconsistent changes to the DB.

Look at this code for example.

See this code

In [2]: from django.contrib.auth.models import User
In [3]: usr1 = User.objects.create_user('ram', 'demo@demo.com', 'demo')
In [4]: usr2 = User.objects.get(username='ram')
In [5]: usr3 = User.objects.get(username='ram')
In [6]: user2 == user3
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
...
In [7]: usr2 == usr3
Out[7]: True
In [8]: usr3.username = 'not_ram'
In [9]: usr3.save()
In [10]: usr2.username
Out[10]: u'ram'
In [11]: us3.username
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
...
In [12]: usr3.username
Out[12]: 'not_ram'
In [13]: usr2 == usr3
Out[13]: True

Whether Sessions are browser length/persistent are set sitewide:


You can set whether you want sessions to be browser length/persistent using SESSION_EXPIRE_AT_BROWSER_CLOSE in settings.py. But you can not set them per user, without mucking with django internal. This might seem a minor annoyance, yet this is something which you need to do for every app, as the remember me, function will not work without this.

Newforms is very limited:

Let us say you want the Form to contain a varible number of fields. How can you define the NewForms class to do your biddings.

from django import newforms as forms
class MyForm(forms.Form):
    foo = froms.CharField()
    bar = froms.CharField()

This can only create a form with a fixed number of fields. While there are ways to generate forms with variable number of fields, (generate the Form class programatically), they are not easy or well documented. (Remind me to write such tutorial sometime.)

Bonus question: How can you generate a form with same form elements multiple (and variable number) times, ala what happens with edit_inline?

Settings mixes application configuration which should be public and passwords, which should be private:
If I am distributing an app MIDDLEWARE_CLASSES is something which I would assume users would not (generally) modify. Similarly, in most of the cases, INSTALLED_APPS, would also be something which users would not change, (unless you are distributing standalone_apps). This means, I want to source control settings.py. But settings.py also contain my DB setiings, and SECRET_KEY, which means, I cannot source control settings.py.

And while we are at it, can we refactor settings.py, so it works without

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

Bonus:

Two things which used to bug me but no more. 1. You cannot extend Models - Well now you can if you use queryset-refactor, or soon can if you are on trunc. 2. Url configuration using regexes. - Now they have two problems. joke notwithstanding, mapping URLs to views is one problem where regexes fit the problem beautifully. With less that 50 lines of code, you can manage a large number of views, and Url patterns.

Friday, March 20, 2015

Google reCAPTCHA integration in Django




what is reCAPTCHA ?

reCAPTCHA is a free service to protect your website from spam and abuse. reCAPTCHA uses an advanced risk analysis engine and adaptive captcha to keep automated software from engaging in absive activities on your site. it does this while letting your valid users pass through with ease.

reCAPTCHA offers more than just spam protection. Every time our CAPTCHAs are solved. that
human effort helps digitize text,annotate images, and build machine learning datasets.This in turn helps preserve books,improve maps, and solve hard Al problems.

demo for reCAPTCHA in your website



How to integrate google reCAPTCHA with django ?

step 1 .  Install django-nocaptcha-recaptcha in your Virtual Environment

              pip install django-nocaptcha-recaptcha

step 2 . Configuration

          Add nocaptcha_recaptcha to your INSTALLED_APPS setting

          Add the following to settings.py

         Required settings:

         NORECAPTCHA_SITE_KEY  (string) = the Google provided site_key
         NORECAPTCHA_SECRET_KEY (string) = the Google provided secret_key

         reffer  this link : https://developers.google.com/recaptcha/intro


        Add the field to a form that you want to protect.

        from nocaptcha_recaptcha.fields import NoReCaptchaField

         class DemoForm(forms.Form):

                captcha = NoReCaptchaField()


       Add Google's JavaScript library to your base template or elsewhere, so it is available on the page        containing the django form.

      <script src="https://www.google.com/recaptcha/api.js" async defer></script>
 
      (optional) You can customize the field.

      You can add attributes to the g-recaptcha div tag through the following

      captcha = NoReCaptchaField(gtag_attrs={'data-theme':'dark'}))

      You can override the template for the widget like you would any other django template.


step 3 : Demo project

          Reffer my code : https://bitbucket.org/renjithsraj/googlecaptcha

       
   
     


   


     

Tuesday, March 10, 2015

Authentication with Social Medias in Django



Now no one waste the too much  for registration on a website , they need a flexible authentication  most popular is social-media( Facebook , Google Plus and twitter ).I needed to add Social media authentication to a Django app today, and instead of writing it directly against the Social Media API .I decided to look around and see if there’s a pre-packaged solution for this common task. Turns out, there’s an excellent project called Python Social Auth, and it covers pretty much any social website with an authentication API.. In this Blog, we will use Facebook, Twitter and Google, as the most common social APIs, but we could easily substitute them with LinkedIn, Yahoo  or a bunch of other providers supported by Python Social Auth library.
Django Version : 1.7.4

Step 1 :  Create a project 

         Here am create a project  called  SocialAuth

project in Tree Structre
         SocialAuth/
              manage.py
             SocialAuth/
                __init__.py
                 settings.py
                urls.py
                uwsgi.py
step 2 : Now, the very small customization's we’ll add are

  • Add ‘SocialAuth’ to INSTALLED_APPS
  • Create the template for the home page
  • Add a view for the home page
  • Add a URL pointing to the home page view

Relevant portion of settings.py:



INSTALLED_APPS = (

    'django.contrib.admin',

    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'SocialAuth',
)

set the static and template root and url in settings.py [ Reffer django Documentaion]

step 3 : Create a folder called templates

    Template: SocialAuth/templates/base.html:


 <!DOCTYPE html>

<html lang="en">
 <head>
   <meta charset="utf-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <title>{% block title %}Social Media Authentication Tutorial{% endblock %}</title>

   <!-- Bootstrap -->
   <link href="/static/css/bootstrap.min.css" rel="stylesheet">
   <link href="/static/css/bootstrap-theme.min.css" rel="stylesheet">
   <link href="/static/css/fbposter.css" rel="stylesheet">
 </head>
 <body>
   {% block main %}{% endblock %}
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
   <script src="/static/js/bootstrap.min.js"></script>
 </body>
 </html>


Template: SocialAuth/templates/index.html:


{% extends 'base.html' %}

{% block main %}
 <div>
 <h1>Social Media authentication demo</h1>

 <p>
   <ul>
   {% if user and not user.is_anonymous %}
     <li>
       <a>Hello {{ user.get_full_name|default:user.username }}!</a>
     </li>
     <li>
       <a href="{% url 'auth:logout' %}?next={{ request.path }}">Logout</a>
     </li>
   {% else %}
     <li>
       <a href="{% url 'social:begin' 'facebook' %}?next={{ request.path }}">Login with Facebook</a>
     </li>
     <li>
       <a href="{% url 'social:begin' 'google-oauth2' %}?next={{ request.path }}">Login with Google</a>
     </li>
     <li>
     <li>
       <a href="{% url 'social:begin' 'twitter' %}?next={{ request.path }}">Login with Twitter</a>
     </li>
   {% endif %}
   </ul>
 </p>
 </div>
{% endblock %}

step 4 : Create Views.py  inside your SocialAuth project directory

SocialAuth/Views.py



from django.shortcuts import render_to_response

from django.template.context import RequestContext


def home(request):
   context = RequestContext(request,'request': request,'user': request.user})
   return render_to_response('index.html',context_instance=context)


step 5 : Create a file called urls.py

 SocialAuth/urls.py 

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
   url(r'^$', 'SocialAuth.views.home', name='home'),
   url(r'^admin/', include(admin.site.urls)),
)

step 6 : Install  Python Scoial Auth

            pip install python-social-auth

step 7 :  Second, let’s make some modifications to our settings.py to include python-social-auth in our project:

     INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'thirdauth',
    'social.apps.django_app.default',
    )

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
    'django.template.loaders.eggs.Loader',
)

AUTHENTICATION_BACKENDS = (
   'social.backends.facebook.FacebookOAuth2',
   'social.backends.google.GoogleOAuth2',
   'social.backends.twitter.TwitterOAuth',
   'django.contrib.auth.backends.ModelBackend',
)

TEMPLATE_CONTEXT_PROCESSORS = (
   'django.contrib.auth.context_processors.auth',
   'django.core.context_processors.debug',
   'django.core.context_processors.i18n',
   'django.core.context_processors.media',
   'django.core.context_processors.static',
   'django.core.context_processors.tz',
   'django.contrib.messages.context_processors.messages',
   'social.apps.django_app.context_processors.backends',
   'social.apps.django_app.context_processors.login_redirect',
)

LOGIN_REDIRECT_URL = ' / ' ( root )


step 8 : Let’s update the urls module to include the new group of URLs : 

from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
   url(r'^$', 'thirdauth.views.home', name='home'),
   url(r'^admin/', include(admin.site.urls)),
   url('', include('social.apps.django_app.urls', namespace='social')),
   url('', include('django.contrib.auth.urls', namespace='auth')),(  add urls for looging in and looging out.)
)

step 8 : python manage.py migrate and run our project ( python manage.py runserver )

And then start adding API-specific parameters for social networks. Right this moment, if you click on any of the“login with X” links, you’ll get redirected to the corresponding social site, but will get an error about invalid client ID. That’s because we have not provided any client IDs yet.

Facebook

  • Go to https://developers.facebook.com/apps/?action=create and click the green “Create New App” button.
  • In the settings of the newly-created application, click “Add Platform”. From the options provided, choose Web, and fill in the URL of the site (http://127.0.0.1:8000/in our example).
  • Copy the App ID and App Secret, and place them into settings.py file:
  • SOCIAL_AUTH_FACEBOOK_KEY = …
  • SOCIAL_AUTH_FACEBOOK_SECRET = …
  • This should be enough to get your app to login with Facebook! Try logging in and out – you should get redirected between your app and FB OAuth2 service, and a new record in the User social auths table will get created, along with a new User record pointing to it.
Twitter 

Google 

  • Go to https://console.developers.google.com/ and create a new application.
  • Under APIs and Auth > Credentials, create a new Client ID.
  • Make sure to specify the right callback URL: http://127.0.0.1:8000/complete/google-oauth2/
  • Copy the values into settings file:
  • SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = …
  • SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = …

Conclusion

Python Social Auth can provide more than just authentication. 

                                                         <----- Thank You ------>


Thursday, March 5, 2015

Get start with Django ?


        
        ""GETTING START WITH DJANGO FRAMEWORK "" 


This Blog is about How to do Web Application in Django frame work with Linux 
Operating System , a Web development framework that saves you time and makes Web development a joy.Using Django, you can build and maintain high-quality Web applications with minimal fuss. With Django, you can take Web applications from concept to launch in a matter of hours. Django takes care of much of the hassle of Web development,so you can focus on writing your app without needing to reinvent the wheel. It’sfree and open source. 

Getting started with Django

     What you need for a basic dev environment:

    • Python 2.7.x or Python 3.4.x
    • easy_install and Pip
    • virtualenv
    • Django
    • Database (SQLite, MySQL, PostgreSQL, MongoDB, etc.)
    • Text editor (Sublime, vim, Komodo, gedit)
   Details for basic dev environment

  • Python

       Python is an easy to learn, powerful programming language. It has efficient  high-level data structures and a simple but effective approach to object-oriented programming. Python’s elegant syntax and dynamic typing, together with its   interpreted nature, make it an ideal language for scripting and rapid application              development in many areas on most platforms.More info : https://www.python.org/

  • Easy_install and Pip
     Easy Install and Pip is a python module (easy_install and pip ) bundled with setuptools that lets you automatically download, build, install, and manage Python packages.

  • Virtualenv
     A Virtual Environment is a tool to keep the dependencies required by different projects in separate places, by creating virtual Python environments for them. It solves the “Project X depends on version 1.x but, Project Y needs 4.x” dilemma, and keeps your global site-packages directory clean and manageable.virtualenv is a tool to create isolated Python environments.


  • Django
       Django is a free and open source web application framework, written in Python. It's a web framework - a set of components that helps you to develop websites faster and easier.Django's primary goal is to ease the creation of complex, database-driven websites. Django emphasizes reusability and "pluggability" of components, rapid development, and the principle of don't repeat yourself. Python is used throughout, even for settings, files, and data models. Django also provides an optional administrative create, read, update and delete interface that is generated dynamically through introspection and configured via admin models.

Django installation

Before we install Django, we'll get you to install an extremely useful tool that will help keep your coding environment tidy on your computer. It's possible to skip this step, but it's highly recommended not to - starting with the best possible setup will save you a lot of trouble in the future!
So, let's create a virtual environment (also called a virtualenv). It will isolate your Python/Django setup on a per-project basis, meaning that any changes you make to one website won't affect any others you're also developing.

Create a virtual Env Iinux Operating System

On Linux, pip will generally be available for the system install of python using the
system package manager, although often the latest version will be unavailable.
Install Pip (Python Package Index )

       Step1 : sudon apt-get install python-pip

       Install Virtual Env In your Local machine

       Step 2 : pip install virtualenv

      Create  Virtual Env 

      Step 3 :  

         step 1 :  mkdir global ( Create a global directory for Environment ) 
         step 2 : cd global ( Set the Dirctory Root ) 
         step 3 : virtualenv MYENV ( Environment Name )
         step 4 :   source global/MYENV/bin/activate(  Activate the Environment  )

     Installing Django

         Step 4 : pip install Django ( This command will install latest version for Django )

    Django Project setup

        Step 1 :  django-admin.py startproject myfirstproject ( project name )
                
                   myfirstproject/
                         manage.py
                         myproject/
                             __init__.py
                             urls.py
                             settings.py
                             wsgi.py

  These files are

  •  The outer myfirstproject/ root directory is just a container for your project.
  •  manage.py: A command-line utility that lets you interact with this  Django            project in various ways. You can read all the details about manage.py in                django-admin.py and manage.py
  • The inner myfirstproject/ directory is the actual Python package for your project. Its name is the Python package name you’ll need to use to import anything inside it (e.g. myproject.urls).
  • myfirstproject/__init__.py: An empty file that tells Python that this directory should be considered a Python package. 
  • myfirstproject/settings.py: Settings/configuration for this Django project. Django settings will tell you all about how settings work.
  • myfirstproject /urls.py: The URL declarations for this Django project; a “table of contents” of your Django- powered site. You can read more about URLs in URL dispatcher.
  • myfirstproject /wsgi.py: An entry-point for WSGI-compatible web servers to serve your project. See How to deploy with WSGI for more details.
Let’s verify your Django project works. Change into the outer mysite directory, if you haven’t already, and run the following command:

python manage.py runserver

You’ll see the following output on the command line:
Performing
system checks...
System check identified no issues (0 silenced).
March 05, 2015 - 07:45:37
Django version 1.7.4, using settings 'myfirstproject
.settings' Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Now
that the server’s running, visit http://127.0.0.1:8000/ with your Web browser. You’ll see a “Welcome to Django” page, in pleasant, light-blue pastel. It worked!





Create Your first App

Each application you write in Django consists of a Python package that follows a certain convention. Django
comes with a utility that automatically generates the basic directory structure of an app, so you can focus on
writing code rather than creating directories.

python manage.py startapp myfirstapp

            myfirstapp/
                __init__.py
                admin.py
                migrations/
                    __init__.py
                models.py
                tests.py
                views.py
                admin.py


Get Start With Django Project:

       I am going to start a simple project for personel blog webapplication , already i create a virtualenv MYENV , nowI am going to install little more packages in MYENV using Pip command.Pip install PIL , Pip install Pillow and Pip install django-imagekit ( this package for mangeing the Images )pip install ipython ( Ipython is a command shell for interactive computing in multiple programming languages, originally developed for the Python programming language )

Create a project :

         django-admin.py startproject myblog

create a application

         python manage.py startapp blog


myblog/settings.py

import os
def root(x):
return os.path.join(os.path.abspath(os.path.dirname(__file__)), '..',x)
SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
DJANGO_SETTINGS_MODULE="myblog.settings"
# Application definition
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'imagekit',
'PIL',
'json',
)
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': root('db.sqlite3'),
}
}
STATIC_URL = '/static/'
MEDIA_ROOT = root('media')
MEDIA_URL = '/media/'
STATIC_ROOT = root('staticstorage')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
root('static'),
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader',
)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.request',
'django.contrib.messages.context_processors.messages'
)
TEMPLATE_DIRS = [ root('templates')
]

myblog/urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
import settings
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('blog.urls', namespace="blog")),
) urlpatterns += patterns('',
url(r'^static/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.STATIC_ROOT, 'show_indexes': False}),
url(r'^media/(?P<path>.*)$', 'django.views.static.serve',{'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
) urlpatterns += staticfiles_urlpatterns()

myblog/blog/models.py
from imagekit.processors import ResizeToFill
from imagekit.models import ImageSpecField
# Create your models here.
class Blogs(models.Model):
b_name = models.CharField(max_length=200,null=True,blank=True)
heading = models.CharField(max_length = 500,verbose_name='Heading',null=True,blank=True)
date = models.DateField(verbose_name = "Published Date",null=True,blank=True)
category = models.CharField(max_length=200,verbose_name='Blog Category',null=True,blank=True)
publisher= models.CharField(max_length=200,verbose_name='Blog Publisher',null=True,blank=True)
mage = ProcessedImageField(upload_to='images/blog', options={'quality': 60},verbose_name = "Blog Image (828px X 363px)",null=True,blank=True)
b_content = models.TextField(verbose_name='Blog Content',null=True,blank=True)
active = models.BooleanField(default=True,verbose_name="Blog Active or Not")


def __str__(self): # __unicode__ on Python 2
return self.b_name


myblog/blog/admin.py
from django.contrib import admin
from .models import Blogs,
admin.site.register(Blogs)

Database Migration 

           python manage.py makemigrations blog
            python mange.py migrate

Create a Admin User
       python manage.py createsuperuser
       Enter your name : Admin
       password : qwerty

Run your Project

       python manage.py runserver

Now that the server’s running, visit http://127.0.0.1:8000/amin Enter username and password , then you can see the fields for adding blogs in myblog website. Add some data in to Blogs table

Create Your Views
myblog/blog/views.py
from django.shortcuts import render
from blog.models import Blogs
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def index(request):
all_blog = Blogs.objects.all().order_by('-id')
return render(request,'index.html',data)

myblog/blog/urls.py

from django.conf.urls import patterns, url
from blog import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
)
Create Template folder inside the myproject Directory ( if any static files is there in your template create a folder static inside the myproject for uplodaing staticfiles(css,js and etc ) , make sure if any static files is there you have to run the command Python manage.py collectstatic , this command will create a folder static storage , it have replica of static folder if any any chages you made in static files make sure run the command Python manage.py collectstatic,

Create a Template

myblog/blog/templates

index.html
<div class="content">
<div class="blog-section">
<div class="container">
<div class="col-md-8 left_column">
<h2 class="with-line">Blogs</h2> {%for blog in all_blog%}
<article class="clearfix">
<header class="grid_8 alpha">
<div class="head_element"><span class="el_1">{{blog.date|date:"d"}}</span><span class="el_2">{{blog.date|date:"b"}}</span>
</div>
<div class="sub">
<a href="single.html" class="readblog">{{blog.heading}}</a>
<p class="sub_head">Posted by <a href="#">{{blog.publisher}}</a>
</p>
</div>
<div class="clearfix"></div>
</header>
<div class="alpha1">
<a href="single.html"><img src="{{blog.image.url}}" alt="">
</a>
</div>
<div class="grid_b4">
<h5> category : {{blog.category}}</h5>
<p style="text-align:justify;">{{blog.b_content|truncatewords:50}}</p>
<a href="{% url 'blog:single' blog.id%}" class="btn btn-1 btn-1c">Read More</a>
</div>
<div class="clearfix"></div>
</article>
{%endfor%}
</div>
<div class="clearfix"></div>

Conclusion


      Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.

Workflow

      Now that your app is set up, follow either of these simple workflows every time you want to make changes to your app:

  • Navigate to your project
  • Activate virtualenv
  • Create and checkout a new git branch
  • Develop
  • Commit changes
  • Merge the new branch with your master branch
  • PULL the changes into the production folder
  • Deploy.