I need to override user save method in my custom OAuth2Adapter. How i can do this?
I need save some special fields in my user Model
auth_provider/views.py
import requests
from allauth.socialaccount.providers.oauth2.views import (
OAuth2Adapter,
OAuth2CallbackView,
OAuth2LoginView,
)
from config.settings.base import EXAMPLE_URLS
from app.users.auth_provider.provider import ExampleProvider
class ExampleAdapter(OAuth2Adapter):
provider_id = ExampleProvider.id
access_token_url = EXAMPLE_URLS["web"] + "oauth/token"
authorize_url = EXAMPLE_URLS["web"] + "oauth/authorize"
profile_url = EXAMPLE_URLS["api"] + "me"
def complete_login(self, request, app, access_token, **kwargs):
headers = {"Authorization": "Bearer %s" % access_token}
extra_data = requests.get(self.profile_url, headers=headers)
return self.get_provider().sociallogin_from_response(request, extra_data.json())
oauth2_login = OAuth2LoginView.adapter_view(ExampleAdapter)
oauth2_callback = OAuth2CallbackView.adapter_view(ExampleAdapter)
I have created a class for retrieving data about a specific food product from farsecret API.
In class I have created 3 functions for:
*obtaining authorization
*getting id of item, for which we are looking
*download data of item
class IngredientImport(APIView):
def get_authorization_token(self):
request_token_url = "https://oauth.fatsecret.com/connect/token"
consumer_key = os.environ.get('NTS_Client_ID')
consumer_secret = os.environ.get('NTS_Client_Secret')
data = {'grant_type':'client_credentials', "scope":"basic"}
access_token_response = requests.post(
request_token_url,
data=data,
verify=False,
allow_redirects=False,
auth=(consumer_key, consumer_secret)
)
return access_token_response.json()["access_token"]
def get_list_by_name(self, name, access_token):
api_url = "https://platform.fatsecret.com/rest/server.api"
params={
"method":"foods.search",
"search_expression":name,
"page_number":1,
"max_results":1,
"format":"json"
}
header = {"Authorization":access_token}
api_call_headers = {"Authorization": "Bearer " + access_token}
response = requests.get(
api_url,
params=params,
headers=api_call_headers
)
items = response.json()["foods"]
try:
return response.json()["foods"]["food"]["food_id"]
except KeyError:
return None
def import_item(self, item_id, api_token):
if item_id == None:
return None
api_url = "https://platform.fatsecret.com/rest/server.api"
params={"method":"food.get", "food_id":item_id, "format":"json"}
api_call_headers = {"Authorization": "Bearer " + access_token}
response = requests.get(
api_url,
params=params,
headers=api_call_headers
)
item = response.json()["food"]["servings"]["serving"]
item_name = response.json()["food"]["food_name"]
if type(item) == list:
item = item[0]
try:
portion_size = float(item["metric_serving_amount"])
carbs = round(float(item["carbohydrate"]) / portion_size * 100, 2)
fats = round(float(item["fat"]) / portion_size * 100, 2)
proteins = round(float(item["protein"]) / portion_size * 100, 2)
except KeyError:
return None
How can I implement this class in my aplication to avoid creating 3 different paths in urls.py for each function. Is it possible or should I break it into function-based views?
class IngredientImport(APIView):
def get_authorization_token(self):
...
def get_list_by_name(self, name, access_token):
...
def import_item(self, item_id, api_token):
...
def get(self, request):
# get name from query param
name = self.request.GET.get('name')
token = self.get_authorization_token()
food_list = self.get_list_by_name(name, token)
for food_id in food_list:
self.import_item(food_id, token)
return Response({'imported_foods': food_list})
Then, on your urls.py:
urlpatterns = [
path('import_foods', IngredientImport.as_view())
]
Models.py
from datetime import datetime
from cmrapp import db,login_manager
from flask_login import UserMixin
#login_manager.user_loader
def load_user(user_id):
return Registration.query.get(int(user_id))
class Registration(db.Model,UserMixin):
id = db.Column(db.Integer(),primary_key=True)
regid = db.Column(db.String(),unique=True)
section = db.Column(db.String(),nullable= False)
username = db.Column(db.String(20),unique=True,nullable = False)
password = db.Column(db.String(60),nullable = False)
def __repr__(self):
return f"Registration('{self.username}','{self.regid}')"
class Participation(db.Model):
id = db.Column(db.Integer(),primary_key=True)
pname = db.Column(db.String(20),nullable= False)
pregid = db.Column(db.String(),unique=True)
psection = db.Column(db.String(),nullable=False)
def __repr__(self):
return f"Participation('{self.pname},'{self.pregid}','{self.psection}')"
#login_manager.user_loader
def load_user(mregid):
return Memberdb.query.get(int(mregid))
class Memberdb(db.Model,UserMixin):
id = db.Column(db.Integer(),primary_key=True)
mregid = db.Column(db.String(20),nullable = False,unique=True)
mname = db.Column(db.String(20),unique=True,nullable = False)
mpassword = db.Column(db.String(60),nullable = False)
organizers = db.relationship('Eventdb',backref='owner',lazy=True)
def __repr__(self):
return f"Memberdb('{self.mname}','{self.id}')"
****routes.py****
from flask import render_template,url_for,request,redirect,flash,request
from cmrapp import app,db,bcrypt
from cmrapp.data import fetch
from datetime import datetime,date
from cmrapp.userforms import Registerform,identityform,studentform,memberform,blockform
from cmrapp.models import Registration,Participation,Memberdb
from flask_login import login_user,current_user,logout_user,login_required
#app.route('/')
#app.route('/signup',methods=["GET","POST"])
def signuppage():
if current_user.is_authenticated:
return redirect(url_for('homepage'))
form = Registerform()
if form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user = Registration(username = form.username.data, regid = form.regno.data, password =
hashed_password,section=form.section.data )
db.session.add(user)
db.session.commit()
flash(f"Your Account has been Created! {form.username.data}",'success')
return redirect(url_for('sloginpage'))
else:
return render_template('signup.html',title="Sign Up",form=form,consent=consent,diff=diff)
#app.route('/slogin',methods=["GET","POST"])
def sloginpage():
if current_user.is_authenticated:
return redirect(url_for('homepage'))
form = studentform()
if form.validate_on_submit():
user = Registration.query.filter_by(username = form.studentname.data).first()
if user:
if user and bcrypt.check_password_hash(user.password,form.spassword.data):
login_user(user,True)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('homepage'))
else:
flash(f'Login Unsuccessful ! Check Name and Password.','danger')
return render_template('slogin.html',title ='Student Login',form=form)
else:
flash(f'User doesn\'t exist' ,'danger')
return render_template('slogin.html',title ='Student Login',form=form)
#app.route('/msignup',methods=["GET","POST"])
def msignuppage():
form = memberform()
if form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(form.memberpassword.data).decode('utf-8')
user = Memberdb(mname = form.membername.data, mregid = form.secureid.data, mpassword =
hashed_password )
db.session.add(user)
db.session.commit()
flash('Your Account has been Created','success')
return redirect('mlogin')
else:
return render_template('msignup.html',title="Member Account",form=form)
# user = user1
#app.route('/mlogin',methods=["GET","POST"])
def mloginpage():
form = memberform()
if form.validate_on_submit():
# if form.membername.data == "Lucky" and form.memberpassword.data == "luckyG2611#":
user = Memberdb.query.filter_by(mname = form.membername.data).first()
if user:
if user and bcrypt.check_password_hash(user.mpassword,form.memberpassword.data):
login_user(user,True)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('mlist'))
else:
flash(f'Login Unsuccessful ! Check Name and Password.','danger')
return render_template('mlogin.html',title ='Member Login',form=form)
else:
flash(f'User doesn\'t exist' ,'danger')
return render_template('mlogin.html',title ='Member Login',form=form)
****userform.py****
from flask_wtf import FlaskForm
from wtforms import StringField,PasswordField,validators,SubmitField,BooleanField,ValidationError,BooleanField,SelectField,DateField,TextAreaField
from wtforms.validators import DataRequired,Length,EqualTo
from cmrapp.models import Registration,Participation,Memberdb
from flask_login import current_user
class Registerform(FlaskForm):
username = StringField('Name',
validators=[DataRequired(),Length(min=2,max =20),validators.regexp('^[a-
zA-Z\s]+$',message="Name contains only string ! Try Again")])
section = SelectField(u'Section',choices=[('1yr-A', 'Ist-A'),('1yr-B', 'Ist-B'), ('1yr-C','Ist-
C'),('2yr-A', 'Sec-A'),('2yr-B', 'Sec-B'), ('2yr-C','Sec-C'),('3yr-A',
'Third-A'),('3yr-B', 'Third-B'), ('3yr-C','Third-C')],validators=
[DataRequired()],validate_choice=False,coerce=str)
regno = StringField('Registration No.',
validators=[DataRequired(), Length(min=10,max=10),validators.regexp('[19]+
[DBCAG]+\d\d\d',message="Use your Respective Regno.")])
password = PasswordField('Password',
validators=[DataRequired(),Length(min=10)])
submit = SubmitField('Sign Up')
def validate_username(self,username):
user = Registration.query.filter_by(username=username.data).all()
if user:
raise ValidationError('Username Already Exist :(')
def validate_regno(self,regno):
regid = Registration.query.filter_by(regid=regno.data).all()
if regid :
raise ValidationError('Regno. Already Exist :(')
class studentform(FlaskForm):
studentname = StringField('Name',
validators=[DataRequired(),Length(min=2,max =20)])
spassword = PasswordField('Password',
validators=[DataRequired(),Length(min=10)])
studentin = SubmitField('Log In')
class identityform(FlaskForm):
identitypswd = PasswordField(validators=[DataRequired(),Length(min=10)])
submit = SubmitField('Want to join')
def validate_regid(self,pregid):
user1 = Participation.query.filter_by(pregid = current_user.regid.data).all()
if user1 :
raise ValidationError('Already Enrolled :(')
class memberform(FlaskForm):
membername= StringField('Member Name:',
validators=[DataRequired(),Length(min=2,max=20),validators.regexp('^[a-
zA-Z\s]+$',message="Name contains only string ! Try Again")])
memberpassword = PasswordField('Password',validators=[DataRequired(),Length(min=10)])
secureid = StringField('UserId',
validators=[DataRequired(),Length(max=10),validators.regexp('[19]+
[BCA1.]+\d\d\d')])
membersubmit = SubmitField('Get In')
def validate_mname(self,mname):
user1 = Memberdb.query.filter_by(mname = mname.data).all()
if user1 is not None:
raise ValidationError('Username Already Exist :(')
def validate_mregid(self,mregid):
mregid = Memberdb.query.filter_by(mregid = mregid.data).all()
if mregid is not None:
raise ValidationError('Already Exist :(')
i have imported all the required module also but it's not working but the first login page is working . if anybody knows about this .Can anyone help me out of this.
You've coded two #login_manager.user_loaders. When you do that multiple times, the last one wins. (See here)
You'll have to choose which of Registration or Memberdb your app will use to represent a logged-in user.
in view.py:
#require_POST
#csrf_exempt
def ipn(request):
transactions_logger = logging.getLogger("django")
processor = Ipn(request.POST, logger=transactions_logger)
verification_success = processor.verify_ipn()
encoding = request.POST.get('ok_charset', None)
data = QueryDict(request.body, encoding=encoding)
if verification_success:
form = OkpayIpnForm(data)
if form.is_valid():
print("ALL FINE!!")
form.save()
return HttpResponse("")
In forms.py:
class OkpayIpnForm(forms.ModelForm):
class Meta:
model = OkpayIpn
exclude = []
Code for IPN Checkprocessor = Ipn(request.POST, logger=transactions_logger:
class Ipn(object):
OKPAY_VERIFICATION_URL = 'https://checkout.okpay.com/ipn-verify'
OKPAY_IPN_INVALID = b'INVALID'
OKPAY_IPN_VERIFIED = b'VERIFIED'
OKPAY_IPN_TEST = b'TEST'
OKPAY_STATUS_COMPLETED = 'completed'
__verification_result = False
def __init__(self, request_data, logger):
if 'ok_verify' in request_data:
raise Exception("ok_verify must not be present in initial request data for {}".format(
self.__class__.__name__
))
self._request_data = request_data
self.logger = logger
return
def verify_ipn(self):
self.__verification_result = False
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
verify_request_payload = {
'ok_verify': 'true',
}
verify_request_payload.update(self._request_data)
resp = requests.post(self.OKPAY_VERIFICATION_URL, data=verify_request_payload, headers=headers)
if resp.content == self.OKPAY_IPN_VERIFIED or resp.content == self.OKPAY_IPN_TEST:
self.__verification_result = True
# if resp.content == self.OKPAY_IPN_VERIFIED: # anyway disable test on production.
# self.__verification_result = True
return self.__verification_result
All is ok, I revice IPN and validate it, then I try to validate form and save it to Database.
But form doesn't pass validation and doesn't save to database.
Thank You for help
Problem was that 1 CharField of Model for saving IPN has maxlength=20, but recieved 40 symbols.
Thx jape he advised to add in form validation else statement and print form.errors
the error of of form validation was :
<li>ok_item_1_type<ul class="errorlist"><li>Ensure this value has at most 20 characters (it has 40).</li></ul></li>
The question I meet is that, when I use UserReg.objects.create(), it will report things above. And I really had look up the solution for seaveral hours, but it doesn't work. So I want to know where I am wrong and how can I fixed it ?
PS:forgive me poor English,thanks a lot.
I'm sorry about it, these code just a part of all codes, and I just post some.
my total project is
project/
app1/...
app2/...
other_general(manage.py etc)
======I will post all files=======
app1/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from app2.models import SocialMed,Article
class UserReg(AbstractUser):
nickname = models.CharField( max_length = 32 ,null = True, blank = True )
avatar = models.ImageField( upload_to = '/media/client/avatar/%Y/%m/%d/' , null = True, blank = True) # need to refer to something
signature = models.CharField( max_length = 200, null = True , blank = True )
user_uuid = models.IntegerField( null = True , blank = True,unique = True )
user_focus = models.ManyToManyField( SocialMed ,null = True , blank = True )
user_favor_article = models.ManyToManyField( Article, null = True, blank = True )
def __unicode__(self):
return self.nickname
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
def __init__(self,nickname):
nickname = 'None'
return nickname
app1/views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from client.models import UserReg
from app2.models import Article, SocialMed
def userRegiste( request ):
if request.method == 'POST':
user_name = request.POST.get('username')
pass_word = request.POST.get('password')
user_mail = request.POST.get('user_mail')
clienter = UserReg.objects.create_user( username=user_name, password = pass_word,email = user_mail )
print clienter
return render( request, 'register.html' )
else:
return render(request, 'register.html' )
TRACEBACK
Traceback Switch to copy-and-paste view
C:\Python27\lib\site-packages\django\core\handlers\base.py in get_response
response = middleware_method(request, callback, callback_args, callback_kwargs)
if response:
break
if response is None:
wrapped_callback = self.make_view_atomic(callback)
try:
response = wrapped_callback(request, *callback_args, **callback_kwargs) ...
except Exception as e:
# If the view raised an exception, run it through exception
# middleware, and if the exception middleware returns a
# response, use that. Otherwise, reraise the exception.
for middleware_method in self._exception_middleware:
response = middleware_method(request, e)
▶ Local vars
E:\django_file\zuiwan\client\views.py in userRegiste
def userRegiste( request ):
if request.method == 'POST':
user_name = request.POST.get('username')
pass_word = request.POST.get('password')
user_mail = request.POST.get('user_mail')
clienter = UserReg.objects.create_user( username=user_name, password = pass_word,email = user_mail ) ...
print clienter
return render( request, 'register.html' )
else:
return render(request, 'register.html' )
▶ Local vars
C:\Python27\lib\site-packages\django\contrib\auth\models.py in create_user
**extra_fields) ...
▶ Local vars
C:\Python27\lib\site-packages\django\contrib\auth\models.py in _create_user
date_joined=now, **extra_fields) ...
▶ Local vars
that's all , and I realy need your any advice, please
Replace
clienter = UserReg.objects.create_user( user_name, password = pass_word,email = user_mail )
with
clienter = UserReg.objects.create_user( username=user_name, password = pass_word,email = user_mail )
You can try this in another way.
user = UserReg()
user.username = user_name
user.email = user_mail
user.set_password(pass_word)
user.save()
and try by adding this in your user model
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'