Model turns into tuple in django's view. Whata hell? - django

I am trying to save a string (session hash) into django's model, but something is going wrong..
When I try to update the string, the model turns into a tuple causing AttributeError.
At the beginning everything was in a one 'post' function in view and yet not working. I tried to devide that stuff into functions, but it still does not help. Before the assignment type(session) says that 'session' is a model, not tuple.
View function code:
def post(self, request, *args, **kwargs):
data = json.loads(request.body.decode('utf-8'))
form = self.form_class(data)
if form.is_valid():
phone = form.cleaned_data.get('phone')
code = form.cleaned_data.get('code')
password = form.cleaned_data.get('password')
session = Session.objects.get_or_create(phone=phone, user=request.user.telegramuser)
if code and password:
return utils.sign_in(session, phone, code, password)
elif code:
return utils.sign_in(session, phone, code)
elif phone:
return utils.send_code_request(session, phone)
return JsonResponse({'state': 'none'})
utils.send_code_request and sign_in have the same structure
def send_code_request(session, phone):
result = asyncio.run(_send_code_request(phone))
# result - {
# 'state': 'ok',
# 'session': 'Hfkdi...AaF24s'
# }
if result['state'] == 'ok':
session.update_session(result.pop('session'))
return JsonResponse(result)
Manager
class DefaultManager(models.Manager):
def get_or_create(self, *args, **kwargs):
try:
return self.get(*args, **kwargs)
except ObjectDoesNotExist:
return self.create(*args, **kwargs)
Error:
Internal Server Error: /sessions/add/
Traceback (most recent call last):
File "C:\Users\ipyth\Documents\projects\telegram-sendall\.env\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\ipyth\Documents\projects\telegram-sendall\.env\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\ipyth\Documents\projects\telegram-sendall\.env\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\ipyth\Documents\projects\telegram-sendall\.env\lib\site-packages\django\views\generic\base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\ipyth\Documents\projects\telegram-sendall\.env\lib\site-packages\django\contrib\auth\mixins.py", line 52, in dispatch
return super().dispatch(request, *args, **kwargs)
File "C:\Users\ipyth\Documents\projects\telegram-sendall\.env\lib\site-packages\django\views\generic\base.py", line 97, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\ipyth\Documents\projects\telegram-sendall\sendall\views.py", line 78, in post
return utils.send_code_request(session, phone)
File "C:\Users\ipyth\Documents\projects\telegram-sendall\sendall\utils.py", line 46, in send_code_request
session.update_session(result.pop('session'))
AttributeError: 'tuple' object has no attribute 'update_session'
[23/Jul/2019 23:51:35] "POST /sessions/add/ HTTP/1.1" 500 86600

get_or_create does indeed return a tuple, of the object and a created flag. Either capture both:
session, created = Session.objects.get_or_create(phone=phone...)
Or, use create instead.
Or even better, use the form save method:
session = form.save()

Related

In Django's auth contrib module, how do I validate a token submitted from a reset password form?

I'm using Django 3.1 with its auth contrib module. I have an API-only application, in which I initiate a password reset using the following Django view
class ResetPasswordView(SuccessMessageMixin, PasswordResetView):
reset_password_template_name = 'templates/users/password_reset.html'
email_template_name = 'users/password_reset_email.html'
subject_template_name = 'users/password_reset_subject'
success_message = "We've emailed you instructions for setting your password, " \
"if an account exists with the email you entered. You should receive them shortly." \
" If you don't receive an email, " \
"please make sure you've entered the address you registered with, and check your spam folder."
success_url = reverse_lazy('users-home')
#method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
request.csrf_processing_done = True
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
email = json.loads(request.body).get('username')
try:
if User.objects.get(email=email).is_active:
form = PasswordResetForm({'email': email})
print("form valid? %s" % form.is_valid())
if form.is_valid():
request = HttpRequest()
request.META['SERVER_NAME'] = socket.gethostbyname('localhost') #'127.0.0.1'
request.META['SERVER_PORT'] = 8000
# calling save() sends the email
# check the form in the source code for the signature and defaults
form.save(request=request,
use_https=False,
from_email="laredotornado#yahoo.com",
email_template_name='../templates/users/password_reset_email.html')
print("email: %s " % email)
return super(ResetPasswordView, self).post(request, *args, **kwargs)
except Exception as e:
print("\n\nerror ...\n\n")
print(e)
# this for if the email is not in the db of the system
return super(ResetPasswordView, self).post(request, *args, **kwargs)
This generates an email in which a link appears, which looks similar to
http://127.0.0.1:8000/password-reset-confirm/Mg/bhd3nc-29fa9003c9c61c2bda5cff0a66b38bdf/
My question is, how do I submit this token (with the user's desired new password) back to the server so that the srver validates the token anad then updates the password for the user?
Edit: Stack trace per the answer given ...
Traceback (most recent call last):
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/utils/decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/directory/views.py", line 395, in dispatch
return super().dispatch(request, **data)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/utils/decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/views/decorators/debug.py", line 89, in sensitive_post_parameters_wrapper
return view(request, *args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/utils/decorators.py", line 43, in _wrapper
return bound_method(*args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "/Users/davea/Documents/workspace/chicommons/maps/web/venv/lib/python3.9/site-packages/django/contrib/auth/views.py", line 260, in dispatch
assert 'uidb64' in kwargs and 'token' in kwargs
Exception Type: AssertionError at /password-reset-complete
Reuse django.contrib.auth.views.PasswordResetConfirmView, which calls self.token_generator.check_token(self.user, session_token).
import json
from django.contrib.auth.views import INTERNAL_RESET_SESSION_TOKEN, PasswordResetConfirmView
from django.views.decorators.csrf import csrf_exempt
class ConfirmResetPasswordView(PasswordResetConfirmView):
#csrf_exempt
def dispatch(self, request):
data = self.data = json.loads(request.body)
# self.user = self.get_user(data["uidb64"])
# self.token_generator.check_token(self.user, data['token'])
self.request.session[INTERNAL_RESET_SESSION_TOKEN] = data.pop('token')
data['token'] = self.reset_url_token
return super().dispatch(request, **data)
def get_form_kwargs(self):
return {
'data': self.data,
'user': self.user,
}
def form_valid(self, form):
_ = form.save()
del self.request.session[INTERNAL_RESET_SESSION_TOKEN]
return HttpResponse()
Sample POST request body:
{
"uidb64": "Mg",
"token": "bhd3nc-29fa9003c9c61c2bda5cff0a66b38bdf",
"new_password1": "new_password",
"new_password2": "new_password"
}
It depends on the authentication strategy implemented with your API. From the fact that you are sending a user a token, I assume that you are using token authentication. :) It means that on the API side you need to implement password reset endpoint with token authentication. Do not forget to expire/blacklist the token.
Another strategy would be to run the password reset process using Django password reset views, without messing up with the API.

FormView get_context_data does not work when form is invalid

When creating a view using FormView class and using get_context_data to display some data on the test html page alongside the form ,
Error is received when the form gets invalid , and context data is not retrieved
in get_context_data
context['username'] = data['username']
KeyError: 'username'
Key Error is thrown when the form invalidates
class TestView(LoginRequiredMixin,FormView):
form_class = TestForm
template_name = 'test.html'
def get_context_data(self, **kwargs):
context = super(CredentialsView, self).get_context_data(**kwargs)
if self.request.user.is_authenticated:
data = TestViewSet.as_view({'get': 'list'})(self.request).data
context['username'] = data['username']
context['firstname'] = data['firstname']
context['lastname'] = data['lastname']
return context
def form_valid(self, form):
password = form.cleaned_data['password']
if form.is_valid():
return self.query_api(password)
else:
return super(TestView, self).form_valid(form)
here is the traceback
Traceback (most recent call last): File
"/usr/local/lib/python3.6/dist-packages/django/core/handlers/exception.py",
line 34, in inner response = get_response(request) File
"/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py",
line 115, in _get_response response =
self.process_exception_by_middleware(e, request) File
"/usr/local/lib/python3.6/dist-packages/django/core/handlers/base.py",
line 113, in _get_response response = wrapped_callback(request,
*callback_args, **callback_kwargs) File "/usr/local/lib/python3.6/dist-packages/django/views/generic/base.py",
line 71, in view return self.dispatch(request, *args, **kwargs) File
"/usr/local/lib/python3.6/dist-packages/django/contrib/auth/mixins.py",
line 52, in dispatch return super().dispatch(request, *args,
**kwargs) File "/usr/local/lib/python3.6/dist-packages/django/views/generic/base.py",
line 97, in dispatch return handler(request, *args, **kwargs) File
"./ssh/views.py", line 91, in post return self.form_invalid(form,
**kwargs) File "./ssh/views.py", line 77, in form_invalid context = self.get_context_data(**kwargs) File "./ssh/views.py", line 97, in
get_context_data kwargs['username'] = data['username'] KeyError:
'username'
In the Scenario Above ,
How can we get the context data when the form is invalid ?
How can we send the form errors back to html page when the form is
invalid ?
get_context_data is called before your form_valid function.
On the loading of the page you try to fetch the value of data["username"] while it's still not completed.
Basically :
GET on your View
-> get_context_data is called --> The form isn't completed yet
You could get your args on a post function.
def post(self, request, *args, **kwargs):
form = TestForm(request.POST)
if form.is_valid():
# Do Stuff
else:
# Something else
return render(ThePageWithTheForm)

Django JsonResponse: User matching query does not exist

So I´ve tried to make an ajax for my models but it is giving me a matching query does not exist, here is the full error:
Internal Server Error: /messages/notification/
Traceback (most recent call last):
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\views\generic\base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\contrib\auth\mixins.py", line 52, in dispatch
return super().dispatch(request, *args, **kwargs)
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\views\generic\base.py", line 97, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\views\generic\detail.py", line 106, in get
self.object = self.get_object()
File "C:\Users\berna\Desktop\Python & Javascript\Web development\MiFamiliaEsUnDesastre\mifamiliaesundesastre\chat\views.py", line 26, in get_object
obj, created = Thread.objects.get_or_new(self.request.user, other_username)
File "C:\Users\berna\Desktop\Python & Javascript\Web development\MiFamiliaEsUnDesastre\mifamiliaesundesastre\chat\models.py", line 29, in get_or_new
user2 = Klass.objects.get(username=other_username)
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\berna\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\query.py", line 415, in get
raise self.model.DoesNotExist(
django.contrib.auth.models.User.DoesNotExist: User matching query does not exist.
HTTP GET /messages/notification/ 500 [0.16, 127.0.0.1:56012]
Also here is my code:
models.py
class ProfileImage(models.Model):
"""
Profile model
"""
user = models.OneToOneField(
verbose_name=_('User'),
#to=settings.AUTH_USER_MODEL,
to = User,
related_name='profile',
on_delete=models.CASCADE
)
avatar = models.ImageField(upload_to='profile_image')
notifications = models.FloatField(default='0')
views.py
def notifications(request, user_id, *args, **kwargs):
user = User.objects.get(pk=user_id)
user.profile.notifications = user.profile.notifications + 1
user.save()
return JsonResponse(data=user.profile.notifications, safe=False)
urls.py
path('messages/notification/', notifications)
my html for the ajax call
// Add the notification val
$.get('notification/')
someone tell me that is that I dont have users, but when I do have a user, I dont know what is going on
You need to send user_id to the view:
path('messages/notification/(?P<user_id>[a-zA-Z0-9/_\.-]*)', notifications)
and:
$.get('messages/notification/{{ user.pk }}')
Update
You have to know their user id to get their notifications:
$.get('messages/notification/12234')
I assume you have a User model somewhere?
Also, user_id is coming in as a string, so need to int() that:
user = User.objects.get(pk=int(user_id))
Or use:
path('messages/notification/<int:user_id>', notifications)
So for does who saw this later, what I did is to change the
path('messages/notification/', notifications)
To
url(r'^ajax/notification/$', notification),

AttributeError: 'bytes' object has no attribute

I have a class in which I am checking user permissions, and depending on them, I return a list of results from models. Here is what I have:
from AnnualLeave.models import Leaves, RejectedLeaves, Employee
class GetLeaves:
def get_results(request):
try:
if request.user.groups.filter(name__in=['SuperAdmin']).exists():
return Leaves.objects.all()
elif request.user.groups.filter(name__in=['Admin']).exists():
return Leaves.objects.filter(employee_id=Employee.objects.get(manager_id=request.user.pk))
else:
messages.error(request, "You are not allowed on this page")
return render(request, 'users/home.html')
except (Leaves.DoesNotExist, Employee.DoesNotExist):
return []
def process_results(request):
leave_request = []
for leave in GetLeaves.get_results(request):
content = {'emp_id': leave.employee_id,
'emp_name': Employee.objects.get(user_id=leave.employee_id).user.get_full_name(),
'start_date': leave.start_date,
'end_date': leave.end_date,
'reason': leave.get_reason_display(),
'description': leave.description,
}
....
leave_request.append(content)
return leave_request
And then I'm calling process_results function in TemplateView like this:
class ProcessLeaveRequest(TemplateView):
template_name = 'LMSAdmin/process_leave_request.html'
def get(self, request, *args, **kwargs):
return render(request, self.template_name, {'leave_requests': GetLeaves.process_results(request)})
Here is a traceback of error:
Internal Server Error: /lms_admin/upcomingleaves/
Traceback (most recent call last):
File "C:\Program Files (x86)\Python37-32\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Program Files (x86)\Python37-32\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Program Files (x86)\Python37-32\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Program Files (x86)\Python37-32\lib\site-packages\django\views\generic\base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Program Files (x86)\Python37-32\lib\site-packages\django\views\generic\base.py", line 97, in dispatch
return handler(request, *args, **kwargs)
File "D:\Projects\LMS\LMSAdmin\views.py", line 77, in get
for leave in GetLeaves.process_results(request):
File "D:\Projects\LMS\LMSAdmin\views.py", line 39, in process_results
content = {'emp_id': leave.employee_id,
AttributeError: 'bytes' object has no attribute 'employee_id'
From what I can see, it is reading the entire webpage with the request parameter in functions. Like the get_results function is not returning a list, but the entire webpage. I do not understand why this is happening because it was working fine before without any changes.
You should not return a HttpRequest from get_results. Instead raise a PermissionDenied error.
else:
from django.core.exceptions import PermissionDenied
messages.error(request, "You are not allowed on this page")
raise PermissionDenied
If you want to redirect to a different page, handle that in the view. You can capture the PermissionDenied and return the redirect.

'dict' object has no attribute 'filter' in django

I have created a class based view
class MyLibrary(generic.DetailView):
context_object_name = 'data'
def get_template_names(self):
request = self.request
template_name = 'my_library.html'
return [template_name]
def get_queryset(self):
request = self.request
user = request.user
context = {}
mainData = []
userIssuedBooks = BooksIssued.objects.filter(user=user)
print(userIssuedBooks)
if user.is_authenticated():
context['issuedBooks'] = userIssuedBooks
return context
I am getting following error when the view is getting called
Internal Server Error: /mylibrary/1/admin
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\django\core\handlers\base.py", line 149,
in get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Python34\lib\site-packages\django\core\handlers\base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Python34\lib\site-packages\django\contrib\auth\decorators.py", line 2
3, in _wrapped_view
return view_func(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\django\views\generic\base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\django\views\generic\base.py", line 88, in
dispatch
return handler(request, *args, **kwargs)
File "C:\Python34\lib\site-packages\django\views\generic\detail.py", line 117,
in get
self.object = self.get_object()
File "C:\Python34\lib\site-packages\django\views\generic\detail.py", line 38,
in get_object
queryset = queryset.filter(pk=pk)
AttributeError: 'dict' object has no attribute 'filter'
I have no clue why this error is getting generated. Can someone help to find what is wrong here?
In django DetailView, get_queryset expects user to return a queryset(as the name implies) but you returned a dict context. You need to do your current stuff in get_context_data instead.
Django doc about adding extra context.