I'm wondering how the TestCase.assertQuerysetEqual method works. I tried it in different ways, each of them leading me to another error message.
#create a backup of all records in the tree
tree_record_backup = list(Tree.objects.all())
#do some updates on another table, which should not affect the tree table if everything goes wrong
#check if list of tree records did not changed
tree_record_qs = Tree.objects.all()
#Number1:
self.assertQuerysetEqual(tree_record_qs,[repr(tree_record_backup)])
#Number2:
self.assertQuerysetEqual(tree_record_qs,tree_record_backup)
Error Message for Number1:
First list contains 21 additional elements.
First extra element 1:
node.pk: 2 - node: node2 - pk: 2 - level: 0 - ancestor: 2
Error Message for Number 2:
AssertionError: Lists differ: ['<Tree: node.pk: 1 - node: ro... != [<Tree: node.pk: 1 - node: roo...
First differing element 0:
<Tree: node.pk: 1 - node: root - pk: 1 - level: 0 - ancestor: 1>
node.pk: 1 - node: root - pk: 1 - level: 0 - ancestor: 1
Thanks for hints how to use the assertQuerysetEqual method correctly.
assertQuerysetEqual takes a queryset, a list of values and a transform callable which is called on the queryset to convert it into something comparable to the list of values. By default this callable is repr. This is kind of irritating since it doesn't actually compare two querysets, but the easy fix for most cases is using map(repr, your_second_queryset) for the list of values. This is documented in django since version 1.3.
try this:
self.assertQuerysetEqual(
tree_record_qs,
[repr(r) for r in tree_record_backup]
)
it's a bit weird and undocumented; but, that should work for you.
Related
I have the following list:
- hosts: localhost
gather_facts: false
vars:
list1: [1,2,3,4]
tasks:
I need this to be of a type dict with key-value pairs where each member of list (1,2,3,4,...n) will have key "a".
dict1: [{a: 1}, {a:2}, {a:3}, {a:4}]
I know there is list2dict filter, but couldn't find examples or literature that would explain it how to do it. PS there can be n number of items in the list.
Thanks!
See filter community.general.dict_kv. For example,
dict1: "{{ list1|map('community.general.dict_kv', 'a') }}"
gives what you want
dict1:
- a: 1
- a: 2
- a: 3
- a: 4
Maybe the solution is to do it with Filter and then loop. But let's see if you guys can tell me a way to do it with GET
I have this query with GET as I need to be sure I get only one result
result = OtherModel.objects.get(months_from_the_avail__lte=self.obj.months_from_avail)
Months_from_avail is an Integer value.
Example
months_from_the_avail = 22
In the other model there's 3 lines.
A) months_from_the_avail = 0
B) months_from_the_avail = 7
C) months_from_the_avail = 13
So, when I query it returns all of them as all are less than equal the value 22 but I need to get the 13 as is the last range.
range 1 = 0-6
range 2 = 7-12
range 3 = 13 ++
Is there any way that I haven't thought to do it? Or should I change it to filter() and then loop on the results?
you can get the first() section from the query order_by months_from_the_avail
Remember that django query are lazy, it won't execute until the query if finished calling so you can still use filter:
result = OtherModel.objects.filter(months_from_the_avail__lte=self.obj.months_from_avail).order_by('-months_from_the_avail').first()
#order by descending get first object which is the largest, return None if query set empty
another suggestion from Abdul which i think it's faster and better is using latest()
OtherModel.objects.latest('-months_from_the_avail')
I am trying to just do a basic INSERT operation to a PostgreSQL database through Python via the Psycopg2 module. I have read a great many of the questions already posted regarding this subject as well as the documentation but I seem to have done something uniquely wrong and none of the fixes seem to work for my code.
#API CALL + JSON decoding here
x = 0
for item in ulist:
idValue = list['members'][x]['name']
activeUsers.append(str(idValue))
x += 1
dbShell.executemany("""INSERT INTO slickusers (username) VALUES (%s)""", activeUsers
)
The loop creates a list of strings that looks like this when printed:
['b2ong', 'dune', 'drble', 'drars', 'feman', 'got', 'urbo']
I am just trying to have the code INSERT these strings as 1 row each into the table.
The error specified when running is:
TypeError: not all arguments converted during string formatting
I tried changing the INSERT to:
dbShell.executemany("INSERT INTO slackusers (username) VALUES (%s)", (activeUsers,) )
But that seems like it's merely treating the entire list as a single string as it yields:
psycopg2.DataError: value too long for type character varying(30)
What am I missing?
First in the code you pasted:
x = 0
for item in ulist:
idValue = list['members'][x]['name']
activeUsers.append(str(idValue))
x += 1
Is not the right way to accomplish what you are trying to do.
first list is a reserved word in python and you shouldn't use it as a variable name. I am assuming you meant ulist.
if you really need access to the index of an item in python you can use enumerate:
for x, item in enumerate(ulist):
but, the best way to do what you are trying to do is something like
for item in ulist: # or list['members'] Your example is kinda broken here
activeUsers.append(str(item['name']))
Your first try was:
['b2ong', 'dune', 'drble', 'drars', 'feman', 'got', 'urbo']
Your second attempt was:
(['b2ong', 'dune', 'drble', 'drars', 'feman', 'got', 'urbo'], )
What I think you want is:
[['b2ong'], ['dune'], ['drble'], ['drars'], ['feman'], ['got'], ['urbo']]
You could get this many ways:
dbShell.executemany("INSERT INTO slackusers (username) VALUES (%s)", [ [a] for a in activeUsers] )
or event better:
for item in ulist: # or list['members'] Your example is kinda broken here
activeUsers.append([str(item['name'])])
dbShell.executemany("""INSERT INTO slickusers (username) VALUES (%s)""", activeUsers)
I have a query that's basically "count all the items of type X, and return the items that exist more than once, along with their counts". Right now I have this:
Item.objects.annotate(type_count=models.Count("type")).filter(type_count__gt=1).order_by("-type_count")
but it returns nothing (the count is 1 for all items). What am I doing wrong?
Ideally, it should get the following:
Type
----
1
1
2
3
3
3
and return:
Type, Count
-----------
1 2
3 3
In order to count the number of occurrences of each type, you have to group by the type field. In Django this is done by using values to get just that field. So, this should work:
Item.objects.values('group').annotate(
type_count=models.Count("type")
).filter(type_count__gt=1).order_by("-type_count")
It's logical error ;)
type_count__gt=1 means type_count > 1 so if the count == 1 it won't be displayed :)
use type_count__gte=1 instead - it means type_count >= 1 :)
I am working on a webserver project and have little experience with MVC architecture. What reading I have done points me to the idea of "Skinny Controllers, Fat Models." Keeping this in mind, I've tried tinkering around in rails to get the effect I'm looking for:
I accept through a form a string and must sanitize it (Assuming this is done through Callbacks). After it has been sanitized, I'm converting it into an array and sorting it.
Each step of the sort is being recorded in a variable #states. I need to put #states variable into the database when the process is done.
My question is: how is this setup best enacted? I think I'm correct that the sanitation should be performed through a callback... but the second part is what's giving me fits.
Here's something of an example:
recieve input: "4 3 2 1\r\n5 2 2 1\r\n1 5 4 3"
sanitize input to: 4 3 2 1 5 2 2 1 1 5 4 3 # Presumably through a callback
until input.sorted? do:
input.bubblesort(#states) # each time bubblesort moves an entry, it sends a copy of the array to #states
#Do something with #states in the model.rb file
I would love some input on this because I'm at an impasse and nothing quite makes sense.
The value you get from the form submission will be stored in the params hash. I'm fairly certain rails sanitizes everything automatically as of rails 4 and that you only need to be wary of tainted data during ActiveRecord queries.
Assuming you have your input: "4 3 2 1\r\n5 2 2 1" I would replace all r's and n's with spaces via the .gsub method. Once you have input such as
input= "4 3 2 1 5 2 2 1" you can do input.split(/\s/) which will convert the string to an array with all elements split where there are spaces. From there you can easily order the array since strings are comparable in ruby.
EDIT***
#states = input.bubblesort(#states) #then maybe something like this depending on your table setup: #new_state = YourModel.create(#states) ' If you're using a db like Postgresql you can specify that the input of a certain attribute will be an array. This is done as so via a migration: 'add_column :table_name, :column_name, :string, array: true, default: []'
Normally, the only logic that is kept in the model are your validations and sort/scope methods.