Django context processor 'AnonymousUser' object is not iterable - django

I'm new to Django and have the below context processor which passes some data which is displayed in the header. everything works ok until the user logs out which should direct them back to the login screen however I get the below error.
here is the code
from . models import Job
from datetime import date
def add_variable_to_context(request):
today = date.today()
engineers_jobs = Job.objects.filter(date_due__lte = today).filter(assigned_to=request.user)
engineer_overdue = 0
for job in engineers_jobs:
engineer_overdue += 1
return {
'engineers_jobs': engineers_jobs,
'engineer_overdue':engineer_overdue,
}
I then tried the below
from . models import Job
from datetime import date
def add_variable_to_context(request):
if request.user.is_authenticated:
today = date.today()
engineers_jobs = Job.objects.filter(date_due__lte = today).filter(assigned_to=request.user)
engineer_overdue = 0
for job in engineers_jobs:
engineer_overdue += 1
return {
'engineers_jobs': engineers_jobs,
'engineer_overdue':engineer_overdue,
}
but that displayed the following error
can someone help me where I am going wrong?
Thanks

Context processors must return a dictionary.
When the user is not logged in you are currently returning None, you should return an empty dictionary instead
from . models import Job
from datetime import date
def add_variable_to_context(request):
if request.user.is_authenticated:
today = date.today()
engineers_jobs = Job.objects.filter(date_due__lte = today).filter(assigned_to=request.user)
engineer_overdue = 0
for job in engineers_jobs:
engineer_overdue += 1
return {
'engineers_jobs': engineers_jobs,
'engineer_overdue':engineer_overdue,
}
return {}

Related

How to fix RuntimeWarning: DateTimeField Question.date_time received a naive datetime?

I want to delete 60 seconds old records but I am getting this error
RuntimeWarning: DateTimeField Question.date_time received a naive datetime (2022-08-27 16:09:30.659947) while time zone support is active.
def delete(self,request):
expiry_date_time = datetime.now() - timedelta(seconds=60)
print('Expiry time = ',expiry_date_time)
count = Question.objects.filter(date_time__gte = expiry_date_time).delete()
User.objects.all().update(total_question_added=0)
resp = {'resp' : 'All questions deleted.','Total question deleted':len(count)}
return Response(resp)
use timezone.now() [Django-doc] instead, this will add the timezone to the timestamp:
from django.http import JsonResponse
from django.utils.timezone import now
# …
def delete(self, request):
expiry_date_time = now() - timedelta(seconds=60)
count, __ = Question.objects.filter(date_time__gte=expiry_date_time).delete()
User.objects.update(total_question_added=0)
return JsonResponse(
{'resp': 'All questions deleted.', 'Total question deleted': count}
)

PUT and POST only specific fields without getting Serializer error in django

Here i wanted to post my data from thingspeak server to Django models and I have imported them by calling functions from DjangoApp.Thingspeak file.But, in this code GET and DELETE method works perfectly but, POST and PUT generates an error exception however, it also take some time for POST and PUT method too. But, as soon as I re-run my server. It catches value Immediately.
Can anybody help me to debug this...
Here is my code for views.py
import json
from django.views.decorators.csrf import csrf_exempt
from django.http.response import JsonResponse
from rest_framework.parsers import JSONParser
from DjangoApp.serializers import PatientSerializer
from DjangoApp.models import Patient
from DjangoApp.Thingspeak import tempValue,humValue,bodyTempValue
# Create your views here.
#csrf_exempt
def PatientAPI(request,id=0):
if request.method == 'GET':
patients = Patient.objects.all()
patients_serializer = PatientSerializer(patients,many=True)
return JsonResponse(patients_serializer.data,safe=False)
elif request.method == 'POST':
patient_data = JSONParser().parse(request)
patient = Patient.objects.create(PatientId=patient_data['PatientId'],PatientName=patient_data['PatientName'],RoomTemp=tempValue(),Humidity=humValue(),BodyTemp=bodyTempValue())
patient_data = json.parse(patient)
patients_serializer = PatientSerializer(data=patient_data)
if patients_serializer.is_valid():
patients_serializer.save()
return JsonResponse("Added Successfully", safe=False)
return JsonResponse("Failed to add", safe=False)
elif request.method == 'PUT':
patient_data = JSONParser().parse(request)
if patients_Serializer.is_valid():
patient=Patient.objects.filter(PatientId=patient_data['PatientId']).update(RoomTemp=tempValue(),Humidity=humValue(),BodyTemp=bodyTempValue())
patient = json.parse(patient)
patients_Serializer = PatientSerializer(patient, data=patient_data)
return JsonResponse("Updated Successfully", safe=False)
return JsonResponse("Failed to Update")
elif request.method == 'DELETE':
patient = Patient.objects.get(PatientId=id)
patient.delete()
return JsonResponse("Deleted Successfully", safe=False)
and Thingspeak.py code
import re
import urllib.request
with urllib.request.urlopen("https://api.thingspeak.com/channels/1633090/feeds/last.json?api_key=C15DPT91QNH37GY6&status=true") as url:
s = repr(url.read())
def tempValue():
temp = re.search('field1":"(.+?)",',s)
if temp:
return(temp.group(1))
def humValue():
hum = re.search('field2":"(.+?)",',s)
if hum:
return(hum.group(1))
def bodyTempValue():
bodyTemp = re.search('field3":"(.+?)",',s)
if bodyTemp:
return(bodyTemp.group(1))
Please do not parse JSON with regexes: JSON is a recursive language which can not be parsed (correctly) with a regular expression since JSON is not a regular language.
But even if you only parse subparts of regexes that might be a regular language, the language is a lot more complicated than what it looks like at first: there are rules about escaping strings, etc. so even if you manage to capture the data through a regex, it would be complicated to process it correctly.
You can interpret it as a JSON object, and then access the values associated with a key:
import requests
url = 'https://api.thingspeak.com/channels/1633090/feeds/last.json?api_key=C15DPT91QNH37GY6&status=true'
response = requests.get(url).json()
temp_value = response['field1']
hum_value = response['field2']
body_temp_value = response['field3']

User matching query does not exist. I want to add data if user is first time coming?

Actually I m working on Blood Donation system. I m checking that if user is already exist then I checking that He or She completed 90 days Or not if He or She completed then His or Her request will be accepted. if didn't complete then I will show message U have to Complete 90 days.
I add data through data admin side and checked on the base of the CNIC that he or she completed 90 days completed or not and its Working But Now the main problem is that If add New Data from Front End he said User matching query does not exist. Now I have to Add else part But I don't know How? please tell me about that I m stuck from past 4 days.
#forms.py
from django.core.exceptions import ValidationError
from django.forms import ModelForm
from django.shortcuts import redirect
from .models import User
from datetime import datetime,timedelta
class UserForm(ModelForm):
class Meta:
model = User
fields = "__all__"
def clean_cnic(self):
cnic = self.cleaned_data['cnic']
print("This is a cnic",cnic)
existuser = User.objects.get(cnic = cnic)
if existuser:
previous_date = existuser.last_donation
current_date = datetime.now().astimezone()
print(previous_date,"-----_---",current_date)
final = current_date - previous_date
print("The final is -> ",final)
if final < timedelta(days= 90):
raise ValidationError("U have to wait 90 days to complete")
return final
#views.py
from django.shortcuts import render
from .models import *
from .forms import UserForm
def home(request):
return render(request, 'home.html')
def donor(request):
if request.method == "POST":
userform = UserForm(request.POST)
if userform.is_valid():
userform.save()
else:
userform = UserForm()
return render(request, 'donor.html',{'userform':userform})
Simply, you need to make sure the user has exists.
def clean_cnic(self):
cnic = self.cleaned_data['cnic']
try:
existuser = User.objects.get(cnic=cnic)
except User.DoesNotExist:
raise ValidationError("User not found!")
previous_date = existuser.last_donation
current_date = datetime.now().astimezone()
final = current_date - previous_date
if final < timedelta(days= 90):
raise ValidationError("U have to wait 90 days to complete")
return final

Django : matching query does not exist

I am getting error while creating an instance of ModelForm in DJango.
I am not always facing the issue but sometimes it work fine and sometimes it gives me error.
ModelFOrm code :
class ClientinfoForm(ModelForm):
Account_Name = forms.CharField(disabled=True)
class Meta:
model = AccountDescription
fields = ['Account_Name','short_Name','group_Master_Project_Code','account_Logo','vertical','client_Website','client_Revenue','Employee_Count','client_Industry_Segment','delivery_Manager_Mail','project_Manager_Mail']
labels = {'client_Revenue':'Client Revenue(in USD Billion)','vertical':'Industry Vertical'}
help_texts = {'client_revenue' : '(In Billion USD)' }
views.py code
def save_client_info(request):
fm = ClientinfoForm(request.POST, instance = AccountDescription.objects.get(Account_Name = acc_name),files = request.FILES or None)
save_form(request,fm)
def clientinfo(request):
if request.user.is_authenticated:
if request.method == 'POST':
print("inside form")
save_client_info(request)
global s4_option
s4_option = AccountDescription.objects.filter(Account_Name = acc_name).values('s4_data')
s4_option = s4_option[0]['s4_data']
accdata = AccountDescription.objects.filter(Account_Name = acc_name)
clientdata = ClientinfoForm(instance = AccountDescription.objects.get(Account_Name = acc_name))
return render(request, 'AccountData/ClientInfo.html',{'name' : 'clientinfo','form':clientdata,'acntdata':accdata,'content':editoption})
Sometimes, when I save it works perfectly fine but sometimes it give matching query doesn't exist.
Let me know if more information is required.
Change the line
instance = AccountDescription.objects.get(Account_Name = acc_name)
in save_client_info function to something like
from django.shortcuts import get_object_or_404
instance = get_object_or_404(AccountDescription, Account_Name=acc_name)
Note: I assumed that you've defined acc_name properly before this line somewhere in your codes.
Because there will be always some situations that this record does not exists and there for Django will raise a does not exist error type. Or you can also return a desired response if this query doesn't exist in your database like:
from django.http import HttpResponse
try:
fm = ClientinfoForm(request.POST, instance = AccountDescription.objects.get(Account_Name = acc_name),files = request.FILES or None)
except AccountDescription.DoesNotExist:
return HttpResponse("Requested account does not exist") # or any other responses

How can I implement incremental wait time for django axes?

I'm looking to implement django axes for brute force protection for my application. I want to implement something like this "lockout for 5 minutes after 5 failed attempts, lockout for 10 minutes after another 5 attempts"
Seems like the example in the doc is more straightforward with a fixed wait time, so I want to know if it's possible to implement something like this.
Yes this is possible, but will require several items to setup.
models.py
from axes.models import AccessAttempt
from django.db import models
from django.utils.translation import gettext_lazy as _
class AccessAttemptAddons(models.Model):
accessattempt = models.OneToOneField(AccessAttempt, on_delete=models.CASCADE)
expiration_date = models.DateTimeField(_("Expiration Time"), auto_now_add=False)
This models.py file is located within my login app(directory: project_name/login/models.py). This will create a new table called login_accessattemptaddons and establishes a "one to one" relationship with Django Axes' AccessAttempt table. This is necessary so that each entry in the AccessAttempt table is associated with each entry in the AccessAttemptAddons table; thus, making the expiration_date column in AccessAttemptAddons an extension of the AccessAttempt table.
settings.py
AXES_FAILURE_LIMIT = 5
AXES_LOCK_OUT_AT_FAILURE = True
AXES_LOCK_OUT_BY_COMBINATION_USER_AND_IP = True
AXES_LOCKOUT_CALLABLE = "login.views.timeout"
In settings.py the AXES_FAILURE_LIMIT is set to 5, meaning after the 5th failure to login, AXES_LOCKOUT_CALLABLE executes. AXES_LOCKOUT_CALLABLE is set to "login.views.timeout." I am not sure if this is best practice, but the function to run after failure is located within my projects login app, views.py file, and in my views.py file, a method called "timeout."
views.py
import datetime
from axes.models import AccessAttempt
from django.contrib.auth import login, authenticate
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django.views import View
from .models import AccessAttemptAddons
from .forms import LoginForm
class LoginView(View):
form = LoginForm
context = {"form": form}
base_page = "login/index.html"
auth_base_page = "login/index.auth.html"
def get(self, request):
""" returns the login app index page """
if(request.user.is_authenticated):
return render(request, self.auth_base_page, self.context)
else:
return render(request, self.base_page, self.context)
def post(self, request):
""" Handles logging the user in """
# passing the request to the form to access in our forms.py file
form_post = self.form(request.POST, request=request)
if(form_post.is_valid()):
email = form_post.cleaned_data["email"]
password = form_post.cleaned_data["password"]
user = authenticate(username=email, password=password)
login(request, user, backend="django.contrib.auth.backends.ModelBackend")
return HttpResponseRedirect(reverse("account:index"))
else:
errors = form_post.non_field_errors()
context = {"form": form_post, "errors": errors}
return render(request, self.base_page, context)
def timeout(request):
try:
loginview = LoginView()
username = request.POST.get("email")
ip_address = request.axes_ip_address
account = AccessAttempt.objects.filter(username=username).filter(ip_address=ip_address)
current_time = datetime.datetime.now()
number_of_attempts = account.failures_since_start
threshold = (number_of_attempts / 5) * 5
form = LoginForm(request.POST)
error = f"Access attempts exceeded. Please wait {threshold} minutes"
base_page = "login/index.html"
context = {"form": form, "errors": error}
result = AccessAttempt.objects.raw(
'''
SELECT axes_accessattempt.id, login_accessattemptaddons.expiration_date
FROM axes_accessattempt
INNER JOIN login_accessattemptaddons
ON axes_accessattempt.id = login_accessattemptaddons.accessattempt_id
WHERE axes_accessattempt.username = %s and axes_accessattempt.ip_address = %s
''', [username, ip_address]
)[0]
if(current_time < result.expiration_date):
return render(request, base_page, context)
else:
account.delete()
account_page = loginview.post(request)
return account_page
except IndexError:
expiration_date = current_time + datetime.timedelta(minutes=threshold)
id = AccessAttempt.objects.filter(username=username, ip_address=ip_address)[0].id
addons = AccessAttemptAddons(expiration_date=expiration_date, accessattempt_id=id)
addons.save()
return render(request, base_page, context)
This is a copy of my views.py(directory: project_name/login/views.py). Starting with the timeout method, note that the threshold formula is the number of attempts divided by 5 then the result is multiplied by 5. Example: (10 failed attempts / 5 ) * 5min = 10min timeout. For attempts non divisible by 5(11, 12, .. 14) they are rounded down to 10min lockout. For 15 failed attempts to 19 failed attempts, the lockout time would be 15min.
Continuing with the code, the AccessAttempt table and AccessAttemptAddons table is joined on the one to one field "accessattempt_id." This creates a resultant table where expiration_date information for each related AccessAttempt id can be obtained. If there are no entries for the current failed attempt(brand new account lockout) then an index error occurs. The error is caught and creates a new expiration entry in the AccessAttemptAddons table with the formula above. On any subsequent attempts, the raw sql will pass without index failures because there is now an existing expiration_date entry.
This leads to the the if statement blocks to check to see if the account is ready to be unlocked or return an error page back to the user. If the current time is less than the expiration_date entry within the result table, then return a page with the error message. If the current time is greater, it means that enough time has passed to retry logging into the account. The request is handed off to the login view "post" method. Any failures after this repeats the timeout method steps.
Closing remarks
The timeout method in the views.py is what is necessary; how the request is handled after the lockout expires is up to the developer. I only showed how I handled it with a class based login view.