Checking previous SMS senders Django/Twilio - python

I'm trying to keep track of the answers from users who sends a "password" into the Twilio app so they can answer a series of questions. First, it'll probably be best to check that "from_number" exists in the database, then create a new Caller if it isn't.
In models.py:
class Callers(models.Model):
body = models.CharField()
from_number = models.CharField()
last_question = models.CharField(max_length=1, default="0")
In views.py:
def HelloThere(request):
body = request.REQUEST.get('Body', None)
from_number = request.REQUEST.get("From",None)
if Caller.objects.filter(from_number == from_number):
if last_question == "0":
caller = Caller(message = "first question". last_question = "1")
caller.save()
return HttpResponse(str(resp))
if last_question == '1':
# so on and so forth
else:
caller = Caller(body=body, from_number=from_number, last_question='0')
caller.save()
message = "What is the password?"
I don't think I can use request.user.is_authenticated().
/Is it a bad idea to have so many of the same field names? "body=body=Body?

First about the model:
class Callers(models.Model):
body = models.CharField()
from_number = models.CharField()
last_question = models.IntegerField(default=0) # if you have more than 10 question then I guess using IntegerField is better here
Then the view:
def hello_there(request): # this is a function, so use lower case with underscore for name
body = request.REQUEST.get('Body', None)
from_number = request.REQUEST.get("From",None)
try:
caller = Caller.objects.get(from_number=from_number) # using get() is better than filter here since I guess you want unique caller field in DB, right?
except Caller.DoesNotExist:
caller = None
if caller:
if caller.last_question == 0:
# update the caller ?
caller.last_question = 1
caller.body = 'Something'
caller.save()
# ... your code ...
return HttpResponse(str(resp))
if last_question == 1:
# so on and so forth
# if you have repeated process here, make a function to update caller to be DRY
else:
new_caller = Caller(body=body, from_number=from_number, last_question=0)
new_caller.save()
message = "What is the password?"
request.user.is_authenticated() is only for User model so you can't use it. And it's okay to use same name for different things, for example body in your view can be variable or argument. If it isn't clear for you then you can pick different name then.
Hope it helps!

Related

Rest API schema to retrieve value from database and return

I need to make a Rest API which will take 3 inputs: input_list (list of srings sentences), from_lang (string), to_lang (string) and return list of string after fetching values from databse table.
Example:
input - {input_list: ['how are you', 'see you later', 'where are you'], from_lang: 'english', to_lang: 'spanish' }
output - {['cómo estás', 'nos vemos más tarde', 'Dónde estás']}
A service will call this API with list of sentences in any supported language, and in return they will get list of same length with translated sentence if it exist in database or null value if it doesn't exist.
How should I proceed?
What I have done is, I have created a serializer to handle/validate incoming request in serializers.py:
def supported_lang(value):
if value not in SUPPORTED_LANGUAGES:
print(value)
print(SUPPORTED_LANGUAGES)
raise serializers.ValidationError('Language not supported')
class TranslateSerializer(serializers.Serializer):
input_list = serializers.ListField(
child=serializers.CharField(allow_blank=False),
allow_empty=False
)
from_language = serializers.CharField(validators=[supported_lang])
to_language = serializers.CharField(validators=[supported_lang])
And I have defined a simple model for storing translations in model.py:
class TranslationModel(models.Model):
english = models.CharField(blank=False, max_length=MAX_LENGTH, unique=True)
spanish = models.CharField(blank=True, max_length=MAX_LENGTH)
italian = models.CharField(blank=True, max_length=MAX_LENGTH)
is_active = models.BooleanField(default=True)
Then in my views.py I have handled post requests like below
class TranslateView(views.APIView):
def post(self, request):
serializer = TranslateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serialized_data = serializer.validated_data
result = self.get_translations(serialized_data) # here i am confused
return Response(result)
So far so good, now I am confused how to fetch the data from model, and how to return it (following best practices).
I have defined a function get_translations() in views.py :
def get_translations(self, request):
output_list = [] # for return response
for sentence in request['input_list']:
if request['from_language'] == 'english':
queryset = TranslationModel.objects.filter(english=sentence)
elif request['from_language'] == 'spanish':
queryset = TranslationModel.objects.filter(hindi=sentence)
elif request['from_language'] == 'italian':
queryset = TranslationModel.objects.filter(telugu=sentence)
try:
resp = queryset.values()[0][request['to_language']]
except:
resp = ""
if not resp:
# print('empty response')
output_list.append(None)
else:
output_list.append(resp)
return output_list
I mainly have three confusions:
Is it good practice to use serializers.Serializer for handling/validating incoming requests
Should I use serializers for model as well, if yes how
How to pass filter value dynamically
Any help is appreciated.
Is it good practice to use serializers.Serializer for handling/validating incoming requests
Of course, It is. That's essentially one of the core concepts of seriaizers (Parsing, Validation and serialization)
Should I use serializers for model as well, if yes how
There is no need for that. You only need a serializer if data is being sent or received from the user which is not the case here.
How to pass filter value dynamically
Use dictionary unpacking
k = {request['from_language']: sentence}
queryset = TranslationModel.objects.filter(**k)

function inside the python class is not called while running the server

i am trying to validate unique user name in the registration form. while i click the submit button after entering the details in the register form, instead of raising a validation error with the given message, it fails and errors out Validationerror at /register/. i am also trying to print the string inside the function. but it doesnt print that too. is it actually calling the clean function. i am using self to achieve this. it should be called !. am i misiing something?
class Register_Form(forms.Form):
user_id = forms.CharField(label="User Name",widget = forms.TextInput(
attrs = {"class":"form-control"}
))
email_id = forms.CharField(label = "Email",widget = forms.EmailInput(
attrs = {"class":"form-control"}
))
password = forms.CharField(label = "Password",widget = forms.PasswordInput(
attrs = {"class":"form-control"}
))
confirm_pass = forms.CharField(label = "Confirm Password",widget = forms.PasswordInput(
attrs = {"class":"form-control"}
))
def clean_username(self):
user_id = self.cleaned_data["user_id"]
print("Entered")
ue = User.objects.filter(username=user_id)
if ue.exists():
raise forms.ValidationError("User name not available")
return user_id
It's not being called, the fact you pass self doesn't mean it'll automatically run, you are just extending your function with self so that it can inherit it's attributes.
Somewhere inside your class you'll have to run self.clean_username(), alternatively if you construct the class, e.g. RF = Register_Form() you'll have to call RF.clean_username()

Django Form some field always get None in clean_field() or clean()

It's always get None in clean() or clean_field(), but it's in self.data.
django 2.x
The fields declaration is:
phone = forms.CharField(
label='',
min_length=phone_number_min,
max_length=phone_number_max,
)
code_length = settings.SMS_CODE_LENGTH
code = forms.CharField(
label='',
min_length=code_length,
max_length=code_length,
)
def clean_code(self):
code = self.cleaned_data.get('code')
phone = self.cleaned_data.get('phone')
result, message = sms_validator.validate(phone, code)
def clean(self):
code = self.cleaned_data.get('code')
phone = self.cleaned_data.get('phone')
result, message = sms_validator.validate(phone, code)
Both of above all run in error:
phone = None
But if
phone = self.data.get('phone')
It's can get the value.
I want to get the phone value in clean_data
Firstly, you must always return the cleaned value from a field clean method. Secondly, it is not safe to access other field values in a field clean method; that is what the overall clean() method is for.

Finding objects without relationship in django

I am learning Django, and want to retrieve all objects that DON'T have a relationship to the current object I am looking at.
The idea is a simple Twitter copycat.
I am trying to figure out how to implement get_non_followers.
from django.db import models
RELATIONSHIP_FOLLOWING = 1
RELATIONSHIP_BLOCKED = 2
RELATIONSHIP_STATUSES = (
(RELATIONSHIP_FOLLOWING, 'Following'),
(RELATIONSHIP_BLOCKED, 'Blocked'),
)
class UserProfile(models.Model):
name = models.CharField(max_length=200)
website = models.CharField(max_length=200)
email = models.EmailField()
relationships = models.ManyToManyField('self', through='Relationship',
symmetrical=False,
related_name='related_to')
def __unicode__ (self):
return self.name
def add_relationship(self, person, status):
relationship, created = Relationship.objects.get_or_create(
from_person=self,
to_person=person,
status=status)
return relationship
def remove_relationship(self, person, status):
Relationship.objects.filter(
from_person=self,
to_person=person,
status=status).delete()
return
def get_relationships(self, status):
return self.relationships.filter(
to_people__status=status,
to_people__from_person=self)
def get_related_to(self, status):
return self.related_to.filter(
from_people__status=status,
from_people__to_person=self)
def get_following(self):
return self.get_relationships(RELATIONSHIP_FOLLOWING)
def get_followers(self):
return self.get_related_to(RELATIONSHIP_FOLLOWING)
def get_non_followers(self):
# How to do this?
return
class Relationship(models.Model):
from_person = models.ForeignKey(UserProfile, related_name='from_people')
to_person = models.ForeignKey(UserProfile, related_name='to_people')
status = models.IntegerField(choices=RELATIONSHIP_STATUSES)
This isn't particularly glamorous, but it gives correct results (just tested):
def get_non_followers(self):
UserProfile.objects.exclude(to_people=self,
to_people__status=RELATIONSHIP_FOLLOWING).exclude(id=self.id)
In short, use exclude() to filter out all UserProfiles following the current user, which will leave the user themselves (who probably shouldn't be included) and all users not following them.
i'v been searching for a method or some way to do that for like an hour, but i found nothing.
but there is a way to do that.
you can simply use a for loop to iterate through all objects and just remove all objects that they have a special attribute value.
there is a sample code here:
all_objects = className.objects.all()
for obj in all_objects:
if obj.some_attribute == "some_value":
all_objects.remove(obj)
Solution to the implementation of get_non_followers:
def get_non_following(self):
return UserProfile.objects.exclude(to_person__from_person=self, to_person__status=RELATIONSHIP_FOLLOWING).exclude(id=self.id)
This answer was posted as an edit to the question Finding objects without relationship in django by the OP Avi Meir under CC BY-SA 3.0.
current_userprofile = current_user.get_profile()
rest_of_users = Set(UserProfile.objects.filter(user != current_userprofile))
follow_relationships = current_userprofile.relationships.filter(from_person=current_user)
followers = Set();
for follow in follow_relationships:
followers.add(follow.to_person)
non_followeres = rest_of_users.difference(followers)
Here non_followers is the list of userprofiles you desire. current_user is the user whose non_followers you are trying to find.
I haven't tested this out, but it think it should do what you want.
def get_non_followers(self):
return self.related_to.exclude(
from_people__to_person=self)

VoteHandler in Google App Engine

I am trying to have this function limit a user to only one vote per image. However it currently lets all votes through. If I change "if existing_vote != 0:" to "if existing_vote == 0:" it lets no votes through. Thoughts?
class VoteHandler(webapp.RequestHandler):
def get(self):
#See if logged in
self.Session = Session()
if not 'userkey' in self.Session:
doRender(
self,
'base/index.html',
{'error' : 'Please login to vote'})
return
#If user hasn't voted - if user doesn't have a vote on that image object
key = self.request.get('photo_id')
vurl = models.Image.get_by_id(int(key))
#pull current site vote total & add 1
existing_vote = models.Vote.all().filter('user=', self.Session['userkey']).filter('photo=',vurl).count()
if existing_vote != 0:
self.redirect('/', { })
else:
newvote = models.Vote(user=self.Session['userkey'], url=vurl)
vurl.votes += 1
vurl.put()
logging.info('Adding a vote')
#Create a new Vote object
newvote = models.Vote(user=self.Session['userkey'], url=vurl)
newvote.put()
self.redirect('/', { })
For the Models:
class User(db.Model):
account = db.StringProperty()
password = db.StringProperty()
name = db.StringProperty()
created = db.DateTimeProperty(auto_now=True)
class Image(db.Model):
user = db.ReferenceProperty(User)
photo_key = db.BlobProperty()
website = db.StringProperty()
text = db.StringProperty()
created = db.DateTimeProperty(auto_now=True)
votes = db.IntegerProperty(default=1)
class Vote(db.Model):
user = db.ReferenceProperty(User) #See if voted on this site yet
photo = db.ReferenceProperty(Image) #To apply vote to right URL
upvote = db.IntegerProperty(default=1)
created = db.DateTimeProperty(auto_now=True)
Looks like your filter on user is wiping out every existing vote, i.e., the equality there is never satisfied. And indeed I'm not sure how I'd satistfy an equality check on a reference propertly. Why not change
user = db.ReferenceProperty(User) #See if voted on this site yet
to, e.g.,
useraccount = db.StringProperty() # account of user who cast this vote
Then the comparison becomes a simple equality check between strings and is sure to work without any complication -- simplicity is generally preferable, when feasible.
On this line here:
existing_vote = models.Vote.all().filter('user=', self.Session['userkey']).filter('photo=',vurl).count()
You need to put a space between the 'photo' and the '=' in the filters - otherwise, it's attempting to filter for a property called 'photo='. This should work:
existing_vote = models.Vote.all().filter('user =', self.Session['userkey']).filter('photo =',vurl).count()

Categories

Resources