How to bulk_update queryset values - django

# Count mandate for each delegate, multiply it by score
delegate_votes = PollVotingTypeRanking.objects.filter(author_delegate__poll=poll).values('pk').annotate(
score=F('priority') *
Count('author_delegate__created_by__groupuserdelegator',
filter=~Q(author_delegate__created_by__groupuserdelegator__delegator__pollvoting__poll=poll) &
Q(author_delegate__created_by__groupuserdelegator__tags__in=[poll.tag])))
# Set score to the same as priority for user votes
user_votes = PollVotingTypeRanking.objects.filter(author__poll=poll
).values('pk').annotate(score=F('priority'))
PollVotingTypeRanking.objects.bulk_update(delegate_votes | user_votes, fields=('score',))
Attempting to update the values for delegate_votes and user_votes, how do i do that? Currently im getting the error 'dict' object has no attribute pk

Related

How to count the number of keys in a django jsonfield

I would like to make a queryset filter to identify all model instance that have a given number of keys in a jsonfield of the model.
I have tried to create a custom lookup (#1) to extra the keys in the json field,
and would like to aggregate those into an array and use the __len lookup of the array to make my filter. Unfortunately, I am stuck at the aggregation that doesn't seem to work (#2).
1
class JsonKeys(Transform):
output_field = TextField()
lookup_name = 'keys'
function = 'jsonb_object_keys'
2
qs = qs.annotate(keysArray=ArrayAgg("myJsonField__keys"))
The error that I get is:
HINT: You might be able to move the set-returning function into a LATERAL FROM item.
Anyone has already tried to perform this task ?

save() not updating the table in database

I have to update 2 tables in database every time user visit a page.
this is working:
order_order = OrderTable.no_objects.get(order_number=order_id)
order_order.status = 'updated status'
order_order.save()
This is not working: (related with first table through foreign key)
order_item = ItemsTable.objects.filter(order_id__order_number=order_id)
for i in range(order_item.count()):
order_item[i].qty = i + 5
order_item[i].qty_nextMonth = i + 30
order_item[i].save()
Can anyone tell what's wrong in 2nd part of code. It's not updating the database.
Each time you write order_item[i], you make a separate fetch, and you return an ItemsTable item from the database. That means that if you set the .qty = ... attribute of that object, it is simply ignored, since the next order_item[i] will trigger a new fetch. Your order_item[i].save() updates the record in the database, but with the values that have been retrieved just from a fetch from the database.
It is better to simply iterate over the queryset, and thus maintain a reference to the same ItemsTable object:
order_items = ItemsTable.objects.filter(order_id__order_number=order_id)
for i, order_item in enumerate(order_items):
order_item.qty = i + 5
order_item.qty_nextMonth = i + 30
order_item.save()
This is more efficient as well, since enumerating over a queryset forces evaluation, and hence you fetch all objects at once.
As of django-2.2, you can use .bulk_update(..) [Django-doc], to update in bulk an iterable of objects.

how to store a field in the database after querying

views.py:
q3=KEBReading.objects.filter(datetime_reading__month=a).filter(datetime_reading__year=selected_year).values("signed")
for item in q3:
item["signed"]="signed"
print item["signed"]
q3.save()
How do I save a field into the database? I'm trying to save the field called "signed" with a value. If I do q3.save() it gives a error as it is a queryset. I'm doing a query from the database and then, based on the result, want to set a value to a field and save it.
prevdate=KEBReading.objects.filter(datetime_reading__lt=date)
i am getting all the rows from the database less than the current date. but i want only the latest record. if im entering 2012-06-03. wen i query i want the date less than this date i.e the date just previous to this. can sumbody help?
q3 = KEBReading.objects.filter(datetime_reading__month=a,
datetime_reading__year=selected_year)
for item in q3:
item.signed = True
item.save()
q3=KEBReading.objects.filter(...)
will return you a list of objects. Any instance of a Django Model is an object and all fields of the instance are attributes of that object. That means, you must use them using dot (.) notation.
like:
item.signed = "signed"
If your object is a dictionary or a class derived from dictionary, then you can use named-index like:
item["signed"] = "signed"
and in your situation, that usage is invalid (because your object's type is not dictionary based)
You can either call update query:
KEBReading.objects.filter(...).update(selected="selected")
or set new value in a loop and then save it
for item in q3:
item.signed="signed"
q3.save()
but in your situation, update query is a better approach since it executes less database calls.
Try using update query:
If signed is a booleanfield:
q3 = KEBReading.objects.filter(datetime_reading__month = a).filter(datetime_reading__year = selected_year).update(signed = True)
If it is a charfield:
q3 = KEBReading.objects.filter(datetime_reading__month = a).filter(datetime_reading__year = selected_year).update(signed = "True")
Update for comments:
If you want to fetch records based datetime_reading month, you can do it by providing month as number. For example, 2 for February:
q3 = KEBReading.objects.filter(datetime_reading__month = 2).order_by('datetime_reading')
And if you to fetch records with signed = True, you can do it by:
q3 = KEBReading.objects.filter(signed = True)
If you want to fetch only records of previous date by giving a date, you can use:
prevdate = KEBReading.objects.filter(datetime_reading = (date - datetime.timedelta(days = 1)))

How to fetch the unique value from Django-query

I have a method:
def get_netmask(user=None):
user = User.objects.get(username=user)
id_user = user.id
obj = Host.objects.get(user=id_user)
obj = obj.ipv4_sub_net.distinct('ipv4_sub_net').order_by('ipv4_sub_net')
# In this line i am getting an error: `'unicode' object has no
# attribute 'distinct'` but the query is not complete . For full
# question please follow the lines and given example
return obj
Object of the Host model are ipv4_sub_net and ipv6_sub_net. My motive is for defining the above method is to get the value from ipv4_sub_net + ipv6_sub_net model field which will be fetched from Host model corresponding to a requesting user (loginned user). To do this i passed reuest.user.username to the get_netmask parameter at the time of calling it. Apart from that i also want to return the count os similar entry in ipv4_sub_net and ipv6_sub_net seperately.
For example:
In table there are four coloum present:
id user_id ipv4_sub_net ipv6_sub_net
1 2 1.0.0.1 /23
2 2 8.9.7.3 /23
3 1 23.2.3.4 /43
4 2 1.0.0.1 /23
So, let's say that the requesting user is with user_id 2. So according to method definitions it will return the dictionary. First index of dictionary contain unique IPv4_sub_net + ipv6_sub_net which is "1.0.0.1" and /23 and the second index will return the count of returning similar sub_net for ipv4 and the third index will return the count of similarsub_netfor ipv6 which2 for ipv4and2 for ipv6`.
Try changing
obj = obj.ipv4_sub_net.distinct('ipv4_sub_net').order_by('ipv4_sub_net')
to
obj = obj.distinct('ipv4_sub_net').order_by('ipv4_sub_net')
Edit
On the first pass, I missed another error. You should also change
obj = Host.objects.get(user=id_user)
to
obj = Host.objects.filter(user=id_user)
get will always return a single object and throw an error if multiple objects are returned. If you're expecting a single object, then I'm not really sure what you're trying to do.

Bounds and constraints in Django ForeignKey field values -- and how they can effect queryset results

For example if I have models.py like this:
Handler(models.Model):
model1 = ForeignKey(Model1)
model2 = ForeigKey(Model2)
user = models.ForeignKey(User)
For example there are 100 instances of Handler with Model1 id = 1, but Model 2 id for this 100 instances is in range 1 to 5. And when I do something like this:
Handles.objects.filter(model1=1).values_list('model2_id', flat=True)
It returns list of 5 id values or list of 100 id values, which are be repeated?
And if it return 100 values is there possibility to remain only one value for every repeated value?
It will return a list of 100 id values.
If you want to get the unique 5 ones, then you can do that in python.
model2_id_uniq_values = list(set(Handles.objects.filter(model1=1).values_list('model2_id', flat=True)))
It may not be the most finely tuned algorithm, and by using a set, you would lose the order. But for your purposes it appears to work.