DEV Community

Cover image for Coding Without The Traditional Database: Facing The Challenges
Mandyiee
Mandyiee

Posted on

Coding Without The Traditional Database: Facing The Challenges

The conventional database would be thought of as the standard tool for building software. Developers like myself frequently ponder whether there is a better approach.

Simply abandoning the common approach and trying something new will result in building without the conventional database. There are several methods, but in our previous article, we chose shelve, a straightforward yet powerful python solution for permanent data storage

I succeeded in creating: thatnoteapp. Thatnoteapp is a web app for taking notes that makes use of the shelve package in Python to store notes as private notes. The packages needed for this project are

  • UUID
  • Flask
  • Flask_ckeditor

The major objective of this project was to develop an authentication-free web-based note-taking tool that saves information to the user's device. A website without user registration or login functionality is referred to as authentication-free.

Numerous challenges were faced in the process of developing this project. Some challenges were overcome, and others caused the initial objectives to be adjusted. A few of the issues are shown here, along with solutions.

  • Incapable of storing data on the user's device
  • Inability to retain new data
  • Key error
  • Personalize the data
  • Personalize the data: get_data function
  • Redirecting the page
  • A list or a string

Incapable of storing data on the user's device

This is a scenario where one's desire to build a program resulted in the creation of something else that was nonetheless beneficial.

The biggest letdown was learning that the website could not access the device's storage as originally intended. To make a folder on the device, I intended on making use of this function.

def start():
  folder = os.path.join(Path.home(), '.dais')
  file = os.path.join(folder,'daisdb')
  os.chdir(Path.home())
  if os.path.exists(folder):
    if os.path.exists(file): 
      var = 1
   else:
     os.chdir(folder)
     noteObject = shelve.open('daisdb')
     note = [] 
     noteObject['notes'] = note
     noteObject.close()
   else: 
     os.mkdir('.dais') 
     os.chdir(folder)
     noteObject = shelve.open('daisdb')
     note = [] 
     noteObject['notes'] = note 
     noteObject.close()

Enter fullscreen mode Exit fullscreen mode

The functionality had not been created. The server would create the folder rather than the user's device. This gave me yet another idea: a programmer must always be innovative.

Although creating a folder on the server was sufficient, the objectives needed to be revised. From initially saving the notes on the device, the objective was changed to "building without the traditional database." However, that created a new challenge, which was how to personalize the data without user authentication.

Inability to retain new data

The list couldn't be updated with the new information. I initially considered making a new list and then rebuilding the shelve data for each newly saved note.

noteObject = shelve.open('daisdb', writeback = True)
noteList =  noteObject['notes']
noteList.append(obj)
noteObject['notes'] = noteList
Enter fullscreen mode Exit fullscreen mode

Although this method worked, I had to see whether a better solution exist. After considerable investigation, I discovered that the error was generated by my failure to include the write back attribute or close the shelve. To eliminate the mistake, I took this action.

noteObject = shelve.open('daisdb', writeback = True)
 noteObject['notes'].append(obj)
 noteObject.sync() 
noteObject.close()
Enter fullscreen mode Exit fullscreen mode

The key error

noteObject.['notes'].append(obj)
Enter fullscreen mode Exit fullscreen mode

This would occasionally generate this error and other times it would function as intended.

Traceback (most recent call last): File "/usr/lib/python3.5/shelve.py", line 111, in __getitem__ value = self.cache[key] KeyError: 'lb'
Enter fullscreen mode Exit fullscreen mode

The Python KeyError, a form of LookupError exception indicates that there was a problem locating the key you were looking for.

After doing a lot of research and reading StackOverflow, I discovered that the error was triggered by noteObject['notes']. The error was eradicated by changing noteObject['notes'] to noteObject.get('notes')

noteObject = shelve.open('daisdb', writeback = True) 
noteObject['notes'].append(obj)
Enter fullscreen mode Exit fullscreen mode

Changed to

noteObject = shelve.open('daisdb', writeback = True)
 noteObject.get('notes').append(obj)
Enter fullscreen mode Exit fullscreen mode

Personalize the data

Utilizing the IP address is one method to establish an authentication-free web app.

An IP address, or Internet Protocol address, is a unique series of numbers that identifies any device on a network.

The next step was to obtain the IP addresses from both the backend (server) and the frontend (javascript) and compare them to generate personalized data.

The server's public IP address, which was not unique, was the IP address that the Python code returned. I required a different IP address for each device, therefore this became a significant issue.

Utilizing Axios to send the IP address to the backend with the newly saved note became the best option.

The input=hidden element was used to store before sending the IP address with the submit button

let start = document.getElementById('title')
        start.addEventListener('focus', async() => {
            let result = await axios.get(`https://api.ipify.org?format=json`, {
                mode: 'cors',
                credentials: 'include'
            });

            let data = await result.data;
            document.getElementById('hide').value = data.ip
        })
Enter fullscreen mode Exit fullscreen mode

I retrieved the user's IP address from the URL and sent it to a flask view to create a customised page for each user.

window.addEventListener('load', async() => { 
 url = "/";
 let result = await axios.get(`https://api.ipify.org?format=json`,
 { mode: 'cors', 
credentials: 'include' 
}); 
 let data = await result.data;  
 let res = axios.post(url, { 
data 
}) 
.then((response) => {
 console.log('sent')
}, (error) => {
 console.log(error);
 });
})
Enter fullscreen mode Exit fullscreen mode

Personalize the data: get_data function

Retrieving data from the backend after utilizing the Axios function to send the data was not familiar to me. It took a lot of research to find out that using the .get_data() was the best option.,

The parameter in the function request.get_data('data'), is the name of the variable that the data was saved with.

let data = await result.data;  
 let res = axios.post(url, { 
data 
}) 
Enter fullscreen mode Exit fullscreen mode

To extract the IP address, the received data is required to be changed into a dictionary.

    resp = request.get_data('data')

    resp = json.loads(resp.decode("utf-8").replace("'",'"'))

    ipaddress = resp['data']['ip'] 
Enter fullscreen mode Exit fullscreen mode

Redirecting the page

The flask redirect function was ineffective. It appeared to be because an Axios function was used to send the data, so I used Javascript's window.location.assign() method to direct the user to their personalized page.

window.addEventListener('load', async() => {
    url = "/"

    let result = await axios.get(`https://api.ipify.org?format=json`, {
        mode: 'cors',
        credentials: 'include'
    });

    let data = await result.data;
    console.log(data)
    let res = axios.post(url, {
            data
        })
        .then((response) => {
            window.location.assign('/' + data.ip);
        }, (error) => {
            console.log(error);
        });
})
Enter fullscreen mode Exit fullscreen mode

A list or a string

For some reason, I mistook this noteObject['notes'] for a string and used a "+" in instead of the list's "append" function. Fortunately, it was resolved very quickly. I suppose when one overthinks, they forget little details. This serves as a reminder that a good programmer should also get enough rest before writing code.

Additionally, there are several things that I figured out rather well. This link will take you to the code. As a programmer, I must admit that there are some problems that I haven't solved or whose solutions could be made easier.

Have a thought? Share it below.

Top comments (0)