Python Forum
Flask - adding new page affects all other pages
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Flask - adding new page affects all other pages
#1
FLASK Error - Please help

I am trying to run a script but while when I comment out add VLAN, the add interface works, when I comment out add interface.py then add vlan works. But when I enable both and try to run add vlan I get this error.

I have show commands that also do the same thing when I introduce one of the below sections. What am I doing wrong?

example error:
Error:
File "/home/app.py", line 48, in addvlan addvlan = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['number'], result['vlanname']) TypeError: __init__() missing 1 required positional argument: 'voicevlan'
app.py script

@app.route('/addvlan',methods = ['POST', 'GET'])
def addvlan():
        if request.method == 'POST':
                result = request.form.to_dict()
                data = request.form.to_dict('number')
                addvlan = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['number'], result['vlanname'])
                return render_template('addvlan.html',result=addvlan.addvlan())
        else:
                return render_template('addvlan.html')



@app.route('/addinterface',methods = ['POST', 'GET'])
def addinterface():
        if request.method == 'POST':
                result = request.form.to_dict()
                data = request.form.to_dict('interface')
                addinterface = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['interface'], result['datavlan'], result['voi$
                return render_template('addinterface.html',result=addinterface.addinterface())
        else:
                return render_template('addinterface.html')
addvlan.py

class router(object):

        def __init__(self,device_type,ip,username,password,port,number,vlanname):
                self.device_type = device_type
                self.ip = ip
                self.username = username
                self.password = password
                self.port = port
                self.number = number
                self.vlanname = vlanname

        def addvlan(self):

                cisco_vios = {
                'device_type':self.device_type,
                'ip': self.ip,
                'username':self.username,
                'password': self.password,
                        'port': self.port
                        }

                net_connect = ConnectHandler(**cisco_vios)

                string_vlan = net_connect.send_command('en')
                string_vlan = net_connect.send_command('cisco')

                data = {
                'number':self.number,
                'vlanname':self.vlanname
                        }

                config_commands = [
                        'vlan {number}'.format(**data),
                        'name {vlanname}'.format(**data),
               ]
                output = net_connect.send_config_set(config_commands)
addinterface.py

class router(object):

        def __init__(self,device_type,ip,username,password,port,interface,datavlan,voicevlan):
                self.device_type = device_type
                self.ip = ip
                self.username = username
                self.password = password
                self.port = port
                self.interface = interface
                self.datavlan = datavlan
                self.voicevlan = voicevlan

        def addinterface(self):

                cisco_vios = {
                'device_type':self.device_type,
                'ip': self.ip,
                'username':self.username,
                'password': self.password,
                        'port': self.port
                        }

                net_connect = ConnectHandler(**cisco_vios)

                string_interface = net_connect.send_command('en')
                string_interface = net_connect.send_command('cisco')

                data = {
                'interface':self.interface,
                'datavlan':self.datavlan,
                'voicevlan':self.voicevlan
                        }

                config_commands = [
                        'interface gi{interface}'.format(**data),
                        'switchport',
                        'switchport access vlan {datavlan}'.format(**data),
                        'switchport voice vlan {voicevlan}'.format(**data)
               ]
                output = net_connect.send_config_set(config_commands)
Reply
#2
your router. __init__() method expects 9 aruments, of which first positional argument is self. When you instantiate object of class router you need to pass 8 arguments. You pass 7, thus it complains that last one - voicelan is missing:
addvlan = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['number'], result['vlanname'])
I guess you are actually missing datavlan param - result['datavlan'], like you do in other places like addinterface


Also note that you have missing closing brackets on following line:
addinterface = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['interface'], result['datavlan'], result['voi$
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
hi Buran,

Voicevlan is part of the add interface section and is not entered in the Add VLAN section, but the addVLAN section is looking for it. I don't know why they are intertwined when both are enabled. They are inputed from different HTML pages.
Reply
#4
(Mar-28-2020, 01:39 PM)CMR Wrote: Voicevlan is part of the add interface section and is not entered in the Add VLAN section
I am bit confused, because you pass result['vlanname'], i.e. it looks like you omit result['datavlan']

At the moment result['vlanname'] is the value you pass for datavlan parameter

(Mar-28-2020, 01:39 PM)CMR Wrote: but the addVLAN section is looking for it
I am bid confused
It looks like you have some misunderstanding about the functions/class methods.
your class.__init__() takes only positional arguments, i.e. no default values, so all arguments are required. You cannot just skip
You can change it to take some default values, e.g. (just an example, it's up to you to decide which params and what default values)
def __init__(self,device_type,ip,username,password,port,interface,datavlan=None,voicevlan=None):
in this case you can skip datavlan and/or voicevlan.

Look also at this one:
https://python-forum.io/Thread-init-ques...#pid108442
here is the method signature:
def __init__(self,device_type,ip,username,password,port,interface,datavlan,voicevlan):
and here is how you call it:
addvlan = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['number'], result['vlanname'])
so you have 9 params and when match with the arguments you pass
  • self - instance it self. it is passed automatically
  • device_type = 'cisco_ios'
  • ip = result['hostname']
  • username = result['username']
  • password = result['password']
  • port = result['port']
  • interface = result['number']
  • datavlan = result['vlanname']
  • voicevlan - NO VALUE THUS THE ERROR
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
Oh due to missing python tags, I didn't see you have 2 router classes. How do you import router?
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#6
I do understand what you mean with regards to stating parameters, the parameters are stated in the python program for the function in app.py. When I comment out the add vlan function in app.py, the add interface works perfectly. When I uncomment it again it breaks and looks for parameters from the other functions. Is each page separate or is there a link between them?

I have tried to add the parameters form the def add interface to the init in the addvlan.py, the same error appears.

these are separate GUIs with separate requests, but they seem to be looking for each others parameters when I uncomment them from the app.py page.

I am sorry but in the app.py under the def interface I was looking for the interface, datavlan and voicevlan. it didn't copy properly

@app.route('/addinterface',methods = ['POST', 'GET'])
def addinterface():
        if request.method == 'POST':
                result = request.form.to_dict()
                data = request.form.to_dict('interface')
                addinterface = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['interface'], result['datavlan'], result['voicevlan'])
                return render_template('addinterface.html',result=addinterface.addinterface())
        else:
                return render_template('addinterface.html')
this is the full app script

from flask import render_template, redirect, Flask, request
from cisco import *
from addvlan import *
from addinterface import router
from netmiko import ConnectHandler
import textfsm


app = Flask(__name__)

@app.route('/')
def redirect_to_index():
    return redirect('/index', code=302)


@app.route('/index',methods = ['POST', 'GET'])
def index():
        if request.method == 'GET':
                return render_template('index.html')


#@app.route('/interfaces',methods = ['POST', 'GET'])
#def interfaces():
#       if request.method == 'POST':
#               result = request.form.to_dict()
#               cisco = router('cisco_ios', result['hostname'], result['username'], result['password'] , result['port'])
#               return render_template('interfaces.html', result=cisco.interfaces())
#       else:
#               return render_template('interfaces.html')


#@app.route('/vlan',methods = ['POST', 'GET'])
#def vlan():
#       if request.method == 'POST':
#               result = request.form.to_dict()
#               cisco = router('cisco_ios', result['hostname'], result['username'], result['password'] , result['port'])
#               return render_template('vlan.html',result=cisco.vlan())
#       else:
#               return render_template('vlan.html')


@app.route('/addvlan',methods = ['POST', 'GET'])
def addvlan():
        if request.method == 'POST':
                result = request.form.to_dict()
                data = request.form.to_dict('number')
                addvlan = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['number'], result['vlanname'])
                return render_template('addvlan.html',result=addvlan.addvlan())
        else:
                return render_template('addvlan.html')



@app.route('/addinterface',methods = ['POST', 'GET'])
def addinterface():
        if request.method == 'POST':
                result = request.form.to_dict()
                data = request.form.to_dict('interface')
                addinterface = router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['interface'], result['datavlan'], result['voicevlan'])
                return render_template('addinterface.html',result=addinterface.addinterface())
        else:
                return render_template('addinterface.html')


@app.errorhandler(500)
def connection_time_out(e):
    return render_template('500.html'), 500


if __name__ == "__main__":
        app.run(host='0.0.0.0', port=8080)
Reply
#7
in app.py you use class router in both your functions. where does it come from? Based on the error it comes from addinterface.py (where it expects 9 params), but you also use router in addvlan function in app.py. You are assuming it's router from addvlan.py (where it takes only 8 aparams), but your assumption is not correct.

So show how you import router in app.py
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#8
This is the add vlan full script, router is the class in that script addvlan.py

from netmiko import ConnectHandler
import textfsm

class router(object):

        def __init__(self,device_type,ip,username,password,port,number,vlanname,datavlan=None,voicevlan=None):
                self.device_type = device_type
                self.ip = ip
                self.username = username
                self.password = password
                self.port = port
                self.number = number
                self.vlanname = vlanname
                self.datavlan =datavlan
                self.voicevlan=voicevlan


        def addvlan(self):

                cisco_vios = {
                'device_type':self.device_type,
                'ip': self.ip,
                'username':self.username,
                'password': self.password,
                        'port': self.port
                        }

                net_connect = ConnectHandler(**cisco_vios)

                string_vlan = net_connect.send_command('en')
                string_vlan = net_connect.send_command('cisco')

                data = {
                'number':self.number,
                'vlanname':self.vlanname
                        }

                config_commands = [
                        'vlan {number}'.format(**data),
                        'name {vlanname}'.format(**data),
               ]
                output = net_connect.send_config_set(config_commands)
This is the add interface plan, i didn't think they interfered with each other so I use class router in this script too.

from netmiko import ConnectHandler
import textfsm

class router(object):

        def __init__(self,device_type,ip,username,password,port,interface,datavlan,voicevlan):
                self.device_type = device_type
                self.ip = ip
                self.username = username
                self.password = password
                self.port = port
                self.interface = interface
                self.datavlan = datavlan
                self.voicevlan = voicevlan


        def addinterface(self):

                cisco_vios = {
                'device_type':self.device_type,
                'ip': self.ip,
                'username':self.username,
                'password': self.password,
                        'port': self.port
                        }

                net_connect = ConnectHandler(**cisco_vios)

                string_interface = net_connect.send_command('en')
                string_interface = net_connect.send_command('cisco')

                data = {
                'interface':self.interface,
                'datavlan':self.datavlan,
                'voicevlan':self.voicevlan
                        }

                config_commands = [
                        'interface gi{interface}'.format(**data),
                        'switchport',
                        'switchport access vlan {datavlan}'.format(**data),
                        'switchport voice vlan {voicevlan}'.format(**data)
               ]
                output = net_connect.send_config_set(config_commands)
Reply
#9
OK, I saw your edited post:
Here is the problem
from addvlan import *
from addinterface import router
with the star import you import all names from addvlan.py.
then with next line you override/shadow router with the one from addinterface.py. Now everywhere in app.py router is addinterface.router

Star imports are considered bad practice and discouraged exactly because of errors like this
better
import addvlan
import addinterface
and then fully qualify names/classes you use, e.g.
@app.route('/addvlan',methods = ['POST', 'GET'])
def addvlan():
        if request.method == 'POST':
                result = request.form.to_dict()
                data = request.form.to_dict('number')
                addvlan_router = addvlan.router('cisco_ios', result['hostname'], result['username'], result['password'], result['port'], result['number'], result['vlanname'])
                return render_template('addvlan.html',result=addvlan_router.addvlan())
        else:
                return render_template('addvlan.html')
Also you may consider combing both router classes into one
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#10
Thanks Buran, I really appreciate your help, I have been struggling with this for a while.
I will try to amalgamate the router classes together, i had them together but i kept getting positional arguments missing. I will try what you have told me and I will let you know what my progress is, thanks again for your help.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Reload flask current page GrahamL 2 1,247 Jan-08-2021, 08:31 AM
Last Post: GrahamL
  API auto-refresh on HTML page using Flask toc 2 5,248 Dec-23-2020, 02:00 PM
Last Post: toc
  [Flask]After login page is not redirecting me to dashboard shockwave 0 922 May-07-2020, 05:22 PM
Last Post: shockwave
  use Xpath in Python :: libxml2 for a page-to-page skip-setting apollo 2 1,464 Mar-19-2020, 06:13 PM
Last Post: apollo
  Flask - Opening second page via href is failing - This site can’t be reached rafiPython1 2 3,038 Apr-11-2018, 08:41 AM
Last Post: rafiPython1

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020