How to delete a record in Django models? - python

I want to delete a particular record like:
delete from table_name where id = 1;
How can I do this in a django model?

There are a couple of ways:
To delete it directly:
SomeModel.objects.filter(id=id).delete()
To delete it from an instance:
instance = SomeModel.objects.get(id=id)
instance.delete()

MyModel.objects.get(pk=1).delete()
this will raise exception if the object with specified primary key doesn't exist because at first it tries to retrieve the specified object.
MyModel.objects.filter(pk=1).delete()
this wont raise exception if the object with specified primary key doesn't exist and it directly produces the query
DELETE FROM my_models where id=1

if you want to delete one instance then write the code
entry= Account.objects.get(id= 5)
entry.delete()
if you want to delete all instance then write the code
entries= Account.objects.all()
entries.delete()

If you want to delete one item
wishlist = Wishlist.objects.get(id = 20)
wishlist.delete()
If you want to delete all items in Wishlist for example
Wishlist.objects.all().delete()

You can also use get_object_or_404(), rather than directly using get() as while using get() we explicitly raise the error of 404.
But, while using get_object_or_404 it is automatically done.
get_object_or_404 According to 4.0 docs, Calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.
Use it like:
For bulk deletion:
AnyModel.objects.filter(id=id).delete()
For deleting single instance, use get_object_or_404() instead of get() in the following way:
instance=get_object_or_404(anyModel,id=id)
instance.delete()
If, not found raises 404 automatically.

Extending the top voted answer by wolph
Note that you should pass request as a parameter to your delete function in your views. An example would be like:
from django.shortcuts import redirect
def delete(request, id):
YourModelName.objects.filter(id=id).delete()
return redirect('url_name')

The delete() method is used to delete model instances from a database.This method immediately deletes the object. this method returns the number of object deleted.
Example:
For deleting one record:
data_to_be_deleted = Modelname.objects.get(fieldname = value)
data_to_be_deleted.delete()
As get method returns a single object from queryset only single record will be deleted.If value supplied doesn't exist this will throw an error.If there are multilpe records in table for same value then also it will throw an error so good practice is to use a single unique value while using get.
For deleting multiple record according to a condition:
For condition based deletion filter method is used on queryset and then delete is called.
data_to_be_deleted = Modelname.objects.filter(fieldname = value)
data_to_be_deleted.delete()
For deleting all records:
For deletion of all model instances/records from database table you need to call delete method on all
data_to_be_deleted = Modelname.objects.all()
data_to_be_deleted.delete()
Note: code can be written in single line as Modelname.objects.all().delete(), but for clear understanding, I have used multiple lines.

It is as simple as calling the following.
SomeModel.objects.get(pk=1).delete()
# Or
SomeModel.objects.filter(pk=1).delete()
# SQL equivalent
# delete from table_name where id = 1;
In case you want to remove multiple records based on id,
use the __in query lookup
SomeModel.objects.fitler(pk__in=[1,2,3,4,5,...]).delete()
# SQL equivalent
# delete from table_name where id in (1,2,4,5,...);
In case you want to delete all records, use .all() to retrieve all queries,
then .delete().
SomeModel.objects.all().delete()
# SQL equivalent
# delete from table_name;

The way I do it:
instance = SomeModel.objects.get(id=1)
instance.delete()
For me it looks easy to understand, that's why I use this approach.

you can delete the objects directly from the admin panel or else there is also an option to delete specific or selected id from an interactive shell by typing in python3 manage.py shell (python3 in Linux).
If you want the user to delete the objects through the browser (with provided visual interface) e.g. of an employee whose ID is 6 from the database, we can achieve this with the following code,
emp = employee.objects.get(id=6).delete()
THIS WILL DELETE THE EMPLOYEE WITH THE ID is 6.
If you wish to delete the all of the employees exist in the DB instead of get(), specify all() as follows:
employee.objects.all().delete()

Related

Model save update only specific fields

I'm trying to write a webservice which performs inserts or updates.
The request is a post with headers,value which contains table name, column name and the value to be set for each column, I'm parsing the request headers and forming a parameter dict
def handel_request(request): if request.method == "POST":
param_dict = formParmDict(request)
##if insert param_dict["Model"] is {'pk':1,'field1':100,'field2':200}
##if update param_dict["Model"] is {'pk':1,'field1':100}
Model(**param_dict["Model"]).save() ## if update then sets field2 to null
return HttpResponse()
else:
return HttpResponseBadRequest()
This works fine while the .save() performs an insert.
In case of update ie if param_dict["Model"] contains {pk:1, field1:somevalue} to be updated then it sets the rest of the fields other than the ones specified in param_dict["Model"] to null. why is that? am I doing something wrong? isn't save suppose to update only the fields specified?
This is not how you're supposed to update.
Model(**param_dict["Model"]).save()
You're creating a new instance with the same id. Instead, you should get the instance, and then update it appropriately.
m = Model.objects.get(id=param_dict['id'])
m.field = param_dict['some_field']
m.save()
Or, you can use the Manager update method:
Model.objects.filter(id=param_dict['id']).update(**param_dict['Model'])
There's also the get_or_create method if you're not sure whether or not the record already exists.
You can try using a REST framework, like tasty-pie or django-rest-framework, which might alleviate some problems you're having.
Edit:
A brief summary about how save works in django. This is what I meant about whether or not an INSERT or an UPDATE is happening. Unless your post_data dict contains empty values for all the fields, read the documentation on how save works for a more thorough understanding of how django works.
So, what is happening in your case is this:
dict = {'id': 1, 'field1': 'my_value'}
m = Model(**dict)
m.id # 1
m.field1 # my_value
m.field2 # None (because you haven't set it, it defaults to None
m.save() # UPDATEs the existing instance with id 1 with ALL of the values of `m`
So, you're saving an instance that contains None values. That's why I'm suggesting you do a get, so that all the correct values are filled, before saving to the database.
Maybe you shoul use some function like this:
def insert_or_update(param_dict):
pk = param_dict.get('pk', None)
if pk:
Model.objects.filter(pk=pk).update(**param_dict)
else:
Model(**param_dict)
Model.save()

How to update() a single model instance retrieved by get() on Django ORM?

I have a function which currently calls Models.object.get(), which returns either 0 or 1 model objects:
if it returns 0, I create a new model instance in the except DoesNotExist clause of the function.
Otherwise, I would like to update the fields in the pre-existing
instance, without creating a new one.
I was originally attempting to
call .update() on the instance which was found, but .update()
seems to be only callable on a QuerySets. How do I get around
changing a dozen fields, without calling .filter() and comparing
the lengths to know if I have to create or update a pre-existing
instance?
With the advent of Django 1.7, there is now a new update_or_create QuerySet method, which should do exactly what you want. Just be careful of potential race conditions if uniqueness is not enforced at the database level.
Example from the documentation:
obj, created = Person.objects.update_or_create(
first_name='John', last_name='Lennon',
defaults={'first_name': 'Bob'},
)
The update_or_create method tries to fetch an object from database
based on the given kwargs. If a match is found, it updates the
fields passed in the defaults dictionary.
Pre-Django 1.7:
Change the model field values as appropriate, then call .save() to persist the changes:
try:
obj = Model.objects.get(field=value)
obj.field = new_value
obj.save()
except Model.DoesNotExist:
obj = Model.objects.create(field=new_value)
# do something else with obj if need be
if you want only to update model if exist (without create it):
Model.objects.filter(id = 223).update(field1 = 2)
mysql query:
UPDATE `model` SET `field1` = 2 WHERE `model`.`id` = 223
As of Django 1.5, there is an update_fields property on model save. eg:
obj.save(update_fields=['field1', 'field2', ...])
https://docs.djangoproject.com/en/dev/ref/models/instances/
I prefer this approach because it doesn't create an atomicity problem if you have multiple web app instances changing different parts of a model instance.
I don't know how good or bad this is, but you can try something like this:
try:
obj = Model.objects.get(id=some_id)
except Model.DoesNotExist:
obj = Model.objects.create()
obj.__dict__.update(your_fields_dict)
obj.save()
Here's a mixin that you can mix into any model class which gives each instance an update method:
class UpdateMixin(object):
def update(self, **kwargs):
if self._state.adding:
raise self.DoesNotExist
for field, value in kwargs.items():
setattr(self, field, value)
self.save(update_fields=kwargs.keys())
The self._state.adding check checks to see if the model is saved to the database, and if not, raises an error.
(Note: This update method is for when you want to update a model and you know the instance is already saved to the database, directly answering the original question. The built-in update_or_create method featured in Platinum Azure's answer already covers the other use-case.)
You would use it like this (after mixing this into your user model):
user = request.user
user.update(favorite_food="ramen")
Besides having a nicer API, another advantage to this approach is that it calls the pre_save and post_save hooks, while still avoiding atomicity issues if another process is updating the same model.
As #Nils mentionned, you can use the update_fields keyword argument of the save() method to manually specify the fields to update.
obj_instance = Model.objects.get(field=value)
obj_instance.field = new_value
obj_instance.field2 = new_value2
obj_instance.save(update_fields=['field', 'field2'])
The update_fields value should be a list of the fields to update as strings.
See https://docs.djangoproject.com/en/2.1/ref/models/instances/#specifying-which-fields-to-save
I am using the following code in such cases:
obj, created = Model.objects.get_or_create(id=some_id)
if not created:
resp= "It was created"
else:
resp= "OK"
obj.save()
update:
1 - individual instance :
get instance and update manually get() retrieve individual object
post = Post.objects.get(id=1)
post.title = "update title"
post.save()
2 - Set of instances :
use update() method that works only with queryset that what would be returned by filter() method
Post.objects.filter(author='ahmed').update(title='updated title for ahmed')

I came across a tricky trouble about django Queryset

Tricky code:
user = User.objects.filter(id=123)
user[0].last_name = 'foo'
user[0].save() # Cannot be saved.
id(user[0]) # 32131
id(user[0]) # 44232 ( different )
user cannot be saved in this way.
Normal code:
user = User.objects.filter(id=123)
if user:
user[0].last_name = 'foo'
user[0].save() # Saved successfully.
id(user[0]) # 32131
id(user[0]) # 32131 ( same )
So, what is the problem?
In first variant your user queryset isn't evaluated yet. So every time you write user[0] ORM makes independent query to DB. In second variation queryset is evalutaed and acts like normal Python list.
And BTW if you want just one row, use get:
user = User.objects.get(id=123)
when you index into a queryset, django fetches the data (or looks in its cache) and creates a model instance for you. as you discovered with id(), each call creates a new instance. so while you can set the properties on these qs[0].last_name = 'foo', the subsequent call to qs[0].save() creates a new instance (with the original last_name) and saves that
i'm guessing your particular issue has to do with when django caches query results. when you are just indexing into the qs, nothing gets cached, but your call if users causes the entire (original) qs to be evaluated, and thus cached. so in that case each call to [0] retrieves the same model instance
Saving is possible, but everytime you access user[0], you actually get it from the database so it's unchanged.
Indeed, when you slice a Queryset, Django issues a SELECT ... FROM ... OFFSET ... LIMIT ... query to your database.
A Queryset is not a list, so if you want to it to behave like a list, you need to evaluate it, to do so, call list() on it.
user = list(User.objects.filter(id=123))
In your second example, calling if user will actually evaluate the queryset (get it from the database into your python program), so you then work with your Queryset's internal cache.
Alternatively, you can use u = user[0], edit that and then save, which will work.
Finally, you should actually be calling Queryset.get, not filter here, since you're using the unique key.

Django debug error

I have the following in my model:
class info(models.Model):
add = models.CharField(max_length=255)
name = models.CharField(max_length=255)
An in the views when i say
info_l = info.objects.filter(id=1)
logging.debug(info_l.name)
i get an error saying name doesnt exist at debug statement.
'QuerySet' object has no attribute 'name'
1.How can this be resolved.
2.Also how to query for only one field instead of selecting all like select name from info.
1. Selecting Single Items
It looks like you're trying to get a single object. Using filter will return a QuerySet object (as is happening in your code), which behaves more like a list (and, as you've noticed, lacks the name attribute).
You have two options here. First, you can just grab the first element:
info_l = info.objects.filter(id=1)[0]
You could also use the objects.get method instead, which will return a single object (and raise an exception if it doesn't exist):
info_l = info.objects.get(id=1)
Django has some pretty good documentation on QuerySets, and it may be worth taking a look at it:
Docs on using filters
QuerySet reference
2. Retrieving Specific Fields
Django provides the defer and only methods, which will let you choose specific fields from the database, rather than fetching everything at once. These don't actually prevent the fields from being read; rather, it loads them lazily. defer is an "opt-in" mode, which lets you specify what fields should be lazily loaded. only is "out-out" -- you call it, and only the fields you pass will by eagerly loaded.
So in your example, you'd want to do something like this:
info_l = info.objects.filter(id=1).only('name')[0]
Though with a model as simple as the example you give, I wouldn't worry much at all about limiting fields.

Django - Getting last object created, simultaneous filters

Apologies, I am completely new to Django and Python.
I have 2 questions. First, how would I go about getting the last object created (or highest pk) in a list of objects? For example, I know that I could use the following to get the first object:
list = List.objects.all()[0]
Is there a way to get the length of List.objects? I've tried List.objects.length but to no avail.
Second, is it possible to create simultaneous filters or combine lists? Here is an example:
def findNumber(request, number)
phone_list = Numbers.objects.filter(cell=number)
I want something like the above, but more like:
def findNumber(request, number)
phone_list = Numbers.objects.filter(cell=number or home_phone=number)
What is the correct syntax, if any?
I haven't tried this yet, but I'd look at the latest() operator on QuerySets:
latest(field_name=None)
Returns the latest object in the
table, by date, using the field_name
provided as the date field.
This example returns the latest Entry
in the table, according to the
pub_date field:
Entry.objects.latest('pub_date')
If your model's Meta specifies
get_latest_by, you can leave off the
field_name argument to latest().
Django will use the field specified in
get_latest_by by default.
Like get(), latest() raises
DoesNotExist if an object doesn't
exist with the given parameters.
Note latest() exists purely for
convenience and readability.
And the model docs on get_latest_by:
get_latest_by
Options.get_latest_by
The name of a DateField or DateTimeField in the model. This specifies the default field to use in your model Manager's latest method.
Example:
get_latest_by = "order_date"
See the docs for latest() for more.
Edit: Wade has a good answer on Q() operator.
this works!
Model.objects.latest('field') - field can be id. that will be the latest id
Since Django 1.6 - last
last()
Works like first(), but returns the last object in the queryset.
Returns the last object matched by the queryset, or None if there is no matching object. If the QuerySet has no ordering defined, then the queryset is automatically ordered by the primary key.
list = List.objects.last() gives you the last object created
For the largest primary key, try this:
List.objects.order_by('-pk')[0]
Note that using pk works regardless of the actual name of the field defined as your primary key.
You can use the count() method on a query set the get the number of items.
list = List.objects.all()
list.count()
Arguments to filter are "AND"ed together. If you need to do OR filters look at Q objects.
http://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects
alternative for the latest object created:
List.objects.all()[List.objects.count()-1]
It is necessary to add an AssertionError for the case when there are no items in the list.
except AssertionError:
...
I am working on Django version is 1.4.22, neither last nor lastet is working.
My way to solve with minimum db loading is like:
latest = lambda model_objects, field : model_objects.values_list( field, flat = True ).order_by( "-" + field )[ 0 ]
latest_pk = latest( List.objects, "pk" )
This function accepts query_set as input.
You may bind this function dynamically by doing:
import types
List.objects.latest = types.MethodType( latest, List.objects )
Then you should be able to get the last object by this latest pk easily.
Try this:
InsertId= (TableName.objects.last()).id

Categories

Resources