Filling out select control with python mechanize - python-2.7

I'm trying to fill out the registration for a website with python mechanize. Everything is going well but I can't figure out how to do the select controls. For example, if I'm picking my birthday month, here's the form that I need to fill out:
<SelectControl(mm=[*, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])>
I've viewed all the answers on stackoverflow already and they all seem to be some variation like this:
br.find_control(name="mm").value = ["0"]
or
form["mm"] = ["1"]
The problem here is that it gives me a error ItemNotFoundError: insufficient items with name '0'

item = br.find_control(name="mm" type="select").get("12")
item.selected = True

Nvm I just needed to do br.form['mm'] = ["1"] <--- I selected this but could have picked any of the values they allowed.

I have used all of the following:
br['mm'] = ['9']
br['mm'] = ['9',]
br.form['mm'] = ['9']
br.form['mm'] = ['9',]
I seem to remember one case where the comma was mandatory.

Related

Django - update dictionary with missing date values, set to 0

So to display a small bargraph using Django and Chart.js I constructed the following query on my model.
views.py
class BookingsView(TemplateView):
template_name = 'orders/bookings.html'
def get_context_data(self, **kwargs):
today = datetime.date.today()
seven_days = today + datetime.timedelta(days=7)
bookings = dict(Booking.objects.filter(start_date__range = [today, seven_days]) \
.order_by('start_date') \
.values_list('start_date') \
.annotate(Count('id')))
# Edit set default for missing dictonairy values
for dt in range(7):
bookings.setdefault(today+datetime.timedelta(dt), 0)
# Edit reorder the dictionary before using it in a template
context['bookings'] = OrderedDict(sorted(bookings.items()))
This led me to the following result;
# Edit; after setting the default on the dictionary and the reorder
{
datetime.date(2019, 8, 6): 12,
datetime.date(2019, 8, 7): 12,
datetime.date(2019, 8, 8): 0,
datetime.date(2019, 8, 9): 4,
datetime.date(2019, 8, 10): 7,
datetime.date(2019, 8, 11): 0,
datetime.date(2019, 8, 12): 7
}
To use the data in a chart I would like to add the missing start_dates into the dictionary but I'm not entirely sure how to do this.
So I want to update the dictionary with a value "0" for the 8th and 11th of August.
I tried to add the for statement but I got the error;
"'datetime.date' object is not iterable"
Like the error says, you can not iterate over a date object, so for start_date in seven_days will not work.
You can however use a for loop here like:
for dt in range(7):
bookings.setdefault(today+datetime.timedelta(dt), 0)
A dictionary has a .setdefault(..) function that allows you to set a value, given the key does not yet exists in the dicionary. This is thus shorter and more efficient than first checking if the key exists yourself since Python does not have to perform two lookups.
EDIT: Since python-3.7 dictionaries are ordered in insertion order (in the CPython version of python-3.6 that was already the case, but seen as an "implementation detail"). Since python-3.7, you can thus sort the dictionaries with:
bookings = dict(sorted(bookings.items()))
Prior to python-3.7, you can use an OrderedDict [Python-doc]:
from collections import OrderedDict
bookings = OrderedDict(sorted(bookings.items()))

Weird behavior in Django queryset union of values

I want to join the sum of related values from users with the users that do not have those values.
Here's a simplified version of my model structure:
class Answer(models.Model):
person = models.ForeignKey(Person)
points = models.PositiveIntegerField(default=100)
correct = models.BooleanField(default=False)
class Person(models.Model):
# irrelevant model fields
Sample dataset:
Person | Answer.Points
------ | ------
3 | 50
3 | 100
2 | 100
2 | 90
Person 4 has no answers and therefore, points
With the query below, I can achieve the sum of points for each person:
people_with_points = Person.objects.\
filter(answer__correct=True).\
annotate(points=Sum('answer__points')).\
values('pk', 'points')
<QuerySet [{'pk': 2, 'points': 190}, {'pk': 3, 'points': 150}]>
But, since some people might not have any related Answer entries, they will have 0 points and with the query below I use Coalesce to "fake" their points, like so:
people_without_points = Person.objects.\
exclude(pk__in=people_with_points.values_list('pk')).\
annotate(points=Coalesce(Sum('answer__points'), 0)).\
values('pk', 'points')
<QuerySet [{'pk': 4, 'points': 0}]>
Both of these work as intended but I want to have them in the same queryset so I use the union operator | to join them:
everyone = people_with_points | people_without_points
Now, for the problem:
After this, the people without points have their points value turned into None instead of 0.
<QuerySet [{'pk': 2, 'points': 190}, {'pk': 3, 'points': 150}, {'pk': 4, 'points': None}]>
Anyone has any idea of why this happens?
Thanks!
I should mention that I can fix that by annotating the queryset again and coalescing the null values to 0, like this:
everyone.\
annotate(real_points=Concat(Coalesce(F('points'), 0), Value(''))).\
values('pk', 'real_points')
<QuerySet [{'pk': 2, 'real_points': 190}, {'pk': 3, 'real_points': 150}, {'pk': 4, 'real_points': 0}]>
But I wish to understand why the union does not work as I expected in my original question.
EDIT:
I think I got it. A friend instructed me to use django-debug-toolbar to check my SQL queries to investigate further on this situation and I found out the following:
Since it's a union of two queries, the second query annotation is somehow not considered and the COALESCE to 0 is not used. By moving that to the first query it is propagated to the second query and I could achieve the expected result.
Basically, I changed the following:
# Moved the "Coalesce" to the initial query
people_with_points = Person.objects.\
filter(answer__correct=True).\
annotate(points=Coalesce(Sum('answer__points'), 0)).\
values('pk', 'points')
# Second query does not have it anymore
people_without_points = Person.objects.\
exclude(pk__in=people_with_points.values_list('pk')).\
values('pk', 'points')
# We will have the values with 0 here!
everyone = people_with_points | people_without_points

Counterbalancing in open sesame

I a writing an inline_script in open sesame (python).
Can anyone tell me what's wrong here? (i think its something very simple, but i can not find it)
when i put the number in List = [1,2,3,4,5,6,7] the first line works, but the second does not work :(
BalanceList1 = range(1:7) + range(13:19) #does not work
if self.get('subject_nr') == "BalanceList1":
#here follows a list of commands
BalanceList2 = list(range(7:13))+list(range(19:25)) #does not work either
elif self.get('subject_nr') == "BalanceList2":
#other commands
In python 2.x you can do the following:
BalanceList1 = range(1,6) + range(13,19)
which will generate 2 lists and add them together in BalanceList1:
[1, 2, 3, 4, 5, 13, 14, 15, 16, 17, 18]
In python 3.x, range doesn't return a list anymore but an iterator (and xrange is gone), you have to explicitly convert to list:
BalanceList1 = list(range(1,6))+list(range(13,19))
A more optimal way to avoid creating too many temporary lists would be:
BalanceList1 = list(range(1,6))
BalanceList1.extend(range(13,19)) # avoids creating the list for 13->18
more optimal than:

Store data group by datetime column using pig

Say that I have the dataset like this
1, 3, 2015-03-25 11-15-13
1, 4, 2015-03-26 11-16-14
1, 4, 2015-03-25 11-16-15
1, 5, 2015-03-27 11-17-11
...
I want to store the data by datetime
so I will have the following output folders
2015-03-25/
2015-03-26/
2015-03-27/
...
How to do that with pig?
Thank you
You can use MultiStorage for this.
Use a FOREACH GENERATE to create a column that contains the date part that you are interested and then something like
STORE X INTO '/my/home/output' USING MultiStorage('/my/home/output','2');

How to obtain months in right order from different years from DateField in django?

I have django model with DateField. I can get list of months of objects in such way:
months = [i.month for i in MyModel.objects.values_list('date', flat=True)]
and after delete duplicates I receive such list (example): [1, 2, 5, 6, 7, 9].
But if I have different years, I want to receive months in right date order. For example:
date1=31.08.2012, date2=31.12.2012, date3=05.05.2013.
So I want to receive not [5, 8, 12] but [8, 12, 5].
How can I do it?
You're trying to get the months in order of when they first appear chronologically?
list(set(date.month for date in MyModel.objects.order_by("date").values_list('date', flat=True)))
Sorting by year is the same as sorting by date. Yay!
The only way to do it would be to add the year in too:
dates = [(i.year, i.month) for i in MyModel.objects.values_list('date', flat=True)]
That would return this list (once duplicates are removed and sorted):
[(2012, 8), (2012, 12), (2013, 5)]
If you wanted later, you could then get just the months by:
>>> [x[1] for x in dates]
[8, 12, 5]
But note that there may well be duplicates in that list too (August In both 2012 and 2013 would come out as 8, for example), and you wouldn't necessarily know where the list changes from one year to the next.