In Django, I want to retrieve the last inserted record from the database and update its values.
I use this model:
def User(models.Model):
name = models.CharField(max_length=15)
I run the following code to retrieve the last inserted record and update the name:
User.objects.last().update(name=‘NEW NAME’)
However, the error is that update is not a known method.
Does .last() indeed return the entire record, or only the primary key?
Thank you very much.
Does .last() indeed return the entire record, or only the primary key?
.last() [Django-doc] returns the last User object, or None, if there is no such record.
Now a single model object has indeed no .update(..) method. Only a QuerySet has an update(..) [Django-doc] method. You thus can for example retrieve it, alter the field, and then save the object:
last_user = User.objects.last()
if last_user is not None:
last_user.name = 'NEW NAME'
last_user.save()
you must at first get the user model then use last like this
user = User.objects.all().last()
and now you can update with this code
user.name = 'Daniel'
user.save()
Suppose you model/database is this
class User(models.Model):
name = models.CharField(max_length=15)
Then you go to the terminal and start the shell to do some testing. For that you do
python manage.py shell
In the shell, first you need to import your database/model
from nameofyourapp.models import User
To get the last element you could write
lastUser = User.objects.all().last()
Now change the last User
lastUser["name"] = "Josh"
Save the changes
lastUser.save()
Exit from the terminal
Related
In my model for user profile, the profile_last_updated = models.DateTimeField(auto_now=True) keeps updating every time the relevant profile owner logs in but doesn't update any of their details. Is there a way to fix this? I found this on SO django last updated keeps updating when there is no new information but it's a bit confusing. Appreciate any help - thanks!
views.py
def user_profile_detail_view(request,pk):
try:
myprofile = get_object_or_404(User, id=pk)
except ObjectDoesNotExist:
return redirect('handler404')
See, the problem with auto_now=True is that the field always gets update whenever the .save() method is called and thus you are seeing an unexpected behaviour.
Instead what you can do is you can remove auto_now or set it to False then always manually update the field using DateTime.
Example:
from datetime import datetime as dt
def your_view_function(request):
#your rest of the function for processing user profile
Models.objects.filter(id=id_of_field_updated).update(profile_last_updated=dt.now())
I'm building a Django application, and in it I would like to track whenever a particular model was last accessed.
I'm opting for this in order to build a user activity history.
I know Django provides auto_now and auto_now_add, but these do not do what I want them to do. The latter tracks when a model was created, and the former tracks when it was last modified, which is different from when it was last accessed, mind you.
I've tried adding another datetime field to my model's specification:
accessed_on = models.DateTimeField()
Then I try to update the model's access manually by calling the following after each access:
model.accessed_on = datetime.utcnow()
model.save()
But it still won't work.
I've gone through the django documentation for an answer, but couldn't find one.
Help would be much appreciated.
What about creating a model with a field that contains the last save-date. Plus saving the object every time is translated from the DB representation to the python representation?
class YourModel(models.Model):
date_accessed = models.DateTimeField(auto_now=True)
#classmethod
def from_db(cls, db, field_names, values):
obj = super().from_db(db, field_names, values)
obj.save()
return obj
How do I run an update and select statements on the same queryset rather than having to do two queries:
- one to select the object
- and one to update the object
The equivalent in SQL would be something like:
update my_table set field_1 = 'some value' where pk_field = some_value
Use the queryset object update method:
MyModel.objects.filter(pk=some_value).update(field1='some value')
Django database objects use the same save() method for creating and changing objects.
obj = Product.objects.get(pk=pk)
obj.name = "some_new_value"
obj.save()
How Django knows to UPDATE vs. INSERT
If the object’s primary key attribute is set to a value that evaluates to True (i.e., a value
other than None or the empty string), Django executes an UPDATE. If
the object’s primary key attribute is not set or if the UPDATE didn’t
update anything, Django executes an INSERT.
Ref.: https://docs.djangoproject.com/en/1.9/ref/models/instances/
This answer compares the above two approaches.
If you want to update many objects in a single line, go for:
# Approach 1
MyModel.objects.filter(field1='Computer').update(field2='cool')
Otherwise you would have to iterate over the query set and update individual objects:
#Approach 2
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
obj.field2 = 'cool'
obj.save()
Approach 1 is faster because, it makes only one database query, compared to approach 2 which makes 'n+1' database queries. (For n items in the query set)
Fist approach makes one db query ie UPDATE, the second one makes two: SELECT and then UPDATE.
The tradeoff is that, suppose you have any triggers, like updating updated_on or any such related fields, it will not be triggered on direct update ie approach 1.
Approach 1 is used on a queryset, so it is possible to update multiple objects at once, not in the case of approach 2.
1st method
MyTable.objects.filter(pk=some_value).update(field1='some value')
2nd Method
q = MyModel.objects.get(pk=some_value)
q.field1 = 'some value'
q.save()
3rd method
By using get_object_or_404
q = get_object_or_404(MyModel,pk=some_value)
q.field1 = 'some value'
q.save()
4th Method
if you required if pk=some_value exist then update it other wise create new one by using update_or_create.
MyModel.objects.update_or_create(pk=some_value,defaults={'field1':'some value'})
If you need to set the new value based on the old field value that is do something like:
update my_table set field_1 = field_1 + 1 where pk_field = some_value
use query expressions:
MyModel.objects.filter(pk=some_value).update(field1=F('field1') + 1)
This will execute update atomically that is using one update request to the database without reading it first.
only in a case in serializer things, you can update in very simple way!
my_model_serializer = MyModelSerializer(
instance=my_model, data=validated_data)
if my_model_serializer.is_valid():
my_model_serializer.save()
only in a case in form things!
instance = get_object_or_404(MyModel, id=id)
form = MyForm(request.POST or None, instance=instance)
if form.is_valid():
form.save()
Accepted answer works great, but it comes with some unwanted side effect.
For example, you are using imageField, the update() will work and update others data, but not update your imageField data
class ProfileSetting(models.Model):
first_name = models.CharField(blank=True)
logo = models.ImageField(blank=True, null=True, upload_to="profile/logo/")
update_data = {
"first_name": "john",
"logo": request.FILES['logo'] # logo will not be properly update
}
ProfileSetting.objects.filter(pk=some_value).update(**update_data)
Here is some example with good explanation Django ImageField is not updating when update() method is used
I'm using Django 1.3 for one of my projects and I need to get the ID of a record just saved in the database.
I have something like the code below to save a record in the database:
n = MyData.objects.create(record_title=title, record_content=content)
n.save()
The ID of the record just saved auto-increments. Is there a way to get that ID and use it somewhere else in my code?
Use n.id after the save.
See "Auto-incrementing primary keys".
It would be n.pk.
To quote "Model.pk":
Regardless of whether you define a
primary key field yourself, or let
Django supply one for you, each model
will have a property called pk. It
behaves like a normal attribute on the
model, but is actually an alias for
whichever attribute is the primary key
field for the model. You can read and
set this value, just as you would for
any other attribute, and it will
update the correct field in the model.
The ID will be automatically updated in your model, so immediately after your n.save() line you can read n.id and it will be populated.
Remove save() and get pk directly:
n = MyData.objects.create(record_title=title, record_content=content)
n.pk
If someone reading this question and after check the other answers still having problems accessing the id after the creation of the object.
Be sure you don't define id as an Integer in your model. If you decide to declare it anyways, use Autofield but you don't need to, It is for free with models.Model
#No
class TestModel(models.Model):
id = models.IntegerField(primary_key=True)
something...
#Ok
class TestModel(models.Model):
id = models.AutoField(primary_key=True)
something...
#Ok
class TestModel(models.Model):
something...
if you do define id as Integer, TestModel.objects.create( or with save() will return None.
I had a similar issue with accessing the id. In Django 3.0.5, this is how I accessed the id. Using your example and variable name, see below:
instance = n.save()
# return the id
instance[0].id
The variable 'instance' above is a list. Accessing id in the methods described above returns an AttributeError ("object has no attribute 'id'") in Django 3.
This answer applies when using modelformset_factory. This is true when creating a Form class from a Django model as described in the Django docs
I am writing a action in django.I want to now about the rows which are updated by the action or say id field of the row.I want to make a log of all the actions.
I am having a field status which has 3 values :'activate','pending','reject'.I have made action for changing the status to activate.when i perform the action i want to have the log of rows updated so i need some value which can be stored in log such as id coresponding to that row
As far as i can understand you want make an admin log-entry for the object you update using your custom action. I actually did something like that, purely as django does it. As its your custom action you can add this piece of code.
Edit: Call this function after your action finishes, or rather i should say, after you change the status and save the object.
def log_it(request, object, change_message):
"""
Log this activity
"""
from django.contrib.admin.models import LogEntry
from django.contrib.contenttypes.models import ContentType
LogEntry.objects.log_action(
user_id = request.user.id,
content_type_id = ContentType.objects.get_for_model(object).pk,
object_id = object.pk,
object_repr = change_message, # Message you want to show in admin action list
change_message = change_message, # I used same
action_flag = 4
)
# call it after you save your object
log_it(request, status_obj, "Status %s activated" % status_obj.pk)
You can always get which object you updated by fetching LogEntry object
log_entry = LogEntry.objects.filter(action_flag=4)[:1]
log_entry[0].get_admin_url()
Hope this helps.
It is very easy!
Just make a loop of your queryset, then you can access each field of that row and store it where you want.
for e in queryset:
if (e.status != "pending"):
flag = False