I am creating an application using Django. The application has user registration and login functionality.
I have three functions related to user authentication as of now, login, registration, and email_check (which is called when the user types email address to see if it is available). I was trying to group these functions under a class for better organisation and easy accessibility.
So I wrote a class and function like so:
class user_auth:
def check_email(email):
with connection.cursor() as conn:
conn.execute('select count(*) from user_info where email = %s', [email])
row = conn.fetchall()
response = bool(row[0][0])
return(response)
However, when I do this, I get a pylint error saying Method should have "self" as the first argument.
If I save this and call it as user_auth.check_email('abc#xyz.com'), it works just fine. But if I add self as the first argument, it stops working.
Am I using classes in an incorrect way? If yes, what is a better way to create a group of functions like this which can be easily imported using a single statement in other files?
As in the comments said, you could use a module for it.
Otherwise if you want to group them inside a class you just need to use the staticmethod or classmethod decorator.
Example:
class user_auth:
#classmethod
def check_email(cls, email):
...
#staticmethod
def static_check_email(email):
...
Related
I'm writing a module to make requests to a work-related website easier. I have one class that initializes the session and has the URL as a variable. I wrote an abstract class to encapsulate the logic of the requests, and one subclass for each of the data-types. Ideally, most of the methods should be class methods, so I can call them by writing module.subclass1.get(params). My problem is that all of these methods need a session, and an URL to make the requests, and I can't figure out a good way to implement this. My code is looking something like this at the moment.
#This class I make an instance of, to have the session and url at hand.
class Website:
def __init__(self, username, password, url):
self.session = getSession(username, password)
self.url = url
#The abstract class that handles the requests
class AbstractClass(abc.ABC):
classvar1 = ""
classvar2 = ""
#classmethod
def get(cls, website, params):
website.session.get(website.url + cls.classvar1, params)
class Subclass1(AbstractClass):
classvar1 = "Something else"
classvar2 = "Something else"
Some of my (suboptimal) solutions are:
1. Passing an instance of Website as an argument to the class methods
This works and is what I do for now, but I would have to pass the website object as a parameter all the time.
All calls would end up looking like this:
module.subclass1.method(website, params)
2. Making the website object a class variable in the abstract class.
This works and makes the method calls look pretty: module.Subclass1.get(params) But it seems like very bad practice, and I would like to always have to specify a username, password, and URL, so different scripts can use different logins and so I can change the URL to test or prod environment.
3. Initializing all the subclasses with a website object in the Website class
This also makes the method calls look pretty website.Subclass1.method(params), but I would have to initialize every single subclass in the Website __init__ method, and would have to change the abstract class to add an__init__ method that takes a Website object as an argument.
Is there any smarter way to accomplish this? Any help is much appreciated.
Cannot return a string from a python class to another python class.
Created two classes and need to get a string from one to the other. I keep getting the message -
'app.classes.xxx' has no attribute 'returnDBString'
Class1.py
from app.classes import DBManager
def CustomerSetup(self, user_id):
db = DBManager.returnDBString()
cnxn = pdc.connect(db)
DBManager.py
class DBManager():
def returnDBString():
return 'Database string and connection info'
def returnConnection():
return pdc.connect(returnDBString())
I was expecting to get back the actual string in the class, but I keep getting the error
app.classes.DBManager' has no attribute 'returnDBString
This has nothing to do with returning strings.
For some reason you have put your function inside a class, which just happens to have the same name as the module it is in. But Python is not Java; functions don't need to be in classes, and if you do define a class then you need to import it specifically, not just the module (or, at least, refer to it via the module).
In any case, you should remove the class declaration and just put your two functions directly at module level.
Decorate the method with #classmethod if it makes sense to have this method under DBManager
This is an issue of usability of module with classes.
There are 2 solution to your problem:
1) If you create class with member function in DBManager.py and want to use it some different file.Then, first thing which should come into you mind that a class is nothing without an class object. You need to create an object of your class and call into returnDBString() with that object. keep in mind you need to create constructor init() as well of you class, its incomplete in your code.
def CustomerSetup(self, user_id):
DBObject = DBManager()
db = DBObject.returnDBString()
2) Don't have class in DBManager.py, delete class and have same function without class. In this case your current code Class1.py would work.
You need to instantiate the class in Class1.py, and make pdc available to it:
db = DBManager.DBManager(pdc).returnDBString()
Note the parens, DBManager().
You'll also need to write your DBManager class like so:
class DBManager():
def __init__(self, pdx):
self.pdx = pdx
def returnDBString(self):
return 'Database string and connection info'
def returnConnection(self):
return self.pdc.connect(self.returnDBString())
I'm building an application and one of the packages manage multiple auth methods.
Now it supports LDAP and PAM but I want in the future it supports a few more.
I have a package with
PAM.py and
LDAP.py
for example PAM.py contents:
import pam
class pam_auth:
def __init__(self, username=None, password=None):
self.username=username
self.password=password
def login(self):
res_auth=pam.authenticate(username=self.username, password=password)
return res_auth
and in another package I have the next class Login:
class Login:
def __init__(self,method=None):
self.authmethod=method
def login(self):
res_login=self.authmethod.login()
return res_login
Now i'm building my auth code like:
p=pam_auth()
p.username="pep"
p.password="just"
l=Login(method=p)
print l.login
And I believe that it is not the best way to do it, and thinking in multiples and different methods to auth.
For Example may be something like?:
l=Login(method=PAM.pam_auth)
l.username="pep"
l.password="just"
print l.login()
¿What is that I must change in Login Class or PAM class to work in this way?
For the change you mentioned, all you need to do is to instanciate the class inside Login's __init__:
class Login:
def __init__(self,method):
self.authmethod=method()
However, as Stefano Sanfilippo mentioned, this may actually hamper modularity, since suddenly Login must know the constructor parameters of the authentication method.
A couple more tips:
If you're writing python 2, you'll want to create new-style classes:
instead of
class Login:
use
class Login(object):
Also, if you're writing a general authentication layer, you probably don't want to deal explicitly with usernames and passwords: what will happen when you want to use third-factor, smartcard or biometric authentication in the future? You probably should deal with opaque "data", that the authentication method receives, unaltered.
In the code below the User class needs to access a function get_user inside an instance of WebService class, as that contains other functions required for authentication with the web server (last.fm). Actual code is here.
class WebService:
def __init__(self, key):
self.apikey = key
def get_user(self, name):
pass # Omitted
class User:
def __init__(self, name, webservice):
self.name = name
self.ws = webservice
def fill_profile(self):
data = self.ws.GetUser(self.name)
# Omitted
The problem is that a reference needs to be held inside every ´User´. Is there another way of doing this? Or is it just me overcomplicating things, and this is how it actually works in the real world?
As requested:
As to handling things like get_top_albums and get_friends, that depends on how you want to model the system. If you don't want to cache the data locally, I'd say just call the service each time with a user ID. If you do want to cache the data locally, you could pass a User object to the method in WebService, then have the method populate the members of the User. You do have to make a design decision though to either have a WebService and a User (what would probably be best), or just a UserWebService.
You can certainly make the reference a static variable, if the web service object is the same for all users.
The syntax is:
class User:
webservice = ...
...
You will then even be able to access it from User instances, but not to assign to it that way, that would require User.webservice syntax.
You are also getting good design alternatives suggested in the comments.
I'm building a webapp that has optional Facebook Login. The users created through the Facebook API are handled differently at several points in my application. I want to encapsulate these differences in a subclass of Person that overrides methods.
class Person(Model):
def get_profile_picture(self):
return profile_pictures.url(self.picture)
class FacebookPerson(Person):
def get_profile_picture(self):
return 'http:/.../%s.jpg' % self.graph_id
I would like to avoid the nasty if self.graph_id and just query the Person model and get the right object for each user.
I've thought of hacking the metaclass to add the FacebookPerson as a base. Obviously I would like to avoid such voodoo.
I'm using Flask and Flask-SQLAlchemy.
The general idea would be to store the model's class name as metadata in each row, and when you instantiate the object, do something like:
def query(self):
# stuff
return model_class(data)
To do this in SQLAlchemy, you might look at making Person the base class to something like BasicPerson and FacebookPerson, and in Person.init(), use the metadata to initialize to the proper subclass.
For example, the idea would be than when this query returns, user will have been initialized to the proper subclass:
user = session.query(Person).filter_by(name='james').first()
You will probably need to modify this concept a bit for SQLAlchemy (I haven't used it in a while), but that's the general idea.
Or, you could do something like store the metadata in a cookie with the user_id, and then when they log in again, use the metadata to pass the proper class to the user query:
user = session.query(FacebookPerson).filter_by(name='james').first()
If you want this to be generic so that the metatdata is meaningful to non-Python clients, instead of storing the model's class name, store the model's "object_type" and have something in each client library that maps object_types to classes.