Geography quiz python - python-2.7

I have an issue with my code. I'm fairly new to python and I'm trying new things. I want to create a geography quiz that will randomly ("but not repeatedly") select country that I have to guess its capital. Currently for every answer I get a message that my answer is wrong. The question is how exactly should I do things so that when I loop through the dictionary for a country, I will have to guess the correct key of that country.
Here is the code:
#!/usr/bin/env python
import os
import jinja2
import webapp2
import random
template_dir = os.path.join(os.path.dirname(__file__), "templates")
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(template_dir), autoescape=False)
class BaseHandler(webapp2.RequestHandler):
def write(self, *a, **kw):
return self.response.out.write(*a, **kw)
def render_str(self, template, **params):
t = jinja_env.get_template(template)
return t.render(params)
def render(self, template, **kw):
return self.write(self.render_str(template, **kw))
def render_template(self, view_filename, params=None):
if not params:
params = {}
template = jinja_env.get_template(view_filename)
return self.response.out.write(template.render(params))
class MainHandler(BaseHandler):
def get(self):
return self.render_template("geokviz.html")
class AboutHandler(BaseHandler):
def get(self):
return self.render_template("geokviz1.html")
class flagHandler(BaseHandler):
def get(self):
return self.render_template("flag.html")
class attractionHandler(BaseHandler):
def get(self):
return self.render_template("attraction.html")
class Capital:
def __init__(self, capital, country):
self.capital = capital
self.country = country
city = {"Zagreb":"Croatia", "Ljubljana":"Slovenia", "Rome":"Italy", "Oslo":"Norway"}
class capitalCityHandler(BaseHandler):
def get(self):
for cities in random.sample(list(city), 1):
capital = city[cities]
params={"capital": capital}
return self.render_template("capital.html", params=params)
def post(self):
odgovor = self.request.get("answer")
if odgovor == city.keys():
result1 = "You are right"
else:
result1 = "You are wrong"
self.write(result1)
app = webapp2.WSGIApplication([
webapp2.Route('/', MainHandler),
webapp2.Route('/geo', AboutHandler),
webapp2.Route('/city', capitalCityHandler),
webapp2.Route('/flag', flagHandler),
webapp2.Route('/attraction', attractionHandler),
], debug=True)
Thanks for all the help

First, you need to check if the capital exists as a key, then you may check if it matches the country.
if odgovor in city.keys() and city[odgovor] == country:

Related

Django form class and view class connected

Hi in my code(not written by me) i have django form class and views class. I dont know how this is connected each other. Can anyone tell me how this is connected? Also can any one please tell me how this messege : Credential is in use by {0} collections that are turned on and "
"{1} collections that are turned off. Be mindful that over-using " "credentials may result in collecting being rate limited by the " "social media API is displayed, i mean if i need to change the alignment of this text where i should change?
My code classes are :
from forms.py :
class CollectionTwitterSearch2Form(BaseCollectionForm):
incremental = forms.BooleanField(initial=True, required=False, label=INCREMENTAL_LABEL, help_text=INCREMENTAL_HELP)
def __init__(self, *args, **kwargs):
super(CollectionTwitterSearch2Form, self).__init__(*args, **kwargs)
self.helper.layout[0][5].extend(('incremental',))
if self.instance and self.instance.harvest_options:
harvest_options = json.loads(self.instance.harvest_options)
if "incremental" in harvest_options:
self.fields['incremental'].initial = harvest_options["incremental"]
def save(self, commit=True):
m = super(CollectionTwitterSearch2Form, self).save(commit=False)
m.harvest_type = Collection.TWITTER_SEARCH_2
harvest_options = {
"incremental": self.cleaned_data["incremental"],
}
m.harvest_options = json.dumps(harvest_options, sort_keys=True)
m.save()
return m
from views.py :
def _get_credential_use_map(credentials, harvest_type):
credential_use_map = {}
if harvest_type in Collection.RATE_LIMITED_HARVEST_TYPES:
for credential in credentials:
active_collections = 0
inactive_collections = 0
for collection in credential.collections.all():
if collection.is_on:
active_collections += 1
else:
inactive_collections += 1
if active_collections == 0 and inactive_collections == 0:
credential_use_map[credential.id] = ("", "")
else:
credential_use_map[credential.id] = ("warning",
"Credential is in use by {0} collections that are turned on and "
"{1} collections that are turned off. Be mindful that over-using "
"credentials may result in collecting being rate limited by the "
"social media API.".format(active_collections,
inactive_collections))
return credential_use_map
class CollectionCreateView(LoginRequiredMixin, CollectionSetOrSuperuserPermissionMixin, SuccessMessageMixin,
CreateView):
model = Collection
template_name = 'ui/collection_create.html'
def get_initial(self):
initial = super(CollectionCreateView, self).get_initial()
initial["collection_set"] = CollectionSet.objects.get(pk=self.kwargs["collection_set_pk"])
return initial
def get_context_data(self, **kwargs):
context = super(CollectionCreateView, self).get_context_data(**kwargs)
context["collection_set"] = CollectionSet.objects.get(pk=self.kwargs["collection_set_pk"])
harvest_type = self.kwargs["harvest_type"]
context["harvest_type_name"] = _get_harvest_type_name(harvest_type)
credentials = _get_credential_list(self.kwargs["collection_set_pk"], harvest_type)
context["credentials"] = credentials
context["credential_use_map"] = _get_credential_use_map(credentials, harvest_type)
context["platform"] = Collection.HARVEST_TYPES_TO_PLATFORM[self.kwargs["harvest_type"]]
return context
def get_form_kwargs(self):
kwargs = super(CollectionCreateView, self).get_form_kwargs()
kwargs["coll"] = self.kwargs["collection_set_pk"]
kwargs['credential_list'] = _get_credential_list(self.kwargs["collection_set_pk"], self.kwargs["harvest_type"])
return kwargs
def get_form_class(self):
return getattr(forms, _get_collection_form_class(self.kwargs["harvest_type"]))
def get_success_url(self):
return reverse('collection_detail', args=(self.object.pk,))
def get_success_message(self, cleaned_data):
if self.object.required_seed_count() != 0:
return "New collection added. You can now add seeds."
return "New collection added."
Full code is here in this git : https://github.com/gwu-libraries/sfm-ui/tree/master/sfm/ui
It would be great anyone can explain how these two classes and template is connected and how the messege is displayed
The CollectionCreateView class is conected to the Form using the function get_form_class, this function is called by default by the CreateView, in there you can see is calling _get_collection_form_class() and as an argument is passing self.kwargs['harvest_type'] this kwargs is comming from the url declaration. The _get_collection_form_class function is returning the CollectionTwitterSearch2Form when the harvest_type is something like TwitterSearch2. The template is given by the template_name = 'ui/collection_create.html' again this is the default vehaviour. And finally for the message this is using SuccessMessageMixin.

Overriding render of RadioSelect in django forms gives unexpected results

I want to override the render for RadioSelect in django. (I have done a similar thing for checkboxes and I want both to look the same). The general workflow for this would be to write a custom renderer, and then change the render in the ChoiceInput, BUT when I copy the existing code and run it the html output is not safe and the escaped html string is shown. This is not making any sense as I didn't do any changes to the class yet, other than change the name:
In my widgets.py:
class ButtonRadioFieldRenderer(ChoiceFieldRenderer):
choice_input_class = OtherRadioChoiceInput
class OtherRadioChoiceInput(OtherChoiceInput):
input_type = 'radio'
def __init__(self, *args, **kwargs):
super(OtherRadioChoiceInput, self).__init__(*args, **kwargs)
self.value = force_text(self.value)
#html_safe
#python_2_unicode_compatible
class OtherChoiceInput(SubWidget):
"""
An object used by ChoiceFieldRenderer that represents a single
<input type='$input_type'>.
"""
input_type = None # Subclasses must define this
def __init__(self, name, value, attrs, choice, index):
self.name = name
self.value = value
self.attrs = attrs
self.choice_value = force_text(choice[0])
self.choice_label = force_text(choice[1])
self.index = index
if 'id' in self.attrs:
self.attrs['id'] += "_%d" % self.index
def __str__(self):
return self.render()
def render(self, name=None, value=None, attrs=None, choices=()):
if self.id_for_label:
label_for = format_html(' for="{}"', self.id_for_label)
else:
label_for = ''
attrs = dict(self.attrs, **attrs) if attrs else self.attrs
return format_html(
'<label{}>{} {}</label>', label_for, self.tag(attrs), self.choice_label
)
def is_checked(self):
return self.value == self.choice_value
def tag(self, attrs=None):
attrs = attrs or self.attrs
final_attrs = dict(attrs, type=self.input_type, name=self.name, value=self.choice_value)
if self.is_checked():
final_attrs['checked'] = 'checked'
return format_html('<input{} />', flatatt(final_attrs))
#property
def id_for_label(self):
return self.attrs.get('id', '')
In my forms.py:
DELIMITER_CHOICES = [
('space', ugettext_lazy("space")),
('underscore', "_"),
]
class SingleDelimiterForm(forms.Form):
delimiter = forms.ChoiceField(initial=0, widget=forms.RadioSelect(renderer=ButtonRadioFieldRenderer), choices=DELIMITER_CHOICES)
The only changes I did was to put "Other" and "Button" in front of already existing classes, and the code doesn't run anymore. If I change OtherChoiceInput to ChoiceInput the code is working. (in the end I only want to add a class to the label...)
I needed unicode strings for the code to work, so from __future__ import unicode_literals fixed the issue. I still found this error very confusing.

How to add list datatype in Django model?

This is how my model.py looks like. The third field (label) should contain more than one value (as a news post can have more than one label) like a list. How to achieve that?
from django.db import
class News(models.Model)
heading=models.CharField(max_length=50)
post_date=models.DateTimeField('Date Posted')
labels=models.???
Django not provide default list field, so that you have to create your own list field from inherit TextField, I am posting one of the example code have a look.
class ListField(models.TextField, metaclass=models.SubfieldBase):
description = "ListField store List of element"
SPLIT_CHAR= ';'
def __init__(self, *args, list_choices=None, **kwargs):
super(ListField, self).__init__(*args, **kwargs)
if list_choices is None:
list_choices = []
self.list_choices = list_choices
def to_python(self, value):
res = []
if value is None:
res = []
if isinstance(value, list):
res = value
if isinstance(value, builtins.str):
res = value.split(self.SPLIT_CHAR)
try:
if "[" in value and "]" in value:
res = eval(value)
except:
pass
return res
def get_prep_value(self, value):
if value is None or value == "":
return None
res = self.SPLIT_CHAR.join(value)
return res
def value_to_string(self, obj):
value = self._get_val_from_obj(obj)
return self.get_prep_value(value)
def formfield(self, **kwargs):
return forms.MultipleChoiceField(choices=self.list_choices)
Then create List field like this one.
from django.db import
class News(models.Model)
heading=models.CharField(max_length=50)
post_date=models.DateTimeField('Date Posted')
labels=ListField()

django custom model field in admin form gives invalid choice error

I have the following class which to be used for a custom model field:
class PaymentGateway(object):
def fullname(self):
return self.__module__ + "." + self.__class__.__name__
def authorize(self):
raise NotImplemented()
def pay(self):
raise NotImplemented()
def __unicode__(self):
return self.fullname()
class DPS(PaymentGateway):
def authorize(self):
pass
def pay(self):
pass
This is how I am writing the custom model field:
from django.db import models
from django.utils.six import with_metaclass
from django.utils.module_loading import import_by_path
class PaymentGatewayField(with_metaclass(models.SubfieldBase, models.CharField)):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 255
super(PaymentGatewayField, self).__init__(*args, **kwargs)
def to_python(self, value):
if value and isinstance(value, basestring):
kls = import_by_path(value)
return kls()
return value
def get_prep_value(self, value):
if value and not isinstance(value, basestring):
return value.fullname()
return value
def value_from_object(self, obj):
return self.get_prep_value(getattr(obj, self.attname))
def formfield(self, **kwargs):
defaults = {'form_class': PaymentGatewayFormField}
defaults.update(kwargs)
return super(PaymentGatewayField, self).formfield(**defaults)
class PaymentGatewayFormField(BaseTemporalField):
def to_python(self, value):
if value in self.empty_values:
return None
if isinstance(value, PaymentGateway):
return value
if value and isinstance(value, basestring):
kls = import_by_path(value)
return kls()
return super(PaymentGatewayFormField, self).to_python(value)
And this is how it is used in a model:
class BillingToken(models.Model):
user = models.ForeignKey('User', related_name='billingtokens')
name = models.CharField(max_length=255)
card_number = models.CharField(max_length=255)
expire_on = models.DateField()
token = models.CharField(max_length=255)
payment_gateway = PaymentGatewayField(choices=[('project.contrib.paymentgateways.dps.DPS', 'DPS')])
I have added the model to admin:
class BillingTokenInline(admin.StackedInline):
model = BillingToken
extra = 0
class UserAdmin(admin.ModelAdmin):
inlines = [BillingTokenInline]
admin.site.register(User, UserAdmin)
So if I go to edit existing user record, which it's billingtoken record has 'DPS' already chosen, and hit save, I get a invalid choice error:
Select a valid choice. project.contrib.paymentgateways.dps.DPS is not one of the available choices.
I have tried to trace the django code and found the error message is defined in django.forms.fields.ChoiceField:
class ChoiceField(Field):
widget = Select
default_error_messages = {
'invalid_choice': _('Select a valid choice. %(value)s is not one of the available choices.'),
}
def __init__(self, choices=(), required=True, widget=None, label=None,
initial=None, help_text='', *args, **kwargs):
super(ChoiceField, self).__init__(required=required, widget=widget, label=label,
initial=initial, help_text=help_text, *args, **kwargs)
self.choices = choices
def __deepcopy__(self, memo):
result = super(ChoiceField, self).__deepcopy__(memo)
result._choices = copy.deepcopy(self._choices, memo)
return result
def _get_choices(self):
return self._choices
def _set_choices(self, value):
# Setting choices also sets the choices on the widget.
# choices can be any iterable, but we call list() on it because
# it will be consumed more than once.
self._choices = self.widget.choices = list(value)
choices = property(_get_choices, _set_choices)
def to_python(self, value):
"Returns a Unicode object."
if value in self.empty_values:
return ''
return smart_text(value)
def validate(self, value):
"""
Validates that the input is in self.choices.
"""
super(ChoiceField, self).validate(value)
if value and not self.valid_value(value):
raise ValidationError(
self.error_messages['invalid_choice'],
code='nvalid_choice',
params={'value': value},
)
def valid_value(self, value):
"Check to see if the provided value is a valid choice"
text_value = force_text(value)
for k, v in self.choices:
if isinstance(v, (list, tuple)):
# This is an optgroup, so look inside the group for options
for k2, v2 in v:
if value == k2 or text_value == force_text(k2):
return True
else:
if value == k or text_value == force_text(k):
return True
return False
But after putting some debug statements before the raise ValidationError line in this function, the exception is not raised here, but the error message is definitely referenced from here. Which hints me that somewhere else is extending ChoiceField might be raising this exception, and I have tried the obvious ones (ChoiceField, TypedChoiceField, MultipleChoiceField, TypedMultipleChoiceField) still no luck. This has already consumed a lot of my time and would like to seek some clever clues.
Finally, figured out where it is throwing the error:
It's in django/db/models/fields/__init__.py line 236
typically because of line 234:
elif value == option_key:
Where value is a PaymentGateway object and option_key is a string
To fix this problem, I had to override the clean method:
def clean(self, value, model_instance):
value = unicode(value)
self.validate(value, model_instance)
self.run_validators(value)
return self.to_python(value)

Flask login 'function' object has no attribute 'is_active'

I try to use flask login in may app:
My controller:
#app.route("/process_log", methods=['POST'])
def process_login():
filled_form = LoginForm(request.form)
if filled_form.validate():
phone = filled_form.phone.data
password = filled_form.password.data
if User.phone_exists(phone) and User.pass_match(phone, password):
user = User.get_by_phone(phone)
login_user(user.get_id)
return redirect(url_for("index"))
else:
return render_template("login.html", form = filled_form, error = u"Не верный логин или пароль")
else:
return render_template("home.html", form = filled_form)
and I have some class with defined functions which required for API of flask login
My User class:
from pymongo import MongoClient
from bson.objectid import ObjectId
class User():
client = MongoClient()
db = client['test']
col = db['user']
user_id = None
def __init__(self, dic):
self.dic = dic
def is_authenticated():
return True
def is_anonymous():
return False
def is_active():
return True
def get_id(self):
return unicode(str(self.user_id))
def save(self):
self.user_id = self.col.insert(self.dic)
print "Debug:" + str(self.user_id)
#staticmethod
def _get_col():
client = MongoClient()
db = client['test']
col = db['user']
return col
#staticmethod
def phone_exists(phone):
col = User._get_col()
if col.find_one({'phone': phone}) != None:
return True
else:
return False
#staticmethod
def pass_match(phone, password):
col = User._get_col()
if col.find_one({'phone': phone})['password'] == password:
return True
else:
return False
#staticmethod
def get(userid):
col = User._get_col()
return col.find_one({'_id':userid})
#staticmethod
def get_by_phone(phone):
col = User._get_col()
dic = col.find_one({'phone': phone})
print dic['password']
return User(dic)
As you see function is_active is defined(Note:I also tried to pass refference with self)
But I still have this error AttributeError: 'function' object has no attribute 'is_active'
I am sorry for too much code here, but it should be pretty straightforward.
Note: I am using mongodb for my project.
Please help me to find my error. Thank you too much
One more thing:
Should I provide login_user(....) with Id or with my user object?
You must sent to login_user User instance (not id), see: https://github.com/maxcountryman/flask-login/blob/master/flask_login.py#L576.
So next code must work:
user = User.get_by_phone(phone)
login_user(user)