Am trying to resend email to any one that not yet confirmed his account .
models.py
class Subscribers(Base):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(50))
confirmed = db.Column(db.Boolean(), default=False)
def confirm(self, token):
s = Serializer(app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
return False
if data.get('confirm') != self.id:
return False
self.confirmed = True
db.session.add(self)
return True
def generate_confirmation_token(self, expiration=3600):
s = Serializer(app.config['SECRET_KEY'], expiration)
return s.dumps({'confirm': self.id})
def get_token(self, expiration=1800):
s = Serializer(app.config['SECRET_KEY'], expiration)
return s.dumps({'email': self.id}).decode('utf-8')
#staticmethod
def verify_token(token):
s = Serializer(app.config['SECRET_KEY'])
try:
data = s.loads(token)
except:
return None
id = data.get('email')
if id:
return User.query.get(id)
return None
This is the function where the confirmation process handled:
#app.route('/send-confirmation/<email>/<token>')
def confirm(token,email):
subre = Subscribers.query.filter_by(email=email).first()
if subre.confirmed:
flash('Э.почта уже подтверждена.')
return redirect(url_for('index'))
if subre.confirm(token):
subre.confirmed = True
db.session.add(subre)
db.session.commit()
send_email(subre.email, 'Благодарим Вас за подписку на наш сайт', 'auth/subscribe/thanks', subre=subre, token=token)
flash('Вы подтвердили свою электронную почту, спасибо!')
else:
flash('Ссылка для подтверждения является недействительным или истек.')
return redirect(url_for('index'))
Tell now everything is working very well, am trying to fetch each account that not yet confirmed by sending them another message asking them to confirm there account, here is the function :
#app.before_request
def resend_confirmation():
subscribers = Subscribers.query.filter_by(confirmed=False)
for sub in subscribers:
email = sub.email
token = email.generate_confirmation_token()
send_email(email, 'Подтверждение по электронной почте было отправлено Вам по электронной почте.',
'auth/email/resend', email=email, token=token)
Here am getting an error says:
AttributeError: 'unicode' object has no attribute 'generate_confirmation_token'
i tried to add __unicode__ function in the model but without avail .
Please any help .
You are trying to call generate_confirmation_token method on email, but you should use Subscribers instance:
#app.before_request
def resend_confirmation():
subscribers = Subscribers.query.filter_by(confirmed=False)
for sub in subscribers:
token = sub.generate_confirmation_token()
send_email(sub.email, 'Подтверждение по электронной почте было отправлено Вам по электронной почте.',
'auth/email/resend', email=email, token=token)
Related
I am trying to send otp and then validate otp for login. I am able to send otp but it is not validating for some reason.
the code for sending otp is below and it is working fine-
class SendOTP(APIView):
permission_classes = (AllowAny, )
def post(self, request, *args, **kwargs):
email = request.data.get('email')
if email:
email = str(email)
user = User.objects.filter(email__iexact = email)
if user.exists():
key = send_otp(email)
if key:
old = User.objects.filter(email__iexact=email)
if old.exists():
old = old.first()
count = old.count
old.count = count + 1
old.save()
print('Count Increase', count)
return Response({
'status': True,
'detail': 'OTP sent successfully.'
})
code for generating 6 digit otp is -
def send_otp(email):
if email:
digits = [i for i in range(0, 10)]
key = ""
for i in range(6):
index = math.floor(random.random() * 10)
key += str(digits[index])
print(key)
return key
else:
return False
code for validating email and otp is below but it is not working-
class ValidateOTP(APIView):
permission_classes = (AllowAny, )
def post(self, request, *args, **kwargs):
email = request.data.get('email' , False)
otp_sent = request.data.get('otp', False)
if email and otp_sent:
e_mail = User.objects.filter(email__iexact = email)
if e_mail.exists():
e_mail = e_mail.first()
otp = e_mail.otp
print(otp, e_mail, otp_sent)
if str(otp_sent) == str(otp):
old.validated = True
old.save()
try:
payload = JWT_PAYLOAD_HANDLER(old)
jwt_token = JWT_ENCODE_HANDLER(payload)
update_last_login(None, old)
except User.DoesNotExist:
raise serializers.ValidationError(
'User with given email and password does not exists'
)
return Response({
'status' : True,
'email': email,
'token': jwt_token,
'detail' : 'OTP mactched.'
})
else:
return Response({
'status' : False,
'detail' : 'OTP incorrect.'
})
else:
return Response({
'status' : False,
'detail' : 'First proceed via sending otp request.'
})
else:
return Response({
'status' : False,
'detail' : 'Please provide both email and otp for validations'
})
it's is showing None for otp = e_mail.otp. is there a way to make it work?
I don't see where old.otp is being set in the SendOTP class, that's probably why it's None. Should be something like this:
old.count = count + 1
old.otp = key
old.save()
Also, if old.exists(): looks weird in ValidateOTP, since there is no references to the old variable, probably should be if e_mail.exists().
I have a timeclock app for employees to check-in/check-out with which works ok, however when you're on the user-activity page and either check in or check out once it submits the form it sends you back to the user-activity.html page, but no data is loaded in the table and its not loading data from the view. Once you refresh the page the data is there again but I'm not sure why this is happening. I'll attach 2 images, one before the checkin/checkout button is pressed, and one after
and here is my view. Thanks for any help you can give
class ActivityView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
context = {}
toggle = UserActivity.objects.current(request.user)
user_data = UserActivity.objects.filter(user=request.user).order_by('-timestamp')
current_users = UserActivity.objects.order_by('user', '-timestamp').distinct('user')
context['toggle'] = toggle
context['user_data'] = user_data
context['current_users'] = current_users
return render(request, "administration/timesheets/user-activity.html", context)
def post(self, request, *args, **kwargs):
context = {}
toggle = UserActivity.objects.toggle(request.user)
context['toggle'] = toggle
return render(request, "administration/timesheets/user-activity.html", context)
EDIT
Also here is my model...
USER_ACTIVITY_CHOICES = (
('checkin', 'Check In'),
('checkout', 'Check Out'),
)
class UserActivityManager(models.Manager):
def current(self, user):
current_obj = self.get_queryset().filter(user=user).order_by('-timestamp').first()
return current_obj
def toggle(self, user):
last_item = self.current(user)
activity = "checkin"
if last_item is not None:
if last_item.timestamp <= tz.localize(datetime.datetime.now()):
pass
if last_item.activity == "checkin":
activity = "checkout"
obj = self.model(
user=user,
activity=activity
)
obj.save()
return obj
class UserActivity(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
activity = models.CharField(max_length=120, default='checkin', choices=USER_ACTIVITY_CHOICES)
timestamp = models.DateTimeField(auto_now_add=True)
time_delta = models.DecimalField(decimal_places=2, max_digits=4, default='0.00', blank=True, null=True)
status = models.CharField(max_length=60, null=True, blank=True)
description = models.TextField(blank=True, null=True)
objects = UserActivityManager()
def __unicode__(self):
return str(self.activity)
def __str__(self):
return str(self.activity)
class Meta:
verbose_name = 'User Activity'
verbose_name_plural = "User Activities"
def next_activity(self):
next = "Check in"
if self.activity == "checkin":
next = "Check out"
return next
#property
def current(self):
current = 'Checked Out'
if self.activity == 'checkin':
current = "Checked in"
return current
def clean(self, *args, **kwargs):
if self.user:
user_activities = UserActivity.objects.exclude(
id=self.id
).filter(
user = self.user
).order_by('-timestamp')
if user_activities.exists():
recent_ = user_activities.first()
if self.activity == recent_.activity:
message = "%s is not a valid activity for this user" %(self.get_activity_display())
raise ValidationError(message)
else:
if self.activity != "checkin":
message = "%s is not a valid activity for this user" %(self.get_activity_display())
raise ValidationError(message)
return super(UserActivity, self).clean(*args, **kwargs)
In your post function, I think you have a typing mistake :
toggle = UserActivity.objects.toggle(request.user)
I think that instead, you need :
toggle = UserActivity.objects.current(request.user)
So I have this custom register API which registers a user, but when user successfully register, I want it to have this message "You have successfully register an account!" But I tried a different method but get an error instead.
serializer.py
class UserCreate2Serializer(ModelSerializer):
email = EmailField(label='Email Address')
valid_time_formats = ['%H:%M', '%I:%M%p', '%I:%M %p']
birthTime = serializers.TimeField(format='%I:%M %p', input_formats=valid_time_formats, allow_null=True, required=False)
class Meta:
model = MyUser
fields = ['username', 'password', 'email', 'first_name', 'last_name', 'gender', 'nric', 'birthday', 'birthTime']
extra_kwargs = {"password": {"write_only": True}}
def validate(self, data): # to validate if the user have been used
email = data['email']
user_queryset = MyUser.objects.filter(email=email)
if user_queryset.exists():
raise ValidationError("This user has already registered.")
return data
def create(self, validated_data):
username = validated_data['username']
password = validated_data['password']
email = validated_data['email']
first_name = validated_data['first_name']
last_name = validated_data['last_name']
gender = validated_data['gender']
nric = validated_data['nric']
birthday = validated_data['birthday']
birthTime = validated_data['birthTime']
user_obj = MyUser(
username = username,
email = email,
first_name = first_name,
last_name = last_name,
gender = gender,
nric = nric,
birthday = birthday,
birthTime = birthTime,
)
user_obj.set_password(password)
user_obj.save()
return validated
views.py
class CreateUser2View(CreateAPIView):
permission_classes = [AllowAny]
serializer_class = UserCreate2Serializer
queryset = MyUser.objects.all()
I tried changing this into the serializer
user_obj.set_password(password)
user_obj.save()
content = {'Message': 'You have successfully register an account'}
return content
But got an error instead. I'm unsure how to do the custom response as I only know it is to be done on views.py.
But if I do this on view:
class CreateUser2View(CreateAPIView):
permission_classes = [AllowAny]
serializer_class = UserCreate2Serializer
queryset = MyUser.objects.all()
def post(self, request):
content = {'Message': 'You have successfully register'}
return Response(content, status=status.HTTP_200_OK)
It will show this even if the validation is incorrect. Please help me as I'm still inexperienced in DRF.
class CreateUser2View(CreateAPIView):
permission_classes = [AllowAny]
serializer_class = UserCreate2Serializer
queryset = MyUser.objects.all()
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response({'Message': 'You have successfully register'}, status=status.HTTP_201_CREATED, headers=headers)
from rest_framework import status
from rest_framework.views import exception_handler as base_handler
def exception_handler(exception, context):
"""
Django rest framework for custom exception handler
#exception : Exception
#context : Context
"""
response = base_handler(exception, context)
if response is not None:
response = custom_response(response)
return response
def serializer_errors(data):
"""
Django rest framework serializing the errors
#data : data is python error dictionary
"""
errors = {}
got_msg = False
message = "Bad request."
if isinstance(data, dict):
for key, value in data.items():
try:
if isinstance(value, list):
value = ", ".join(value)
except Exception:
pass
if not got_msg:
if value:
message = value
got_msg = True
errors[key] = value
if not isinstance(message, str):
message = "Bad request"
return errors, message
def error(source, detail, code):
"""
Create python dictionary of error
#source : Where coming the error
#detail : Error detail information
"""
error = {}
error["source"] = source
error["detail"] = detail
if code:
error["code"] = code
return error
def custom_response(response):
"""
Modification the response of django rest framework
#response : Return response
"""
modified_data = {}
modified_data["code"] = response.status_code
modified_data["status"] = get_status(response.status_code)
data, message = serializer_errors(response.data)
modified_data["message"] = message
modified_data["errors"] = data
response.data = modified_data
return response
def get_status(status_code):
"""
Return result base on return http status
#status_code : HTTP status code
"""
result = ""
if status_code == status.HTTP_200_OK:
result = "Success"
elif status_code == status.HTTP_201_CREATED:
result = "Instance create"
elif status_code == status.HTTP_204_NO_CONTENT:
result = "Instance deleted"
elif status_code == status.HTTP_403_FORBIDDEN:
result = "Forbidden error"
elif status_code == status.HTTP_404_NOT_FOUND:
result = "Instance not found"
elif status_code == status.HTTP_400_BAD_REQUEST:
result = "Bad request"
elif status_code == status.HTTP_401_UNAUTHORIZED:
result = "Unauthorized request"
elif status_code == status.HTTP_500_INTERNAL_SERVER_ERROR:
result = "Internal server error"
else:
result = "Unknown error"
return result
I have a working piece of code which runs fine.
Here's the model:
class Therapist(models.Model):
user = models.OneToOneField(User)
SEX_CHOICES = (
('M','male'),
('F','female'),
)
sex = EncryptedCharField(choices = SEX_CHOICES, blank=False, max_length=20, verbose_name = "Płeć")
company = models.ManyToManyField(Company, blank=True, verbose_name = "Firma")
subscription = models.ForeignKey(Subscription, blank=False, verbose_name = "Abonament")
uuid = models.UUIDField(primary_key=False, editable=False, default=uuid.uuid4, null=True, blank=True)
def __unicode__(self):
return '%s %s' % (self.user.first_name, self.user.last_name)
def __str__(self):
return '%s %s' % (self.user.first_name, self.user.last_name)
The form:
class MyRegistrationForm(forms.Form):
SEX_CHOICES = (
('F', 'kobieta'),
('M', 'mężczyzna'),
)
first_name = forms.CharField(label="Imię")
last_name = forms.CharField(label="Nazwisko")
user_email = forms.EmailField(label="Adres e-mail")
user_sex = forms.ChoiceField(label="Wybierz swoją płeć", choices = SEX_CHOICES)
username = forms.CharField(label="Nazwa użytkownika")
password1 = forms.CharField(label="Wpisz hasło", widget = PasswordInput())
password2 = forms.CharField(label="Powtórz hasło", widget = PasswordInput())
def clean_username(self):
username = self.cleaned_data['username']
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
# this is to verify if any user exists at all. If yes - do not allow other users to be created!
if Therapist.objects.all().exists():
raise forms.ValidationError(_(u'Jakiś użytkownik już istnieje, a Twoja wersja programu nie pozwala na tworzenie więcej niż 1 użytkownika. Wersje dla więcej niż jednego terapeuty dostępne pod kontakt#zapiszsesje.pl'), code='invalid')
else:
return username
raise forms.ValidationError(u'Użytkownik o nazwie "%s" już istnieje.' % username)
def clean_user_email(self):
email = self.cleaned_data['user_email']
try:
user = User.objects.get(email =email)
except User.DoesNotExist:
return email
raise forms.ValidationError(u'Użytkownik o takim adresie email już istnieje.')
& the view:
def myRegistrationView(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username = form.cleaned_data['username'],
email = form.cleaned_data['user_email'],
password = form.cleaned_data['password1'],
first_name = form.cleaned_data['first_name'],
last_name = form.cleaned_data['last_name']
)
user.save()
subscription = Subscription(
expired_on = datetime.datetime.now() + datetime.timedelta(days = 90)
)
subscription.save()
therapist = Therapist(
user = user,
sex = form.cleaned_data['user_sex'],
subscription = subscription,
)
therapist.save()
return HttpResponseRedirect(reverse('registration_gotowe'))
else:
form = MyRegistrationForm()
param = {
'form':form
}
return render(request, 'registration/registration_form.html', param)
When I package the app using a Mac and PyInstaller the app works fine until I get to that view and try to register creating a User, Subscription and Therapist. In that moment I get a
TypeError at /konto/register/
'NoneType' object is not iterable error ...
The same code works fine on Windows before and after the PyInstaller compilation to an exe file. Apart from that the app seems to work fine without any errors.
If I comment out the part of the code where the Therapist is created in the view:
therapist = Therapist(
user = user,
sex = form.cleaned_data['user_sex'],
subscription = subscription,
)
therapist.save()
the app 'works' fine - this error does not occur....
What am I missing?
I try to use flask login in may app:
My controller:
#app.route("/process_log", methods=['POST'])
def process_login():
filled_form = LoginForm(request.form)
if filled_form.validate():
phone = filled_form.phone.data
password = filled_form.password.data
if User.phone_exists(phone) and User.pass_match(phone, password):
user = User.get_by_phone(phone)
login_user(user.get_id)
return redirect(url_for("index"))
else:
return render_template("login.html", form = filled_form, error = u"Не верный логин или пароль")
else:
return render_template("home.html", form = filled_form)
and I have some class with defined functions which required for API of flask login
My User class:
from pymongo import MongoClient
from bson.objectid import ObjectId
class User():
client = MongoClient()
db = client['test']
col = db['user']
user_id = None
def __init__(self, dic):
self.dic = dic
def is_authenticated():
return True
def is_anonymous():
return False
def is_active():
return True
def get_id(self):
return unicode(str(self.user_id))
def save(self):
self.user_id = self.col.insert(self.dic)
print "Debug:" + str(self.user_id)
#staticmethod
def _get_col():
client = MongoClient()
db = client['test']
col = db['user']
return col
#staticmethod
def phone_exists(phone):
col = User._get_col()
if col.find_one({'phone': phone}) != None:
return True
else:
return False
#staticmethod
def pass_match(phone, password):
col = User._get_col()
if col.find_one({'phone': phone})['password'] == password:
return True
else:
return False
#staticmethod
def get(userid):
col = User._get_col()
return col.find_one({'_id':userid})
#staticmethod
def get_by_phone(phone):
col = User._get_col()
dic = col.find_one({'phone': phone})
print dic['password']
return User(dic)
As you see function is_active is defined(Note:I also tried to pass refference with self)
But I still have this error AttributeError: 'function' object has no attribute 'is_active'
I am sorry for too much code here, but it should be pretty straightforward.
Note: I am using mongodb for my project.
Please help me to find my error. Thank you too much
One more thing:
Should I provide login_user(....) with Id or with my user object?
You must sent to login_user User instance (not id), see: https://github.com/maxcountryman/flask-login/blob/master/flask_login.py#L576.
So next code must work:
user = User.get_by_phone(phone)
login_user(user)