Series of Questions without database with Django/Twilio - python

I want to create a series of questions for anyone to answer. I could create a User for everyone who texts in and have a field for "completed_questions" but I was wondering if this could be done without a database. For example:
def HelloQuiz(request):
body = request.REQUEST.get('Body', None)
if body == 'Quiz me up':
message = "2 + 3?"
if body == '6':
message = "Congrats! Next question: what color is green?"
if body == 'Green':
message == "You beat the quiz!"
resp = twilio.twiml.Response()
resp.sms(message)
return HttpResponse(str(resp))
But here, if they text green as their first response, they automatically beat the quiz. I can't really think of any way to achieve this because it requires a look into a past completed action.
Thanks!

Using sqlite3 is the way to go. It's way better than writing to a text file.
What I have in mind is you can use the standard User model to create user, maybe use the phone number as username, something like:
from_number = request.REQUEST.get('From', None)
user = User.objects.get_or_create(username=from_number, ...)
# ... your code ...
Then you only need to define one model for the quiz and probably a relationship model:
class Quiz(models.Model):
message = models.CharField(max_length=100)
order = models.IntegerField()
response = models.CharField(max_length=100)
# ... fields you need ...
def __unicode__():
return self.message
class QuizUser(models.Model):
quiz = models.ForeignKey('Quiz')
user = models.ForeignKey('User')
So whenever there is a message coming in you can use some simple queryset to lookup for the right user and quiz like:
from_number = request.REQUEST.get('From', None)
body = request.REQUEST.get('Body', None)
user = User.objects.get(username=from_number)
quiz = Quiz.objects.get(message=body)
user_quiz = QuizUser.objects.get(user=user, quiz=quiz)
# ... your code ...
This is just my basic opinion.
You can of course go for you original plan, use custom user model and add completed_quiz field and have the list of quiz as a static list.
Have fun coding!

Related

Django if elif else statement

I'm trying to print the result according to the user's age selection in the form, but my if,elif and else statements are not working.
class Quiz(models.Model):
age_choices = (('10-12', '10-12'),
('13-16', '13-16'),
('17-20', '17-20'),
('21-23','21-23'),
)
age = models.CharField(max_length = 100, choices = age_choices)
views.py
def create_order(request):
form = QuizForm(request.POST or None)
if request.method == 'POST':
quiz = Quiz.objects
if quiz.age=='10-12':
print("10-12")
elif quiz.age=='13-16':
print("13-16")
elif quiz.age=='17-20':
print("17-20")
elif quiz.age=='21-23':
print("21-23")
else:
return None
context = {'form':form}
return render(request, "manualupload.html", context)
quiz = Quiz.objects will return a django.db.models.manager.Manager object and this can be further used to fetch the objects from database belonging to that particular model. The appropriate query set will be quiz = Quiz.objects.all() Then you will get the list of all objects in that belong to Quiz model. Once you get list of all objects, you can get the specific object either by indexing or by filtering using a specific query that you need to look into and then for that particular object you can get the age property.
Refer to official django documentation about creating queries for more information.
As #Abhijeetk431 mentioned, your issue lies in quiz = Quiz.objects.
If you use type(quiz), you will find that it outputs django.db.models.manager.Manager. This is not what you want, as age is a property of the Quiz class, not the Manager class.
For starters, refer to this.
This will return you a Queryset list, something akin to an Excel table. age is akin to the column in the table. To get age, what you want is the row (the actual Quiz object) in said table, which you can achieve using get or using the square brackets [].
Thus, your code should look something like this:
Model.objects.all()[0]
That would return the correct object(only the first row) and allow you to get the column value.
However, further clarification will be needed though, to know exactly what your problem is aside from 'it doesn't work'. How did you know your code is not working; what did the debugger tell you?

how do i write a filter to get all the fields of the user 'tim' 's only

i only want all the questions, rank, and choice of the user tim
x = AnswerModel.objects.all(user=tim)?
class AnswerModel(models.Model):
user = models.ForeignKey(UserModel)
question = models.ForeignKey(QuestionModel)
rank = models.IntegerField(default=1)
choice = models.CharField(max_length=4, choices=CHOICE)
You have many option for this:
x = AnswerModel.objects.filter(user__username__exact='tim')
OR
x = AnswerModel.objects.filter(user=
UserModel.objects.get(username__exact='tim'))
Or you can do get as well which will throw exception if it gets multiple results or couldnot find the object.
See Queryset API

Django request not available in form clean

I can't access request from the clean field of a ModelForm. I want to check that the request user is not trying to attend too many events.
I've tried this fix: Django: Accessing request in forms.py clean function
...among other things but am still struggling.
My form is this:
class EventEditForm(forms.ModelForm):
class Meta:
model = Event
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(EventEditForm, self).__init__(*args, **kwargs)
name = forms.CharField(max_length=1024,
initial="Give short, descriptive name",
widget=forms.TextInput(attrs={'onfocus':'if(this.value=="Give short, descriptive name") this.value="";'}))
location = forms.CharField(max_length=1024,
initial="Be specific, give online map link",
widget=forms.TextInput(attrs={'onfocus':'if(this.value=="Be specific, give online map link") this.value="";'}))
dateTimeOptions = {
'format': 'dd/mm/yyyy HH:ii P',
'autoclose': 'true',
'showMeridian': 'true',
}
date = forms.DateTimeField(label="Date and time",widget=DateTimeWidget(options=dateTimeOptions,
attrs={'id':"date-time"}))
host_act = forms.CharField(max_length=1024,
initial="What act will you bring, if any?", required=False,
widget=forms.TextInput(attrs={'onfocus':'if(this.value=="What act will you bring, if any?") this.value="";'}))
description = forms.CharField(required=False, max_length=10240,
initial="Give some details. Any activities prepared?",
widget=forms.Textarea(attrs={'onfocus':'if(this.value=="Give some details. Any activities prepared?") this.value="";'}))
def clean_location(self):
cd = self.cleaned_data
location = cd.get('location')
if location == "Be specific, give online map link" or '':
raise forms.ValidationError("Please enter a location")
return location
def clean_name(self):
cd = self.cleaned_data
name = cd.get('name')
other_names = Event.objects.proposed(datetime.now)
if name == "Give short, descriptive name" or '':
raise forms.ValidationError("Please enter a name")
return name
def clean(self):
"""
Check that there is not another event on at
the same time and place. Then check that user has not committed
to another event on the same date, even somewhere else.
"""
cleaned_data = super(EventEditForm, self).clean()
event_start_estimate = cleaned_data.get("date") - timedelta(hours=3)
event_end_estimate = event_start_estimate + timedelta(hours=7)
location = cleaned_data.get("location")
events_on_date = Event.objects.\
filter(date__range=[event_start_estimate,event_end_estimate])
events_at_location_on_date = events_on_date.filter(location=location)
print events_at_location_on_date
# Check event clash is not this event clashing with itself
try:
events_with_same_date_and_location_id = events_at_location_on_date[0].id
except:
pass
this_event_id = self.instance.id
try:
if events_with_same_date_and_location_id == this_event_id:
events_at_location_on_date = False
except:
pass
if events_at_location_on_date:
raise forms.ValidationError("There is already an event on \
this date. Please join this event or pick another \
date and time. Note: You may have accidentally failed to \
change the date with the picker.")
print self.request
user = self.request
print user
events_on_date_user_has_commit = events_on_date.filter(host__exact=user)
if events_on_date_user_has_commit:
raise forms.ValidationError("You are already committed to an event\
on this date.")
return cleaned_data
My view is:
class EventEditView(UpdateView):
template_name = "edit_event.html"
model=Event
pk_url_kwarg='event_id'
form_class = EventEditForm
You cannot access the request in a form. You need to pass it in from the view in some way. If you're using a FormView generic view, the answer you have linked to is a great way to do it. Looks like you are already expecting the request to be sent in:
self.request = kwargs.pop('request', None)
If you are using a function based view, or a non FormView classed based view, just pass in the request as a keyword argument when you initialize the form. For example:
form = EventEditForm(request.POST, request=request) # or self.request for a class based view

why is my Python GAE code asynchronous?

This is the code:
def create_game(user_id):
game = classes.Games(user_id = user_id)
game.put()
def get_game(user_id):
game_query = classes.Games.gql('WHERE user_id = :1', user_id)
game = False
for item in game_query:
game = item
if not game:
create_game(user_id)
get_game(user_id)
else:
return game
def render_page(self):
message = 'this is a game page<br>'.decode('utf-8')
user = creditentials.get_user(self)
if not user:
self.redirect('/')
return
game = get_game(user.key().id())
message += 'current game ID: '.decode('utf-8') + str(game.key().id())
self.response.write(message)
I expect it to create just one instance of the game, instad it creates 10! Appearantly GQL query is perfromed asynchronously, and starting from the 3rd (?) instance of the get_game(user_id) it just skips game_query = classes.Games.gql('WHERE user_id = :1', user_id) line.
Am I right? How do I avoid this?
Queries aren't immediately consistent, so an entity that you've only just created won't be returned in a query performed right-away, you need to wait a bit.
In your case, you don't need to query for the entity - you just created it, so you know it exists, and can use it. Change your create_game function to return the new game, and then use that.
If you expect your user_id to be unique (and given your query, this seems to be the case) you could use it as the entity-id, then you can get-by-id instead of querying, which will strongly-consistent.
Check the "Data Consistency" section on this docs page for more detail on how queries work.

Django - How to make a form for a model's foreign keys?

Here's what I'm trying to do. I'm wondering if someone can suggest a good approach:
models.py:
class Color(models.Model):
name = models.CharField(...
class Speed(models.Model):
name = models.CharField(...
class Dog(models.Model):
name = models.CharField(...
color = models.ForeignKey(Color...
speed = models.ForeignKey(Speed...
class DogRequest(models.Model):
dog = models.ForeignKey(Dog...
request_time = models.DateTimeField()
Now I want to have a page where a user can enter or edit a DogRequest, but the form should look like this:
Enter Dog Request:
---------------------
color (dropdown V)
speed (dropdown V)
|save|
So how would I design that form in the view? The problem is the user will be entering properties of a dog, but not a dog. So I need to find or create a dog record depending on what the user enters.
So far I've tried something like this:
class DogRequestForm(ModelForm):
class Meta:
model = DogRequest
fields = ('request_time','color','speed')
color = forms.ModelChoiceField(queryset=Color.objects.all())
speed = forms.ModelChoiceField(queryset=Speed.objects.all())
Now assuming that even works, where do I put the code to figure out the Dog record to use (or create) depending on what's entered for color and speed? And how do I fill the form from a DogRequest?
I don't think you want to use a ModelForm here. It will never be valid without some hackery, since you won't have found or created the dog object before calling is_valid().
Instead, I'd just use a regular form, and then override the save method of DogRequest to find or create the dog.
Update: Responding to the followup question in the comment, I haven't tested this, but something like it should work.
class DogRequestForm(forms.Form):
id = forms.IntegerField(required=False, widget=forms.HiddenInput())
color = forms.ModelChoiceField(queryset=Color.objects.all())
speed = forms.ModelChoiceField(queryset=Speed.objects.all())
and then when you create an instance of this form for your edit view you need to instantiate it with something like this:
data = {
'id': dog_request_id,
'color': dog_color,
'speed': dog_speed,
}
form = DogRequestForm(data)
where you populate the current dog_request_id, dog_color and dog_speed from your existing DogRequest object.

Categories