0

I'm building a quick registration page with Firebase, Pyrebase & Flask; I have managed to create a user account & push the data to the business folder; I have also created a login where the user is logged into a profile page - to display their name & their name of business.

My only problem is that I cannot extract the single data, but instead it displays the data as a single block; this makes it hard for me to find a way just to extract only the businessName or just the userName from the registerList.

I also want only the information to display just the user who has signed in - I think I need to use some type of user[idToken] I'm not sure.. Instead I get the whole list (I know using a for-loop doesn't help!)

registration.py

    import pyrebase
    from flask import * 

    app = Flask(__name__)

    config = {
        "apiKey": "",
        "authDomain": "",
        "databaseURL": "",
        "projectId": "",
        "storageBucket": "",
        "messagingSenderId": "",
        "appId": "",
        "measurementId": ""
    }

    firebase = pyrebase.initialize_app(config)
    auth = firebase.auth()
    db = firebase.database()


    @app.route('/', methods=['GET', 'POST'])
    def login():
        unsuccessful = 'Please check your credentials'
        successful = 'Login successful'
        if request.method == 'POST':
            email = request.form.get('name')
            password = request.form.get('pass')
            try:
                user = auth.sign_in_with_email_and_password(email, password)
                register = db.child("Bame_Register").child("business").get()
                registerList = register.val()
                return render_template('profile.html', registerList=registerList)
            except:
                return render_template('new.html', us=unsuccessful)
        return render_template('new.html', us=unsuccessful)


    @app.route('/register', methods=['GET', 'POST'])
    def register():
        unsuccessful = 'Please check your credentials'
        successful = 'Registraion successful'
        if request.method == 'POST':
            email = request.form.get('email')
            password = request.form.get('pass')
            userName = request.form.get('inputName')
            businessName = request.form.get('businessName')
            try:
                user = auth.create_user_with_email_and_password(email, password)
                auth.send_email_verification(user['idToken'])
                bameRegister = dict(userName=userName, businessName=businessName)
                db.child("Bame_Register").child("business").push(bameRegister)
                return render_template('new.html', x=successful)
            except:
                return render_template('new.html', y=unsuccessful)
        return render_template('new.html')


    if __name__ == '__main__':
        app.run(debug=True)

new.html

    <!DOCTYPE html>
    <html>
    <head>
      <title>Flask Firebase Auth</title>
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
      <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    </head>
    <body>
      <div class="container">
        {% if s %}
          <div class="alert alert-success">
            <h2>{{s}}</h2>
          </div>
        {% endif %}

        {% if us %}
          <div class="alert alert-danger">
            <h2>{{us}}</h2>
          </div>
        {% endif %}

        <form action="/" method="post">
          <h2>Please sign in</h2>
          <label for="inputEmail">Email address</label>
          <input type="email" id="inputEmail" name="name"  placeholder="Email address" required autofocus>
          <label for="inputPassword">Password</label>
          <input type="password" id="inputPassword" name="pass"  placeholder="Password" required>
          <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
        </form>
      </div>
      <br>
      <div class="container">
        {% if x %}
          <div class="alert alert-success">
            <h2>{{x}}</h2>
          </div>
        {% endif %}

        {% if y %}
          <div class="alert alert-danger">
            <h2>{{y}}</h2>
          </div>
        {% endif %}

        <form action="{{ url_for('register') }}" method="post">
          <h2>Please create an account to register your business</h2>
          <label for="inputEmail">Email address</label>
          <input type="email" id="inputEmail" name="email"  placeholder="Email address" required autofocus>
          <label for="inputPassword">Password</label>
          <input type="password" id="inputPassword" name="pass"  placeholder="Password" required>
          <br>
          <label for="inputName">Enter your name: </label>
          <input type="text" id="inputName" name="inputName" placeholder="Name" required>
          <label for="businessName">Business Name</label>
          <input type="text" id="businessName" name="businessName" placeholder="Business Name" required>
          <button class="btn btn-lg btn-primary btn-block" type="submit">Register business</button>
        </form>
      </div>
    </body>
    </html>

profile.html

   <!DOCTYPE html>
   <html lang="en" dir="ltr">
     <head>
       <title>dynamic pages</title>
     </head>
     <body>
       {% for key,value in registerList.items() %}
         {% for data in value.values() %}
           <h4>{{ data }}</h4>
         {% endfor %}
       {% endfor %}
       <h6>Dynamic profile page</h6>
     </body>
   </html>

How would I display just the name of the user or just their business name? I was thinking maybe data[userName] or data[businessName], but that didn't work! I want to be able to take the data separately so I can control where I display the data. The data displayed should only be of the user who has logged in. Then I can later add functionality where the users can edit their information.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Any chance you could please provide these information:(1) The output of ```print(user) ``` (2) ```print(register )```(3) ```print(registerList)``` from within the try block inside your login method right before this line ```return render_template('profile.html',registerList=registerList)``` – Akib Rhast Jul 06 '20 at 00:31
  • I tried ```print(register)``` on my IDLE and got back `````` – Sinclair Akoto Jul 06 '20 at 01:49
  • I also tried ```print(user)``` and got back a large dictionary in it had different keys like my email, localId, idToken etc ...I would print what I got back but its too large – Sinclair Akoto Jul 06 '20 at 01:52
  • I also tried ```print(registerList)``` and got back ```OrderedDict([('-MBVxA_L1VbTzjnRjpmf', {'businessName': 'BondRobotics', 'userName': 'Sinclair Akoto'}), ('-MBVy-LNwphkGrrK3rfB', {'businessName': '619 fly attire', 'userName': 'richie'})])``` – Sinclair Akoto Jul 06 '20 at 01:56

3 Answers3

0

In your register function try this:

#.push(bameRegister, user['idToken']) pushes your data with a uniquely identifiable key that is the user idToken
results = db.child("Bame_Register").child("business").push(bameRegister, user['idToken'])

Then in your login function try this:

registerlist = db.child("Bame_Register").child("business").get(user['idToken']).val()
print(registerlist)

Create a new user after you have made the above changes then login as that new user. Add a comment on what the new print(registerlist) gives you.

Let me know if it works ?!

Hopefully what the above query changes would do is create a uniquely identifiable key before pushing to firebase during register. Then querying for that unique key and the value of that key during login will result in a single user data.

A little explanation of what I think is happening :

bameRegister = dict(userName=userName, businessName=businessName)
db.child("Bame_Register").child("business").push(bameRegister)

The above piece of code is from your register function. Each time you make a push, this is what is being created:

('-MBVxA_L1VbTzjnRjpmf', {'businessName': 'BondRobotics', 'userName': 'Sinclair Akoto'})

The above is a key value pair where the key is '-MBVxA_L1VbTzjnRjpmf' and the value is {'businessName': 'BondRobotics', 'userName': 'Sinclair Akoto'}.

The key is autogenerated by firebase on push

A demo on ordered dict from python conole: enter image description here

Akib Rhast
  • 651
  • 4
  • 15
  • Thank you for your help! I managed to find what I was looking for, however I am still stuck.. in order to only get the data for ```userName``` or ```businessName```, I followed your recommended steps and then I just put ```registerlist.get('FIREBASE_AUTOGENERATED_KEY')``` into a variable then used that variable to reference the dictionary key I want the value of.. ```b = registerlist.get('-MBVy-LNwphkGrrK3rfB')``` then ```print(b['userName'])``` or ```print(b['businessName'])``` – Sinclair Akoto Jul 06 '20 at 14:00
  • This gave me the data which I wanted - I just need to pass it into my flask project to test & double check as I figured it out on my IDLE.. my next question is if the key ```'-MBVxA_L1VbTzjnRjpmf'``` is autogenerated, how could I automatically reference that when creating a page - so I don't have to reference the firebase key? would you be able to help or share some light into how I could make this work? I was thinking if this is being stored in the business collection, can I not just reference the business collection along with the ```user[idToken]```? – Sinclair Akoto Jul 06 '20 at 14:08
0

With the help of the previous comment, I managed to find a way to implement the same process onto a Flask webpage.

@app.route('/', methods=['GET', 'POST'])
def login():
    unsuccessful = 'Please check your credentials'
    successful = 'Login successful'
    if request.method == 'POST':
        email = request.form.get('name')
        password = request.form.get('pass')
        try:
            user = auth.sign_in_with_email_and_password(email, password)
            registerList = db.child("Bame_Register").child("business").get(user['idToken']).val()
            data = registerList.get('-MBZJcfqbGhiOghMJEX5')
            usrNme = data['userName']
            bus = data['businessName']
            return render_template('profile.html', usrNme=usrNme, bus=bus)
        except:
            return render_template('new.html', us=unsuccessful)
    return render_template('new.html')

This works, however I had to hardcode the autogenerated key Firebase creates when a user registers their business..

If anyone could help me somehow automate the data object so that I wouldn't have to write out the name of each key i.e. '-MBZJcfqbGhiOghMJEX5' - every time a new registration is stored.

If there was a way I could automate it so that the key would be accessed from a variable, which would recognised as '-MBZJcfqbGhiOghMJEX5' or any other new registration created, it would allow me to create a template for all registrations - rather than writing out something similar below for each and every single registration created...

Ideally the information displayed when the user is logged in, will only be their own if using the user['idToken'] as suggested.

0

I had the same issue but was able to figure out a fix from this @Akib's answer above and another post linked here: Extracting Data from OrderedDict

I will provide a mix of my code and the others I referenced.

First, follow @Akib's steps above. I will post them for convenience.

"In your register function try this:"

results = db.child("Bame_Register").child("business").push(bameRegister, user['idToken'])

"Then in your login function try this:"

registerlist = db.child("Bame_Register").child("business").get(user['idToken']).val()

Like he said, the print(registerlist) results in:

('-MBVxA_L1VbTzjnRjpmf', {'businessName': 'BondRobotics', 'userName': 'Sinclair Akoto'})

Now, based on the errors I was getting trying to get a specific value from this, this is an OrderedDict and was when I move to this Extracting Data from OrderedDict post. What I learned is how to iterate the list in the OrderedDict. To do this, first Import OrderedDict at the top of your "registration.py" file:

from collections import OrderedDict

Last, we parse/iterate the OrderedDict. Only the If statement was what I added "in order to only get the data for userName":

for val in bameRegister.values():
            for k,v in val.items():
                #print(k, v)
                if k == 'userName':
                    #print(v)
                    name = v
        print(name)

This print(name) will result in:

Sinclair Akoto

Hope this helps you out! This is my first stackoverflow post so, Good Luck!