How I integrated Django with Blockchain and built a Decentralized Application(dapp)?
An effective guide for Python Developers to begin their Blockchain Development journey.
One can never deny the fact that the moment while working with DAPP development, one of the major challenges lies in connecting the smart contract with the front end of the website.
The most effective procedure is undoubtedly using Web3(Python or Javascript) library to do this for you. While this might be a lot easier for a Javascript developer to accomplish this part(since the internet is flooded with Web3.js tutorials ), it can be equally troublesome for a Python developer to do the same task.
Should you choose Web3.py?
Although it goes without saying that the Web3.js community is by far the larger one but Web3.py, on the other hand, with more than 1.5k stars on Github, 133 contributors as well as being used some really high profile Ethereum APIs is already mature enough and undoubtedly production-ready.
This simply means that it's high time for Python Developers to initiate their Blockchain-based DAPP Development journey with Web3.py.
However, the inception might be the toughest part since there isn’t enough help online for Python Developers online to build a decentralized application using Web3.py, except the official documentation(which is literally helpful), i.e., https://web3py.readthedocs.io/en/stable/.
Therefore, just in case you too are a Python Developer and wish to develop Decentralized Applications on Blockchain using Python, then this is going to be a must-read article for you.
With that being said, Let’s begin.
Tools Required
Before beginning, let’s understand the How I integrated Django with Blockchain and built a Decentralized Application(DAPP)? we will need for this project.
- Remix IDE: Remix is an open source tools that not only lets you write your smart contracts but also supports testing, debugging as well as deployment of smart contracts. Read the official documentation for more info: https://remix-ide.readthedocs.io/en/latest/.
- Infura: Infura is undoubtedly the tool that has made our lives a lot more simpler. In simpler terms, it comprises of a set of tools that allows anyone to interact with Ethereum Blockchain(which otherwise is an enormously troublesome task.)
3. Django 3.0: Well, this is the Python Framework that we will be working on.
Installation: $ python -m pip install Django
4. Web3.py: This is the tool that will allow us to talk to the smart contract and call its functions. Read the official documentation for more info: https://web3py.readthedocs.io/en/stable/quickstart.html
Installation: $ pip3 install web3
Let's connect to the Blockchain
To begin with, change the environment on Remix to Injected Web3 as shown below, and connect to Ropsten Network on Metamask.
Before getting started with actual web3.py interaction, let’s first setup a secure and reliable connection with blockchain.
Without Infura, it would literally have been a nightmare to even think about doing so. However, in the present scenario is fairly simple since all you need is an Infura API Key. Follow along with these steps to get the API Key- Get infura API Key
Once you get the API key and all the above-mentioned requirements installed, we are all set for the next step.
Note: In order to follow along with this project, you might want to get a Infura Key for the ROPSTEN Network.
CONNECT TO WEB3.PY AND INITIATE THE INTERACTION
While this code is already quite self-explanatory, there is not much to understand here. This is just a basic setup where I take a few imperative factors like
a. The Private and Public Keys for signing transactions
b.Creating a HTTPProvider for web3
c. Storing the contract’s ABI as well as address.
d. Creating a contract instance by passing the ABI and Address as parameters.
Alright! Now we have a reliable setup with our smart contract. However, before understanding how to make calls to the smart contract, let’s first understand what kind of calls can we possibly make in the first place.
What would you want from the Smart Contract?
While there can be a wide range of functionalities one can do, the 5 most imperative things you might want from a smart contract are as follows.
a. Calling a Getter function from the Contract(the LONG way):
While this might seem to be a bit complicated but this is what we call any getter function from the contract.
While this may seem to be a really lengthy procedure to follow, you can therefore go with the simple method of calling getter functions as mentioned below.
b. Calling a simple Read_Only Function(the SIMPLE way):
A read_only function within the contract can be seen as a function that only returns a particular data when called.
For example, this get_count function with the view keyword only returns the total number of posts when called.
function get_count() view public returns(uint){return postCount;}
In order to call, such functions we need to implement a simple line of code.
Well, that was pretty simple and that’s all we need to do.
c. Making a Transaction with a Function
Since we already know of Read_Only functions, there might be other functions in your contract that would ask for some arguments and then perform some functions.
Speaking in technical terms, calling such functions are seen as making a transaction since these type of function calls include Gas price along with it.
Let’s consider this function from the smart contract:
function createPost(string memory _content) public{require(bytes(_content).length > 0);postCount++;posts[postCount] = Post(postCount,_content,0,msg.sender);emit PostCreated(postCount,_content,0,msg.sender);}
Now this code takes the argument content from the user and later adds it to the list of posts. Now calling such a transaction would require some since the user is trying to update a particular data on the blockchain. Thus we are eventually making a transaction.
So how to make this transaction?
Well, that’s a complicated one. So let’s break it down.
As line 259 indicates, we aren’t calling the function createPost, rather we are building a transaction. However, as you see the buildTransaction functions take in a dictionary of data as an argument which is very imperative to understand.
a. chainId: Simply represents the network number we are connected to since each Ethereum Network has its own chain ID. In this case, 3 represents Ropsten Network.
b. gas: Since we already know each transaction requires gas to be executed. This parameter simply represents the highest amount of gas we are willing to pay for the execution of our transaction.
c. gasPrice: Gas price indicates the amount of gas to be paid in Wei per unit of Gas
d. nonce: This simply keeps the count of the previous transactions made by the user.
Once we build this transaction with all parameters filled as per our choice, now it's time for signing this transaction with the signTransaction function itself. This function takes the transaction as well as the private key as an argument.
Finally, we know a transaction is completed when we receive its transaction receipt using the waitForTransactionReceipt function. Once we get this receipt we can ensure that the record has been added to the blockchain successfully.
d. Making A Payment With Ether
Sending ether to a contract or a different account involves similar steps, as seen before, like building a transaction, signing it with private key as well as getting a confirmation receipt.
However, it does involve two additional fields like,
to: symbolizes the receiver of the payment
value: this is the amount to be transferred.
Well, that’s all you need to do in order to transfer funds from one account to another.
e. Calling an Event
Well, what is an event in the first place?
Events in Solidity may be seen as real time records in the form of transaction logs that are not only stored in blockchain but can also be accessed at any given time by the with the help of the address of the contract.
Although, I haven’t used any events in my code, the official documentation of Web3.py shows a clear procedure to call your events.
myContract = web3.eth.contract(address=contract_address, abi=contract_abi)tx_hash = myContract.functions.myFunction().transact()receipt = web3.eth.getTransactionReceipt(tx_hash)myContract.events.myEvent().processReceipt(receipt)
Alright. These are the most imperative calls that you might want to use while interacting with your smart contract.
Although we have quite clearly understood the recommended procedures to interact with a contract using web3.py and call for a particular function, there still lies one last thing to be understood, i.e., What do we do after the contract response back?
Since we are using Django Web Framework, there is a very strong need for us to understand how do we handle the responses of the contract and use it as per our need.
Handling Contract’s Responses in Django
There are 2 possible ways the contract might respond back.
First, you might have a made a transaction(added something to the Blockchain or made a payment). In this case, you will simple get back a transaction receipt. There is nothing more you would like to do with it since its just a confirmation that your transaction has executed.
Secondly, you might call a function that returns you a list of data. Well, this is what we are actually interested in.
So let’s understand the Second Case with the help of some codes I wrote to handle a similar situation.
This is literally a simple function, isn’t it?
Here, all we actually did was call the get_posts_from_contract() function. What does this function do? Although it's quite self-explanatory but have a look yourself.
Our smart contract has an array of data that contains all the posts from the users, their tipped amount as well as the address of the author. In this function, we simply call that array and return it.
Therefore, when the posts() function calls the get_post_from_smart_contract() function, it basically gets a nested list of data that looks something like this.
Pretty Ugly, right?
Now the most crucial question that arises is, How do we handle this list in our template?
Let’s Move To The Template Section in Django
Since the data from the contract is a nested list, the effective of handling a list of data in Django Template is:
{% for data in data_from_views.py %}
...
<h1>{{ data.0 }}</h2>
<h1>{{ data.1 }}</h2>...
{% endfor %}
And this is exactly how I handled it in my templates. The code is shown below:
LET’S WRAP UP
Well, you just learned the entire process of not only interacting with a smart contract with Python, but also handling its responses in the way we want.
As soon as you run the development server, the above template will be rendered and you can have a complete website that not only interacts with the blockchain but also let’s you write on it as well as make payments.
Great! So now that we are done, you can grab a cup of coffee and try this all over again by yourself.