What are Data Access Object and Data Transfer Object in Python?

Ajay Last Updated : 06 Feb, 2023
8 min read

Introduction

A design pattern is simply a repeatable solution for problems that keep on reoccurring. The pattern is not an actual code but a template that can be used to solve problems in different situations. Especially while working with databases, it is often considered a good practice to follow a design pattern. This ensures easy switching between the databases in our applications. There are three types of database design patterns, they are:

  1. Object Relational Mapping (ORM)
  2. Entity-Attribute-Value (EAV) pattern
  3. Model-View-Controller (MVC) pattern.

ORM’s function is to map the data represented in an object-oriented form to the database. DAO (Data Access Object) and DTO (Data Transfer Object) patterns are used in Object Relational Mapping. DAO acts as a bridge between the database and the application. DTO acts as a data store from where the data is received and transferred to different layers i.e., to the DAO application.

In this article, we will look at DAO (Data Access Object) and DTO (Data Transfer Object), especially in Python. We will follow a practical approach to understand these concepts better.

Learning Objectives

  1. To understand the concept of DAO
  2. To understand how DTO works
  3. To be able to combine DAO and DTO in your application
  4. To understand how isolating DAO from application makes switching databases easier

This article was published as a part of the Data Science Blogathon.

Table of Contents

  1. Setting up the Workspace
  2. What are Data Access Objects?
  3. What are Data Transfer Objects?
  4. Implementing both DAO and DTO
  5. Conclusion

Setting up the Workspace

In this section, we will set up the coding workspace, so it can be easier for you to follow along with me. You can use any code editor of your choice and any database of your choice. I am going to use Visual Studio Code as my editor and Redis as my database.

We will be working with three python files. One file for DTO, one for DAO, and the main code i.e. application code. Create a new folder and inside the new folder, create three new .py files as follows.

File Directory

What are Data Access Objects?

In this section, we will learn what Data Access Objects (DAO) is and will also try to implement DAO in Python, using Redis as a database. You can try it out using any database either Relational or NoSQL.

DAO (Data Access Object) is a pattern that acts as an abstraction between the database and the main application. It takes care of adding, modifying, retrieving, and deleting the data and you do not need to know how it does this, that’s what an abstraction is. DAO is implemented in a separate file. Then these methods are called in the main application. That’s how it works.

Let’s write a simple StudentDAO class, which takes in data and adds it to the database. Also, it retrieves data from the database.

import redis

class StudentDAO:
    def __init__(self):
        self.client = redis.Redis(host='localhost', port=6379, decode_responses=True)
    def add_student(self, school,student_name):
        self.client.sadd(school,student_name)
    def get_all_student(self, school):
        data = self.client.smembers(school)
        print(data)

The first step in writing the DAO class is defining the init method, where we specify the database connection that we want to use. As I’m using Redis, I create a Redis client in the init method. If you are using MySQL, then you would be using something like MySQL.connector.connect(user=’user’, password=’password’, host=’host’, database=’database’)

Then, we have defined two methods. One is the add_student() method, which takes the school and student_name as parameters. Then we create a set with the name of the school and add the student’s name to the set. This is saved to the Redis server.

The get_all_student() method, takes the school as a parameter and retrieves all the student names from that particular school set. So this DAO class we defined can be used to add a student name to a set with the school’s key name in Redis Server and retrieve all the students’ names from a particular school.

Now, let’s test our StudentDAO class. As we know that all the application code goes in the main.py; let’s now write some code in the main.py to access this StudentDAO and add data to our database. This can be done as follows:

from dao import StudentDAO

student_dao = StudentDAO()
student_name = "Lary"
student_dao.add_student("School:Hindenburg",student_name)
student_dao.get_all_student("School:Hindenburg")

So, we import our StudentDAO into the main.py, create an instance, and assign it to the student_dao variable. Let’s try adding a student named Lary from Hindenburg School to our database. For this, we store the name in a variable student_name. Then we call the add_student() method by passing the school and the student_name as the parameter.

If everything works out well, the add_student() method should have added Lary to the set having the key name School: Hindenburg to the Redis server. Now let’s try to retrieve it. For this, we already defined a function called get_all_student(). I will now call the get_all_student() command by passing the school name as a parameter.

The following is the output after running the main.py

{'Lary'}

So StudentDAO has managed to add data to our database successfully and also retrieve it. It acts as an abstraction layer between Redis Server and the main.py.

Data Access Object

Data Access Object in Action

Now, what if you want to change the database due to unforeseen circumstances? All you do is create a new DAO class. The main.py remains the same as it has nothing to do with the database, as the DAO class does everything. You will have to change the add_student() and the get_all_student() methods in the dao.py without disturbing the main.py This saves us a lot of time. If we were to write the entire code in a single file without using the dao class and directly adding the data to the database, it would make a mess when we want to change it to another database. We would have to change the entire file, which is tedious.

What are Data Transfer Objects?

Data Transfer Object (DTO) can be assumed as a data store. It’s used to transfer data between different layers. The only work of a Data Transfer Object is to get the data and transfer it. So it consists of the getters and setters method.

The above section shows how to store data in the Redis Server using the Data Access Object. Now, where does the DTO fit in here? In the above, we are sending data from main.py to StudentDAO class. Here instead of sending data from the application code to the dao.py, we can send the data from the application code, i.e. from main.py to a DTO class, and the data from DTO will go to DAO class, which then upload it to the database.

You might wonder why we are sending the data from our main file to DTO and from DTO to DAO instead of sending it directly to the DAO. In some situations, the data needs to be serialized or deserialized before sending it to the database or at the time of retrieving it from the database. This serialization and deserialization might differ from database to database. So when we change the database, we need to change the DAO and the main.py.

So instead, we can create a separate DTO class that handles all this for us. So the data from main.py is sent to a DTO object, then the DTO object serializes the data, and this DTO object is given as input to the DAO, which takes this data and saves it to the server. The opposite happens when we want to retrieve the data. Let’s try it out

dto.py

class StudentDTO:
    def __init__(self,school,student_name):
        self.school = school
        self.student_name = student_name
    def getall(self):
        school = self.school
        students = list(self.student_name)
        return {"School": school, "Students":students}

We created a StudentDTO which stores the school and student_name information at the time of instantiation. Also, it has a getall() method, which gets all the students from a given school and returns it as a dictionary. The output we get from the Redis is in the form of a set. But here, we are converting the set of student names to a list and passing this list as a value in the dictionary. So we are modifying the data before sending it to the main file.

Implementing both DAO and DTO

In this section, we will change the dao.py and main.py so the DAO object can call the DTO object to transfer the data from the main file to the database.

The following changes are made to the dao.py:

import redis
from dto import StudentDTO

class StudentDAO:
    def __init__(self):
        self.client = redis.Redis(host='localhost', port=6379, decode_responses=True)
    def add_student(self, student_dto):
        self.client.sadd(student_dto.school,student_dto.student_name)
    def get_all_student(self, school):
        data = self.client.smembers(school)
        return StudentDTO(school,data).getall()

Initially, when we first wrote dao.py, we passed school and student_name parameters directly to the add_student() function. Now instead of doing that, we are passing the StudenDTO object i.e. student_dto, to the add_student() function, which contains both the school and student name.

Also in the get_all_student() method, we retrieve all the student names and give them to the StudentDTO object, and call the getall() method, which returns a dictionary containing the school name and the list of students. Now for all this to take place, we also need to make appropriate changes in the main file.

from dao import StudentDAO
from dto import StudentDTO

student_dao = StudentDAO()

student1= "Lary"
student2 = "Mike"
school = "School:Hindenburg"

stud1 = StudentDTO(school,student1)
stud2 = StudentDTO(school,student2)

student_dao.add_student(stud1)
student_dao.add_student(stud2)

student_names = student_dao.get_all_student("School:Hindenburg")
print(student_names)

Now let’s walk through the code to see how it’s working. First, we instantiate a StudentDAO() object. We also create two variables to store two student names and a single variable to store the school name.

Now the data from main.py needs to flow to the dao.py through the dto.py as DTO is responsible for transferring data from one part to another. So we create two StudentDTO objects, one for each name. Now the data has moved from the application file to the DTO file. Now we will call the add_student() method by passing the StudenDTO objects to it. The DAO then retrieves the data stored in DTO in the add_student() method. At the same time, it adds this data to the Redis Server.

Finally, let’s retrieve the data from the server. For this, we call the get_all_object() method of the student_dao object by passing the school name. This gets all the students as a set and stores them in variable data. This variable is passed to the StudentDTO object. So the data that DAO fetched from the Redis Server is moved from DAO to DTO. The getall() function of the StudentDTO object is called. This function fetches the students’ names, converts them into a list, and returns them as a dictionary.

This dictionary is now finally stored in the student_names variable in the main.py. So the data which is passed from DAO to DTO has undergone some changes (it was converted into a dictionary), and finally, from DTO, the data moved to the main.py

The contents of this variable are finally printed. The output generated is as follows

{‘School’: ‘School:Hindenburg’, ‘Students’: [‘Lary’, ‘Mike’]}

Data Access Object

DAO and DTO in action

This is just a glimpse of how the DTO can be used to transfer data between different layers like here, between the DAO and the application that is the main file. In our case, the application stores the data in DTO. Then the DAO access this data in DTO and then saves it in the database. Then when retrieving the data, the DAO sends the data to the DTO. Then finally, the application obtains the data from the DTO. As I have mentioned before, data serialization can be used in DTO before sending it to the other layers.

Conclusion

In conclusion, the DAO (Data Access Object) pattern acts as an abstraction between the database and the main file, whereas the DTO(Data Transfer Object) is used to transfer the data between these layers. DTO is useful when you want to make changes to the data format before it is saved in the database or at the time of retrieving. And the combination of them is employed in an application for best practices and easy database switching.

The following are the key takeaways from this article:

  • The DAO provides the encapsulation of the database-specific code, that is, it is isolated from the main program.
  • The DTO acts as a data store that moves the data from one layer to another.
  • Both DAO and DTO can be combined to make a more maintainable code.
  • The use of DAO and DTO makes it easy during the testing phase, as these are separated from the main code.

Github Link for the Code:

https://github.com/LuciAkirami/design_pattern

The media shown in this article is not owned by Analytics Vidhya and is used at the Author’s discretion.

I work as a Developer in the field of Data Science. I constantly spend time learning new things be it related to AI, DataSceine, and CyberSecurity. Deep learning and machine learning are two topics that I find particularly fascinating, and Python is my preferred language for programming. Cyber Security is another field that I'm touching upon recently. I have experience with large-scale data analysis, and I have a solid grasp of a variety of deep learning and machine learning approaches, including neural networks, regression models, and natural language processing. I'm eager to take on new challenges and make a meaningful contribution to the industry, so I'm constantly seeking for ways to enlarge and deepen my knowledge and skills in the subject.

Responses From Readers

Clear

Congratulations, You Did It!
Well Done on Completing Your Learning Journey. Stay curious and keep exploring!

We use cookies essential for this site to function well. Please click to help us improve its usefulness with additional cookies. Learn about our use of cookies in our Privacy Policy & Cookies Policy.

Show details