Tumblelog by Soup.io
Newer posts are loading.
You are at the newest post.
Click here to check if anything new just came in.

February 17 2016

Python 3 in 2016

My completely anecdotal view on the state of Python 3 in 2016. Based on my own recent experience, observations, and exchanges with other members of the Python community.

February 15 2016

Wagtail: 2 Steps for Adding Pages Outside of the CMS

My first Caktus project went live late in the summer of 2015. It's a community portal for users of an SMS-based product called RapidPro. The portal was built in the Wagtail CMS framework which has a lovely, intuitive admin interface and excellent documentation for developers and content editors. The code for our Wagtail-based project is all open sourced on GitHub.

For this community portal, we needed to allow users to create blog pages on our front-facing site without giving those same users any level of access to the actual CMS. We also didn't want outside users to have to learn a new CMS just to submit content.

We wanted a simple, one-stop form that guided users through entering their content and thanked them for submitting. After these outside users requested pages be published on the site, CMS content editors could then view, edit, and publish the pages through the Wagtail CMS.

Here's how we accomplished this in two steps. Karen Tracey and I both worked on this project and a lot of this code was guided by her Django wisdom.

Step 1: Use the RoutablePageMixin for our form page and thank you page

Now for a little background information on Wagtail. The Wagtail CMS framework allows you to create a model for each type of page on your site. For example, you might have one model for a blog page and another model for a blog index page that lists out your blog pages and allows you to search through blog pages. Each page model automatically connects to one template, based on a naming convention. For example, if your model is called BlogIndexPage, you would need to also have a template called blog_index_page.html, so that Wagtail knows how to find the related template. You don't have to write any views to use Wagtail out of the box.

However, in our case, we wanted users to submit a BlogPage entry which would be a child of a BlogIndexPage. Therefore, we wanted our BlogIndexPage model to route to itself, to a submission page, and to a "thank you" page.

RapidPro blog workflow

This is where Wagtail's RoutablePageMixin came into play. Here's the relevant code from our BlogIndexPage model that routes the user from the list page to the submission page, then to the thank you page.

In models.py:

from django.template.response import TemplateResponse

from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.fields import RichTextField
from wagtail.contrib.wagtailroutablepage.models import RoutablePageMixin, route


class BlogIndexPage(RoutablePageMixin, Page):
    intro = RichTextField(blank=True)
    submit_info = RichTextField(blank=True)
    thanks_info = RichTextField(blank=True)

@route(r'^$')
def base(self, request):
      return TemplateResponse(
          request,
          self.get_template(request),
        self.get_context(request)
      )

@route(r'^submit-blog/$')
def submit(self, request):
      from .views import submit_blog
      return submit_blog(request, self)

@route(r'^submit-thank-you/$')
def thanks(self, request):
      return TemplateResponse(
          request,
          'portal_pages/thank_you.html',
          { "thanks_info" : self.thanks_info }
      )

The base() method points us to the blog index page itself. Once we added the RoutablePageMixin, we had to explicitly define this method to pass the request, template, and context to the related template. If we weren't using this mixin, Wagtail would just route to the correct template based on the naming convention I described earlier.

The submit() method routes to our blog submission view. We decided to use the URL string "submit-blog/" but we could have called it anything. We have a view method submit_blog() defined in our views.py file that does the work of actually adding the page to the CMS.

The thanks() method routes to the thank you page (thank_you.html) and passes in content editable via the CMS in the variable thanks_info as defined in the BlogIndexPage model.

Step 2: Creating the form and view method to save the user-generated information

Here's the slightly trickier part, because we didn't find any documentation on adding pages to Wagtail programmatically. We found some of this code by digging deeper through the Wagtail repo and found the tests files especially helpful. Here are the relevant parts of our code.

In forms.py, we added a Django ModelForm.

class BlogForm(forms.ModelForm):
    class Meta:
        model = BlogPage

In views.py, we created a view method called submit_blog() that does a number of things.

  1. Imports the BlogForm form into the context of the page.
  2. Upon submission/post, saves the BlogForm with commit=False, so that it is not saved to the database, yet.
  3. Creates a slug based on the title the user entered with slugify(). This would normally be auto-generated and editable in the Wagtail CMS.
  4. Adds the unsaved BlogPage as a child to the BlogIndexPage (we passed in the reference to the index page in our routable submit() view method).
  5. Saves the page with the unpublish() command which both saves the uncommitted data to our CMS and marks it as a Draft for review.
  6. Saves the revision of the page so that we can later notify the Wagtail admins that a new page is waiting for their review with save_revision(submitted_for_moderation=True)
  7. Finally, this sends out email notifications to all the Wagtail admins with send_notification(blog.get_latest_revision().id, 'submitted', None). The None parameter in this function means do not exclude any Wagtail moderators.
def submit_blog(request, blog_index):

      form = BlogForm(data=request.POST or None, label_suffix='')

      if request.method == 'POST' and form.is_valid():
          blog_page = form.save(commit=False)
          blog_page.slug = slugify(blog_page.title)
          blog = blog_index.add_child(instance=blog_page)
          if blog:
              blog.unpublish()
              # Submit page for moderation. This requires first saving a revision.
              blog.save_revision(submitted_for_moderation=True)
              # Then send the notification to all Wagtail moderators.
              send_notification(blog.get_latest_revision().id, 'submitted', None)
          return HttpResponseRedirect(blog_index.url + blog_index.reverse_subpage('thanks'))
      context = {
          'form': form,
          'blog_index': blog_index,
      }
      return render(request, 'portal_pages/blog_page_add.html', context)

Final Thoughts and Some Screenshots

Blog submission page

Front-end website for user submission of blog content.

Wagtail is very straightforward to use; we plan to use it on future projects. If you want to get started with Wagtail, the documentation is very thorough and well written. I also highly recommend downloading the open sourced demo site and getting that rolling in order to see how it's all hooked together.

Climbing up Branches

Today I pushed the latest Evennia development branch "wclient". This has a bunch of updates to how Evennia's webclient infrastructure works, by making all exchanged data be treated equal (instead of treating text separately from other types of client instructions).

It also reworks the javascript client into a library that should be a lot easier to expand on and customize. The actual client GUI is still pretty rudimentary though, so I hope a user with more web development experience can take upon themselves to look it over for best practices.

A much more detailed description of what is currently going on (including how to check out the latest for yourself) is found in this mailing list post. Enjoy!

February 13 2016

Django "view-permissions" for related objects

Django "view-permissions" for related objects

Building an RSS feed for Django

This RSS using Rss201rev2Feed from Django. And we found it from source code of blog.pythonanywhere.com: https://github.com/pythonanywhere/jab/blob/master/jab/feeds.py

Demo: http://django.id/blog/feed/

Using jsPDF in Django templates to export as PDF

Using jsPDF in Django templates to export as PDF

jsPDF is used to generate pdf files in client-side Javascript.

You can find the links for jsPDF here and also you can find the link to project homepage.

You've to include the scripting files/links in head section to work properly.

Tip: We have to download the newest version of the library and include it in the HEAD or at the end of the BODY section.

Example to run the script from local storage:

In the HEAD section:

<head>
    <script src="js/jspdf.js">script>
head>

(or)

In the BODY section:

<body>
    
    
    <script src="js/jspdf.js">script>
    <script src="js/main.js">script>
body>

After loading the scripts in HEAD/BODY section, now we can start using the jsPDF library.

Lets start with some of basics of jsPDF to get the idea of using it in our applications:

First let us discuss how to create a new document?

It's simple as below mentioned:

var doc = new jsPDF(orientation, unit, format, compress);

The constructor can take several parameters.

  • orientation - The default value of orientation is "portrait". We can set it to "landscape" if we want a different page orientation.
  • unit - We can tell jsPDF in which units we want to work. Use on of the following: "pt" (points), "mm" (default), "cm", "in".
  • format - It's default page format. We can change it we want other formats also like: "a3", "a4" (default), "a5", "letter", "legal".

As an order to understand, here is an example:

var doc = new jsPDF('landscape');
doc.text(20, 20, 'Hello landscape world!');

We can add new page using the following code:

doc.addPage(width, height);

As parameters we can pass the page width and height in the units defined in the docuent constructor. Adding pages moves us to this page, so many operations will be executed on that page. If we want to go to another page we can use the setPage function.

doc.setPage(pageNumber);

You can also get the actual number of pages by using the below code:

doc.internal.getNumberOfPages();

In an order to understand, here is an example:

var doc = new jsPDF();
doc.text(20, 20, 'Hello world!');
doc.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');
doc.addPage('a6','l');
doc.text(20, 20, 'Do you like that?');

 Now it's time to work with text:

1. The most important thing is displaying text, we do it using the funtion named doc.text which takes 3 parameters. like below:

doc.text(X, Y, "Text to be displayed");

- The first two are X and Y positions of the text in units defined in the document constructor.

* Here we have to notice a point: Y position, it is the position of the text baseline, so printing something with the Y position set to 0 will actually print it over the top edge of the document.

- The third argument is the text to be displayed.

2. The second thing is the font name used to draw the text. We can choose one of the following: couriertimesarial. We can change the font family and font style by running the doc.setFont function.

doc.setFont("arial", "bold");

By executing the doc.getFontList function we can find out what fonts are available and what font styles we can set for given font.

doc.getFontList();
/*
{
    "courier": ["normal", "bold", "italic", "bolditalic"],
    "Courier": ["", "Bold", "Oblique", "BoldOblique"],
    "times": ["normal", "bold", "italic", "bolditalic"],
    "Times": ["Roman", "Bold", "Italic", "BoldItalic"],
    "helvetica": ["normal", "bold", "italic", "bolditalic"],
    "Helvetica": ["", "Bold", "", ""] 
}
*/

We can also change the font style individually by using the doc.setFontStyle or the doc.setFontType function, which is alias to the first one.

doc.setFontType("bolditalic");
// is the same as calling
doc.setFontStyle("bolditalic");

3. Next things is the font size. Now, for that we use doc.setFontSize function.

doc.setFontSize(40);

Example:

var doc = new jsPDF();
doc.setFontSize(22);
doc.text(20, 20, 'This is a title');

doc.setFontSize(16);
doc.text(20, 30, 'This is some normal sized text underneath.');

4. Last but not the least, the text color. We can change the text color using the doc.setTextColor function and passing three parameters which are RGB (Red, Green, Blue) color values.

var doc = new jsPDF();
// I know the proper spelling is colour ;)
doc.setTextColor(100);
doc.text(20, 20, 'This is gray.');

doc.setTextColor(150);
doc.text(20, 30, 'This is light gray.');

doc.setTextColor(255, 0, 0);
doc.text(20, 40, 'This is red.');

doc.setTextColor(0, 255, 0);
doc.text(20, 50, 'This is green.');

doc.setTextColor(0, 0, 255);
doc.text(20, 60, 'This is blue.');

In a order of full example:

var doc = new jsPDF();

doc.text(20, 20, 'This is the default font.');

doc.setFont("courier");
doc.setFontType("normal");
doc.text(20, 30, 'This is courier normal.');

doc.setFont("times");
doc.setFontType("italic");
doc.text(20, 40, 'This is times italic.');

doc.setFont("helvetica");
doc.setFontType("bold");
doc.text(20, 50, 'This is helvetica bold.');

doc.setFont("courier");
doc.setFontType("bolditalic");
doc.text(20, 60, 'This is courier bolditalic.');

Now it's time to work with Images:

We have only function for the images is the doc.addImage. It takes image as a first parameter, image format/type as a second and X,Y positions of the image as a third and fourth arguments respectively. Here we can also optionally pass new image size as a fifth and sixth arguments.

var img = new Image();
img.addEventListener('load', function() {
    var doc = new jsPDF();
    doc.addImage(img, 'png', 10, 50);
});
img.src = 'image_path/image_name.png';

In the above example, we passed an Image HTML DOM element as a first argument of the addImage function, however it can also be a base64 encoded image string.

var imgData = 'data:image/jpeg;base64,/.......base64code.....iiigAoooo//2Q==';
var doc = new jsPDF();
doc.setFontSize(40);
doc.text(35, 25, "Octonyan loves jsPDF");
doc.addImage(imgData, 'JPEG', 15, 40, 180, 180);

Working With Graphics:

First of all, we have to set the drawn shapes fill and stroke with colors. We do it using the doc.setFillColor and the doc.setDrawColor accordingly, passing RGB color values as parameters. 

doc.setFillColor(100, 100, 240);
doc.setDrawColor(100, 100, 0);

We can also set the stroke width. The stroke width unit is the same as defined in the document constructor.

doc.setLineWidth(1);

Every shape drawing function takes the center point co-ordinates (triangle is the only exception) as two first parameters. They also take the last parameter for drawing style. It can be "S", "F", "DF", "FD" string and the meanings are: "stroke", "fill", "stroke and fill", "fill and stroke". The last two of course differ in the order of the drawing operations.

For example, we can draw an ellipse, by passing two radiuses :

// Empty ellipse
doc.ellipse(50, 50, 10, 5);
// Filled ellipse
doc.ellipse(100, 50, 10, 5, 'F');
// Filled circle with borders

or a circle, by passing only one radius as parameter :

doc.circle(150, 50, 5, 'FD');

or a rectangle, by passing it's width and height as parameters :

var doc = new jsPDF();

// Empty square
doc.rect(20, 20, 10, 10); 

// Filled square
doc.rect(40, 20, 10, 10, 'F');

// Empty red square
doc.setDrawColor(255,0,0);
doc.rect(60, 20, 10, 10);

// Filled square with red borders
doc.setDrawColor(255,0,0);
doc.rect(80, 20, 10, 10, 'FD'); 

// Filled red square
doc.setDrawColor(0);
doc.setFillColor(255,0,0);
doc.rect(100, 20, 10, 10, 'F'); 

 // Filled red square with black borders
doc.setDrawColor(0);
doc.setFillColor(255,0,0);
doc.rect(120, 20, 10, 10, 'FD');

or a rounded rectangle, by passing it's width, height and border radius as parameters : 

// Filled sqaure with rounded corners
doc.roundedRect(50, 150, 10, 10, 3, 3, 'FD');
// Black sqaure with rounded corners
doc.setDrawColor(0);
doc.setFillColor(255, 255, 255);
doc.roundedRect(140, 20, 10, 10, 3, 3, 'FD'); 

and a triangle, by passing each corners co-ordinates.

// Filled triangle with borders
var doc = new jsPDF();
doc.triangle(60, 100, 60, 120, 80, 110, 'FD');
doc.setLineWidth(1);
doc.setDrawColor(255,0,0);
doc.setFillColor(0,0,255);
doc.triangle(100, 100, 110, 100, 120, 130, 'FD');

Last but not least, we can also draw lines passing through the co-ordinates of two points.

// Line
doc.line(50, 250, 100, 250);

Here is an example and some of functionalities we can apply on lines:

var doc = new jsPDF();

doc.line(20, 20, 60, 20); // horizontal line
 
doc.setLineWidth(0.5);
doc.line(20, 25, 60, 25);

doc.setLineWidth(1);
doc.line(20, 30, 60, 30);

doc.setLineWidth(1.5);
doc.line(20, 35, 60, 35);

doc.setDrawColor(255,0,0); // draw red lines

doc.setLineWidth(0.1);
doc.line(100, 20, 100, 60); // vertical line

doc.setLineWidth(0.5);
doc.line(105, 20, 105, 60);

doc.setLineWidth(1);
doc.line(110, 20, 110, 60);

doc.setLineWidth(1.5);
doc.line(115, 20, 115, 60);

Here is a full example to understand in a better way:

var doc = new jsPDF();

doc.ellipse(40, 20, 10, 5);

doc.setFillColor(0,0,255);
doc.ellipse(80, 20, 10, 5, 'F');

doc.setLineWidth(1);
doc.setDrawColor(0);
doc.setFillColor(255,0,0);
doc.circle(120, 20, 5, 'FD');

Now, we are going to know about an interesting functionality over here - addHTML():

The below example will show you a preview of the html document that you've added this jsPDF script to generate pdf. This will generate the pdf as shown in the browsers.

var pdf = new jsPDF('p','pt','a4');

pdf.addHTML(document.body,function() {
 var string = pdf.output('datauristring');
 $('.preview-pane').attr('src', string);
});

The below example code will render the html and dispalys as plain text.

var doc = new jsPDF();

// We'll make our own renderer to skip this editor
var specialElementHandlers = {
 '#editor': function(element, renderer){
  return true;
 }
};

// All units are in the set measurement for the document
// This can be changed to "pt" (points), "mm" (Default), "cm", "in"
doc.fromHTML($('body').get(0), 15, 15, {
 'width': 170, 
 'elementHandlers': specialElementHandlers
});

We can also add Metadata to our Generating pdf:

var doc = new jsPDF();
doc.text(20, 20, 'This PDF has a title, subject, author, keywords and a creator.');

// Optional - set properties on the document
doc.setProperties({
 title: 'Title',
 subject: 'This is the subject',
 author: 'Author Name',
 keywords: 'generated, javascript, web 2.0, ajax',
 creator: 'Creator Name'
});

// Output as Data URI
doc.save('Test.pdf');

For the people who want a full script with an example:

1. Add the following script to the HEAD:

<script src="http://mrrio.github.io/jsPDF/dist/jspdf.debug.js">--script>

or Download Locally

2. Add HTML script to execute jsPDF code:

Customize this to pass the identifier or just change the #content to be the identifier you need.

<script>
    function demoFromHTML() {
        var pdf = new jsPDF('p', 'pt', 'letter');
        // source can be HTML-formatted string, or a reference
        // to an actual DOM element from which the text will be scraped.
        source = $('#content')[0];

        // we support special element handlers. Register them with jQuery-style 
        // ID selector for either ID or node name. ("#iAmID", "div", "span" etc.)
        // There is no support for any other type of selectors 
        // (class, of compound) at this time.
        specialElementHandlers = {
            // element with id of "bypass" - jQuery style selector
            '#bypassme': function (element, renderer) {
                // true = "handled elsewhere, bypass text extraction"
                return true
            }
        };
        margins = {
            top: 80,
            bottom: 60,
            left: 40,
            width: 522
        };
        // all coords and widths are in jsPDF instance's declared units
        // 'inches' in this case
        pdf.fromHTML(
        source, // HTML string or DOM elem ref.
        margins.left, // x coord
        margins.top, { // y coord
            'width': margins.width, // max width of content on PDF
            'elementHandlers': specialElementHandlers
        },

        function (dispose) {
            // dispose: object with X, Y of the last line add to the PDF 
            //          this allow the insertion of new lines after html
            pdf.save('Test.pdf');
        }, margins);
    }
>

3. Add your body content to generate as PDF:

<a href="javascript:demoFromHTML()" class="button">Generate PDFa>
<div id="content">
    <h1>
        Here is a complete example to generate a pdf using jsPDF.
    h1>
>

 

Creating Django App

Django:

Django is a high-level Python Web framework that encourages rapid development.
Install django in virtualenv to keep it safe from messing around with the other versions you may have.
$ virtualenv env
$ env/bin/activate
$ pip install django

If Django is installed, you can see the version of our installation by running following command 

    $ python -c "import django; print(django.get_version())"

otherwise you get an error “No module named django”

Creating a Project:

If this is your first time using Django, you’ll need to auto-generate code that establishes a Django Project
 A collection of settings, 
 Including database configuration, 
 Django-specific options and application-specific settings.

With the following command:

    $ django-admin.py startproject myproject

This will Create "myproject" directory in your current directory.The above command(startproject) creates

  myproject/
    |- manage.py
    |- myproject/
         |- __init__.py
         |- settings.py
         |- urls.py
         |- wsgi.py

The outer "myproject/" root directory is where your project is stored.

manage.py:

It is automatically created in each Django project. manage.py is a thin wrapper around django-admin.py before delegating to django-admin.py.It puts your project’s package on sys.path,Sets the DJANGO_SETTINGS_MODULE environment variable so that it points to your project’s settings.py file,  Calls django.setup() to initialize various internals of Django.

The inner "myproject/" directory is the actual Python package for your project.

myproject/__init__.py:

An empty file that tells Python, this directory should be considered a Python package.

myproject/settings.py:

Settings/configuration for this Django project. 

myproject/urls.py:

The URL declarations for Django project

myproject/wsgi.py:

An entry-point for WSGI-compatible web servers to serve your project.

Database setup:

By default, SQLite is included in Python, so you won’t need to install anything to support your database.If you wish to use another database, install the appropriate database, and change ENGINE and NAME keys in the DATABASES to match your database connection settings

 
ENGINE – example: 'django.db.backends.sqlite3'

NAME – The name of your database. 

INSTALLED_APPS

INSTALLED_APPS holds the names of all Django applications that are activated in this Django instance. By default, INSTALLED_APPS contains the following applications:

django.contrib.admin – The admin site. django.contrib.auth – An authentication system. django.contrib.contenttypes – A framework for content types. django.contrib.sessions – A session framework. django.contrib.messages – A messaging framework. django.contrib.staticfiles – A framework for managing static files.

<.pre

Before using these applications you need to create a database by running the following command

$ python manage.py migrate

The migrate command looks at the INSTALLED_APPS setting and creates necessary database tables according to the database settings in your myapplication/settings.py file.

Creating an App:

To create your app, make sure you’re in the same directory as manage.py and type this command:


 

$ python manage.py startapp myapp   #This creates a directory myapp

  myapp/
    |-migrations/
        |- __init__.py
    |-__init__.py
    |-admin.py
    |-models.py
    |-tests.py
    |-views.py

In our myapp application,create one Model: An Article has publication_date,title and content.

Edit the myapp/models.py file

Example:
  from django.db import models
  class Article(models.Model):
    publication_date = models.DateField()
    title = models.CharField(max_length=50)
    content = models.TextField(max_length=200)

Activating models: First you need to tell your project that "myapp" app is installed.so,Include your app name(myapp) in INSTALLED_APPS of settings.py file

  INSTALLED_APPS = ( 'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)

 

Now,run following command:

$ python manage.py makemigrations myapp

By running makemigrations, you’re telling Django that you’ve made some changes to your models. Now, run migrate again to create those model tables in your database:

 $ python manage.py migrate

For writting view. Open the file myapp/views.py and write your code:
Example:
    

    from django.http import HttpResponse
    def index(request):
        return HttpResponse("Hello,You're at the myapp index.")

To call the view, we need to map it to a URL we need a URLconf.To create a URLconf in the "myapp" directory, create a file called urls.py
Now your app looks like:

    myapp/
        |-__init__.py
        |-admin.py
        |-models.py
        |-tests.py
        |-urls.py
        |-views.py

Example:myapp/urls.py


 

from django.conf.urls import patterns, url from polls import views

urlpatterns = patterns('myapp.views', url(r'^$', index, name='index'),)

The next step is to point the root URLconf at the myapp.urls module. In myproject/urls.py insert an include()

Example:

myproject/urls.py


 

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

from django.contrib import admin

urlpatterns = patterns('', url(r'^myapp/', include('myapp.urls')), url(r'^admin/', include(admin.site.urls)),   )

The development server:

To start Django Development server change into your outer directory and run the following command


 

$ python manage.py runserver

Now Go to http://localhost:8000/myapp/ in your browser,you will see the text which you defined in the index view.       

“Hello,You’re at the myapp index.”

django Payu Payment gateway Integration

In this blog, we will see how to integrate Django and PayU Payment Gateway. To integrate with PayU, we have package called "django-payu" - a pluggable Django application.

GitHub Repository: django-payu

Documentaion: django-payu.readthedocs.org

Install:

$ pip install django-payu

Integration Process:

1. To start the integartion process, you need test merchant account and test credit card credentials to have the experience of overall transaction flow.

  • Once you create the account with PayU, they will provide SALT and KEY, we need this two credentials for the integration.

    NOTE: Here, you need to make the transaction request to the test-server and not on the production-server. Once you are ready and understood the entire payment flow, you can move to the production server.

2. To initialise the transaction, you need to generate a post request to the below urls with the parameters mentioned below

  • For PayU Test Server: POST URL: https://test.payu.in/_payment
  • For PayU Production (LIVE) Server: POST URL: https://secure.payu.in/_payment
  • Parameters to be posted by Merchant to PayU in transaction request are:
    • key (Mandatory), txnid (Mandatory), amount(Mandatory), productinfo(Mandatory), firstname(Mandatory), email (Mandatory), phone (Mandatory), lastname, udf1-udf5, address1, address2, city, state, country, zipcode, surl(Mandatory), furl(Mandatory), curl(Mandatory), hash(Checksum)(Mandatory): sha512(key|txnid|amount|productinfo|firstname|email| udf1|udf2|udf3|udf4|udf5||||||SALT)
  • NOTE:
    • udf : User defined field
    • surl : Sucess URL (Success redirection URL)
    • furl : Failure URL (Failure redirection URL)
    • curl : Cancel URL (Cancel redirection URL)
    • hash(Checksum) : A checksum is generated by a mathematical function using the Merchant ID(key), message and the Salt as input. The Checksum algorithm used is SHA512.

3. Add the following information in the setting file using the details from your PayU account:

PAYU_MERCHANT_KEY = "Your MerchantID",

PAYU_MERCHANT_SALT = "Your MerchantSALT",

# Change the PAYU_MODE to 'LIVE' for production.
PAYU_MODE = "TEST"

4. When the user click on the checkout button in your template, generate the mandatory parameter named "hash" using the get_hash() method.

from payu import get_hash
from uuid import uuid4

data = {
    'txnid':uuid4().hex, 'amount':10.00, 'productinfo': 'Sample Product',
    'firstname': 'test', 'email': 'test@example.com', 'udf1': 'Userdefined field',
}
hash_value = get_hash(data)

5. Then, send a post request to the PayU server using the HTML form filled with the data submitted by the buyer containing all the fields mentioned above.

6. When the transaction "post request" hits the PayU server, a new transaction is created in the PayU Database. For every new transaction in the PayU Database, a unique identifier is created every time at PayU’s end. This identifier is known as the PayU ID (or MihPayID).

7. Then the customer would be re-directed to PayU’s payment page. After the entire payment process, PayU provides the transaction response string to the merchant through a "post response". In this response, you would receive the status of the transaction and the hash.

8. Similar to Step 4, you need verify this hash value at your end and then only you shouls accept/reject the invoice order. You can verfy this hash using check_hash() method.

from django.http import HttpResponse
from payu import check_hash
from uuid import uuid4

def success_response(request):
    hash_value = check_hash(request.POST)
    if check_hash(request.POST):
        return HttpResponse("Transaction has been Successful.")

In this "django-payu" package, there are many other functions to Capture, Refund, Cancel etc., For the detailed documentation, See here.

February 12 2016

open file

open file in text editor

February 11 2016

CSV Files - Read and Create

CSV files seem to be what some companies live by. Because of that we need to know how to work with them. In this video learn the basics of using csv reader, writer, DictReader, and DictWriter
Watch Now...

February 10 2016

Special Offer for the Readers of DjangoTricks Blog

Django app/project/directory po messages collector and pofile bulder

Some times if third party application is not translated competelly, developer have to extract and save all of i18n strings of third party application to current project, somewhere in root project directory (and configure additional LOCALE_DIRS entry) or in any project's applications (usually named "main" or same as project ...

Older posts are this way If this message doesn't go away, click anywhere on the page to continue loading posts.
Could not load more posts
Maybe Soup is currently being updated? I'll try again automatically in a few seconds...
Just a second, loading more posts...
You've reached the end.

Don't be the product, buy the product!

Schweinderl