I have a problem with this code in django
I have defined two global variables
But Django does not identify them
my view:
global phone,rand_num
def phone_login(request):
if request.method == 'POST':
form = PhoneLoginForm(request.POST)
if form.is_valid():
phone = f"0{form.cleaned_data['phone']}"
rand_num = randint(1000, 9999)
api = KavenegarAPI('mytoken!')
params = { 'sender' : '', 'receptor': phone , 'message' : rand_num }
api.sms_send(params)
return redirect('account:verify')
else :
form = PhoneLoginForm()
return render(request,'account/phone_login.html',{'form':form})
def verify(request):
if request.method == "POST":
form = VerifyCodeForm(request.POST)
if form.is_valid():
if rand_num == form.cleaned_data['code']:
profile = get_object_or_404(Profile, phone = phone)
user = get_object_or_404(User,profile__id = profile.id)
login(request,user)
messages.success(request,'logged in successfully' , 'success')
return redirect('popasssts:all_posts')
else:
messages.error(request,'your code is wrong','warning')
else:
form = VerifyCodeForm()
return render(request,'account/verify.html',{'form' : form})
my urls :
path('verify/',views.verify,name='verify'),
i have this error :
NameError at /account/verify/
name 'rand_num' is not defined
Request Method: POST
Request URL: http://127.0.0.1:8000/account/verify/
Django Version: 3.0.7
Exception Type: NameError
Exception Value:
name 'rand_num' is not defined
I want the user to enter the site after entering the SMS code.
Regarding the global variables, you need to put the global keyword inside the functions and assign initial values to the variables outside:
phone = ""
rand_num = -1
def phone_login(request):
global phone, rand_num
# ...
def verify(request):
global phone, rand_num
# ...
With this approach, the values of phone and rand_num are shared among all users of the application. If your application have multiple users, a better approach would be to store the values in the current user's session:
def phone_login(request):
if request.method == 'POST':
# ...
if form.is_valid():
# ...
# Save the values in the session
request.session["phone"] = phone
request.session["rand_num"] = rand_num
# ...
def verify(request):
if request.method == "POST":
# ...
if form.is_valid():
# Get the values from the session, setting
# default values in case they don't exist.
phone = request.session.get("phone", "")
rand_num = request.session.get("rand_num", -1)
# ...
For using sessions, the django.contrib.sessions application must be enabled in the INSTALLED_APPS list of the settings.py file of the Django project. Also, this application must be migrated to the project's database with the command python manage.py migrate.
In the official Django documentation you have more information about sessions.
Caution: Global variables violates maybe the most important principle of the programming, the encapsulation. Using them, will turn your code to a spaghetti. Don't use them. (Unless there is another way)
Here is what encapsulation means:
...Encapsulation refers to the bundling of data with the methods that operate on that data, or the restricting of direct access to some of an object's components.
Source: Wikipedia
If you really want to use it, here is your problem: global keyword should be used in functions.
Let's try that way:
phone = ""
rand_num = 0
def phone_login(request):
global phone, rand_num
if request.method == 'POST':
...
def verify(request):
global phone, rand_num
if request.method == "POST":
...
Related
I have created a function called a panel.
When i run the server it gives an error " UnboundLocalError at /service-panel/ local variable 'username' referenced before assignment" .
I don't know what is getting wrong.
Here is views.py
#login_required
def panel(request):
if(request.session.has_key('username')):
username = request.session['username']
data = Enquiry.objects.filter(service=request.session['service'])
return render(request, 'service-provider-panel/base.html', {'username':username, 'data':data})
You have a logical error:
#login_required
def panel(request):
if(request.session.has_key('username')):
username = request.session['username']
data = Enquiry.objects.filter(service=request.session['service'])
else:
# else statement is needed because the variables username and data must be defined.
username = None
data = None
return render(request, 'service-provider-panel/base.html', {'username':username, 'data':data})
The problem is that the condition request.session.has_key('username') can be False. Then, the username variable will not be assigned. The same with data variable.
A solution could be:
#login_required
def panel(request):
username = None
data = None
if(request.session.has_key('username')):
username = request.session['username']
data = Enquiry.objects.filter(service=request.session['service'])
return render(request, 'service-provider-panel/base.html', {'username':username, 'data':data})
You will need to control the logic in the template (service-provider-panel/base.html) when data or username is None.
I'm new to Django's testing and trying to write test functions for views, but I don't get the whole test view thing, I've seen a lot of examples but it seems to be to difficult, I need an example on something I wrote to get the idea.
here's a function I want to test its post and get:
def ForgetPasswordRegistry(self, request):
forgetpassword = True
if request.method == 'GET':
if 'UserID' in request.session:
forgetpassword = False
return request, forgetpassword
elif request.method == 'POST':
email = request.POST['email']
if self.IsUserExist(email):
forget = models.ForgetPasswordRegistry()
forget.UserID = self.GetUser(email)
forget.Access = 1
session = random.randint(999999999999999, 9999999999999999999999999999999999)
forget.Session = str(session)
link = 'http://127.0.0.1:8000/home/resetpassword/' + forget.Session
self.SendEmail('Reset-Password', link, [forget.UserID.Email])
forget.save()
FeedBack = ' Check Your Mail You Got A Recovery Mail'
AlertType = 'alert-success'
return request, AlertType, None, FeedBack, None, None
else:
AlertType = 'alert-danger'
ModalFeedBack = 'This Email Dose Not Exist'
EmailErrors = 'This Email Dose Not Exist'
return request, AlertType, forgetpassword, None, EmailErrors, ModalFeedBack
Don't let the concept of views confuse you!! Essentially there is a python function that you need to exercise certain conditionals of.
It looks like there are 4 main branches:
GET not in session
GET in session
POST exists
POST does not exist
so there should probably be at least 4 different tests. I'll post the first one because it is pretty straightforward:
def ForgetPasswordRegistry(self, request):
forgetpassword = True
if request.method == 'GET':
if 'UserID' in request.session:
forgetpassword = False
return request, forgetpassword
def test_forget_get_user_id_in_session(self):
request = Mock(session={'UserID': 'here'}, method='GET')
# instantiate your view class
yourview = YourView()
sefl.assertEqual(yourview.ForgetPasswordRegistry(request), (request, False))
The post user exists branch is a little more complicated because there are more things that the test needs to account for, and potentially provide stub implementations for:
SendEmail
GetUser
models.ForgetPasswordRegistry()
Use Django's test client: https://docs.djangoproject.com/en/stable/topics/testing/tools/#the-test-client
Example:
from django.test import Client, TestCase
class ViewTestCase(TestCase):
def test_post_creation(self):
c = Client() # instantiate the Django test client
response = c.get('/forgetpassword/')
self.assertEqual(response.status, 200)
i have a django website that runs a chatbot app to simulate a customer service by getting the question and retrieving the best match reply in the DB using queries.
view.py:
#csrf_exempt
def home(request):
context= locals()
template= 'home.html'
return render(request,template,context)
#csrf_exempt
def male_chatbot(request):
if not request.session.session_key:
request.session.create()
context= locals()
template= 'male_chatbot.html'
return render(request,template,context)
#csrf_exempt
def run_python_male(request):
if request.method == "POST":
session_key = request.session.session_key
param11 = request.POST.get('param1')
msg = chatbot.run_conversation_male(param11)
return JsonResponse({ 'msg': msg})
chatbot.py:
raw_chatting_log =[]
chatting_log =[]
def chatting_log_data(raw_Input,Input,check):
if check== "check":
if raw_Input in raw_chatting_log:
return True
else:
return False
else:
if check== "app":
raw_chatting_log.append(raw_Input)
chatting_log.append(Input)
def check_lastB():
new='جديد'
if len(raw_chatting_log) == 0:
return new
else:
return raw_chatting_log[-1]
def delandsave_chat_log():
name= str(uuid.uuid4())
thefile = open('/home/mansard/webapps/gadgetron/src/chatting_logs/'+name+'.txt', 'w')
for item in chatting_log:
thefile.write("%s\n" % item)
thefile.close()
raw_chatting_log.clear()
chatting_log.clear()
def run_conversation_male(user_in):
last_B = check_lastB()
H = user_in
NN1= "H:"+str(user_in)
New_H= ' '.join(PreProcess_text(H))
if last_B== 'تقييمك للمحادثة و الخدمة؟':
#do_somthing
else:
if chatting_log_data(H,NN1,"check") == True:
#do_somthing
else:
#find_replay
So, the idea is saving the input/output conversation in two list :
raw_chatting_log ==> hold the data with out the addition 'H:' or 'B:' just a the input and output.to help the chatbot remembering the asked questions and using it in chatting_log_data(H,NN1,"check").
chatting_log=> will hold the the conversation to the chat log in form of 'H:' and 'B:' to save the whole list when the user ends the conversation or close the page in def delandsave_chat_log()
and for last_B helps me know what is the chatbot's last responce
So far it is working for one user, now what i'm thinking is switching to make it handle or chat with many users at the same time where each user has it own chatbot.run_conversation_male and each chat/conversation is separate each with it own chatting log list so that i can use it for checking and saving the data.
class Member(models.Model):# member db table
userID = models.CharField(max_length=80,primary_key=True) #user id
password = models.CharField(max_length=32)# password
nickname = models.CharField(max_length=100)# user nickname
penalty = models.PositiveSmallIntegerField(max_length=10,default=0,null=True)
participation=models.ForeignKey('Room',default=None,blank=True,null=True)
def __unicode__(self):
return self.userID
def doJoin(request):
if request.is_ajax() and request.method == 'POST':
# check validation
userID = request.POST['userID']
userNickname = request.POST['nickname']
if (checkID(userID) == False) and (checkNickname(userNickname) == False) :
#save to the database
newUser = Member()
newUser.userID = userID
newUser.nickname = userNickname
newUser.password = request.POST['password']
print newUser.userID , newUser.nickname , newUser.password , newUser.penalty , newUser.participation
newUser.save() #<------------error line!!!!
return HttpResponse('true')
else:
return HttpResponse('false')
else:
HttpResponse('false')
line about 8
In function doJoin:
newUser.save() # <--- error... so sad...
What should I do? Help me please.
What's wrong in this source?
Do you have debugging turned off? If you're getting a 500 and you have debugging turned on, you'll get a stack trace with the exception.
What are checkID() and checkNickname() doing? If those are performing some sort of validation, you really should be doing that in a form class instead of in the view. I also wouldn't be pulling values directly out of the request.POST to populate your model. I would highly recommend retrieving those values from a form's cleaned_data dictionary.
I just simple want to pass the emailadress from def send_username to the second def username_is_send. How do I do it? How can I pass the variable to the next def?
#csrf_protect
def send_username(request, template_name='auth/user/registration/send_username_form.html',
email_template_name='auth/user/registration/send_username_email.html',
send_username_form=SendUsernameForm, post_reset_redirect=None):
if post_reset_redirect is None:
post_reset_redirect = reverse('auth.user.registration.views.username_is_send')
if request.method == "POST":
form = send_username_form(request.POST)
if form.is_valid():
opts = {}
opts['use_https'] = request.is_secure()
opts['email_template_name'] = email_template_name
opts['request'] = request
form.send_mail_now(**opts)
return HttpResponseRedirect(post_reset_redirect)
else:
form = send_username_form()
return render_to_response(template_name, {
'form': form,},
context_instance=RequestContext(request))
def username_is_send(request, template_name='tmp/username.html'):
return render_to_response(template_name, context_instance=RequestContext(request))
Thanks!
Craphunter
You need to store the state somehow in order to pass parameters through a redirect. Multiple possibilities:
Store the mail address in the session, then read in the session variable again in the username_is_send view.
Use a GET parameter to pass the mail address.
And it's "pass", not "path". And the "def" is called (view) function.