how to store a field in the database after querying - django

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)))

Related

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.

Django get count of each age

I have this model:
class User_Data(AbstractUser):
date_of_birth = models.DateField(null=True,blank=True)
city = models.CharField(max_length=255,default='',null=True,blank=True)
address = models.TextField(default='',null=True,blank=True)
gender = models.TextField(default='',null=True,blank=True)
And I need to run a django query to get the count of each age. Something like this:
Age || Count
10 || 100
11 || 50
and so on.....
Here is what I did with lambda:
usersAge = map(lambda x: calculate_age(x[0]), User_Data.objects.values_list('date_of_birth'))
users_age_data_source = [[x, usersAge.count(x)] for x in set(usersAge)]
users_age_data_source = sorted(users_age_data_source, key=itemgetter(0))
There's a few ways of doing this. I've had to do something very similar recently. This example works in Postgres.
Note: I've written the following code the way I have so that syntactically it works, and so that I can write between each step. But you can chain these together if you desire.
First we need to annotate the queryset to obtain the 'age' parameter. Since it's not stored as an integer, and can change daily, we can calculate it from the date of birth field by using the database's 'current_date' function:
ud = User_Data.objects.annotate(
age=RawSQL("""(DATE_PART('year', current_date) - DATE_PART('year', "app_userdata"."date_of_birth"))::integer""", []),
)
Note: you'll need to change the "app_userdata" part to match up with the table of your model. You can pick this out of the model's _meta, but this just depends if you want to make this portable or not. If you do, use a string .format() to replace it with what the model's _meta provides. If you don't care about that, just put the table name in there.
Now we pick the 'age' value out so that we get a ValuesQuerySet with just this field
ud = ud.values('age')
And then annotate THAT queryset with a count of age
ud = ud.annotate(
count=Count('age'),
)
At this point we have a ValuesQuerySet that has both 'age' and 'count' as fields. Order it so it comes out in a sensible way..
ud = ud.order_by('age')
And there you have it.
You must build up the queryset in this order otherwise you'll get some interesting results. i.e; you can't group all the annotates together, because the second one for count depends on the first, and as a kwargs dict has no notion of what order the kwargs were defined in, when the queryset does field/dependency checking, it will fail.
Hope this helps.
If you aren't using Postgres, the only thing you'll need to change is the RawSQL annotation to match whatever database engine it is that you're using. However that engine can get the year of a date, either from a field or from its built in "current date" function..providing you can get that out as an integer, it will work exactly the same way.

Editing an Object in Database from Django Form

How can you edit an existing object in a database from a form? I use this for example:
obj_ex = Model(column = value, column2 = value2)
obj_ex.save()
However this doesn't update my object in the database. I have tried to access the pk of the entry and save the values of the entry with the pk of x but I still can't update the table.
Is there a way to use an .update() type to update objects? Or is there another way to update a table?
Thank you.
Instead of:
obj_ex = Model(column=value, column2=value2)
Which creates a new instance (and later a new db record) try:
o = Model.objects.get(pk=1234) # load instance with id=1234 to memory from db
o.column = value
o.column2 = value2
o.save()
Because I had multiple entries in the table, I used an update field to updated the cells in the table. This is what I did:
o = Model.objects.filter(x=value0).values_list("id", flat=True) #where x is posted information getting the primary key (id).
Model.objects.select_related().filter(id = o).update(column = value, column2 = value2)
The update field does not need a .save() as it will update the table when it is called.
I would like to thank Udi for his answer as it did step me into the right direction.

django query optimization in iteration

class Value(models.Model):
attribute = models.ForeignKey(Attribute)
platform = models.ForeignKey(Platform)
value = models.CharField(max_length=30)
class Attribute(models.Model):
name = models.CharField(max_length=50)
....
1.
for attribute in attributes:
attribute.value = Value.objects.get(Q(attribute__id=attribute.id) & Q(platform__id=platform.id))
2.
values = Value.objects.filter(platform__id=platform.id)
for attribute in attributes:
attribute.value = values.get(attribute__id=attribute.id)
Can I say the method 2 is more efficient than 1 because it prevents excessive DB query?
Example 2 can be reduced to only 1 DB query like so:
values = Value.objects.filter(platform__id=platform.id)
attribute_values = {value.attribute_id: value for value in values}
for attribute in attributes:
attribute.value = attribute_values[attribute.id]
I'm assuming that Value.attribute is a ForeignKey
I wouldn't say that's the case, because filter and get are just building up some where statements for sql query. You might think that django is caching the value values because you only do it once, but the query is not even evaluated when you do:
values = Value.objects.filter(platform__id=platform.id)
Every time you call get, it's adding a where statement upon the filter statement and hit the database to fetch the results, so you don't gain anything in terms of performance.
By the way, Value.objects.get(Q(attribute__id=attribute.id) & Q(platform__id=platform.id)) is the same as:
Value.objects.get(attribute=attribute, platform=platform)
which is more readable.

django annotate count filter

I am trying to count daily records for some model, but I would like the count was made only for records with some fk field = xy so I get list with days where there was a new record created but some may return 0.
class SomeModel(models.Model):
place = models.ForeignKey(Place)
note = models.TextField()
time_added = models.DateTimeField()
Say There's a Place with name="NewYork"
data = SomeModel.objects.extra({'created': "date(time_added)"}).values('created').annotate(placed_in_ny_count=Count('id'))
This works, but shows all records.. all places.
Tried with filtering, but it does not return days, where there was no record with place.name="NewYork". That's not what I need.
It looks as though you want to know, for each day on which any object was added, how many of the objects created on that day have a place whose name is New York. (Let me know if I've misunderstood.) In SQL that needs an outer join:
SELECT m.id, date(m.time_added) AS created, count(p.id) AS count
FROM myapp_somemodel AS m
LEFT OUTER JOIN myapp_place AS p
ON m.place_id = p.id
AND p.name = 'New York'
GROUP BY created
So you can always express this in Django using a raw SQL query:
for o in SomeModel.objects.raw('SELECT ...'): # query as above
print 'On {0}, {1} objects were added in New York'.format(o.created, o.count)
Notes:
I haven't tried to work out if this is expressible in Django's query language; it may be, but as the developers say, the database API is "a shortcut but not necessarily an end-all-be-all.")
The m.id is superfluous in the SQL query, but Django requires that "the primary key ... must always be included in a raw query".
You probably don't want to write the literal 'New York' into your query, so pass a parameter instead: raw('SELECT ... AND p.name = %s ...', [placename]).