Difference between null=True and on_delete=models.SET_NULL django - python

I have a field
owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
What is the difference between these two attributes on model field ?

null=True means owner field can be null in the database which means you can make an object of your model that has no owner.
on_delete=models.SET_NULL
means if the owner of an existing object got deleted set this field for existing object to null.

null=True means that the field could be empty or null, but on_delete=models.SET_NULL is being used to take of the presence of the owner of the field, that it should be set to NULL if the owner is not present.
class Product(models.Model):
name = models.CharField(max_length = 50)
category = models.ForeignKey(Category, on_delete=models.SET_NULL)

SET_NULL argument of the ForeignKey on_delete option is only available to you when you have set the null option on the ForeignKey field to True.
After use null=True and on_delete=models.SET_NULL, when a deletion happens to the referenced object then the value of the referencing object will be updated as NULL. So a NULL value will be placed for the referencing object.

Related

Delete 2 model different objects which reference each other as foreign keys

We have two Django models:
class Project(models.Model):
project_title = models.CharField(max_length=30)
owner = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING)
class User(models.Model):
usernmae = models.CharField(max_length=50)
active_project = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING, related_name='current_project')
I have a user with object (with id say 692). And this user created a project with id=12345, therefore these owner field will get have this particular referenced.
I want to delete that user. But it shows error that
delete on table "app_user" violates foreign key constraint
This is expected as on_delete=models.DO_NOTHING, was set. One way I found out was using on_delete=models.CASCADE.
Question: How should I go about deleting the user (692) without changing the model definition(having to re-run migration)?
Doing it manually by deleting the project first, leads to the same foreign-key error, as owner field is User object.
How to handle this mutual foreign key relationship while deleting, as deleting any one of those two throws the foreign-key exception?
Update
Some correction in the model definition username is the field name instead of usernmae (typo). And the foreignkey for project is Project not the User model.
class Project(models.Model):
project_title = models.CharField(max_length=30)
owner = models.ForeignKey(User, null=True, on_delete=models.DO_NOTHING)
class User(models.Model):
username = models.CharField(max_length=50)
active_project = models.ForeignKey(Project, null=True, on_delete=models.DO_NOTHING, related_name='current_project')
IF you really don't want to make a migration (any specific reason?) and if you are ok with doing this manually this time. Then you have two options:
Go into the admin panel and manually change the User field in the project instance to a different user or to NULL. Now you should be able to delete the User instance since it's not referred anymore into the project.
If that worked, you can then delete the project instane as well.
Curios if this will work, let me know!

Bidirectional OneToOne relation - Django

I have two models (Slot, Appointment). On the appointment one, I have defined a OneToOne relation with the slot model, so good so far; thanks to the RelatedManager I can access the appointment from the slot object but this's done at python level and I need (for some future changes) appointment_id column to be created on the Slot table.
class Slot(models.Model):
start_at = models.DateTimeField()
end_at = models.DateTimeField()
duration = DateTimeRangeField(
null=True,
blank=True
)
# Bidirectional
appointment = models.OneToOneField(
"appointments.Appointment",
on_delete=models.SET_NULL,
related_name="slot",
blank=True,
null=True
)
class Appointment(models.Model):
slot = models.OneToOneField(
Slot,
on_delete=models.SET_NULL,
related_name="appointment",
null=True,
blank=True,
)
The code above will raise some errors when trying to create the migrations like:
appointments.Appointment.slot: (fields.E302) Reverse accessor for 'Appointment.slot' clashes with field name 'Slot.appointment'.
HINT: Rename field 'Slot.appointment', or add/change a related_name argument to the definition for field 'Appointment.slot'.
Basically, due to the python part of the ORM, you can't define the same field on both models.
Any idea of how to achieve this. I guess I will have to overwrite some parts of the RelatedManager. I could make this throw SQL but then it won't be clear on the code level.

Deleting nullable field is deleting related objects

I have a Tournament model with related Standings:
class Tournament(models.Model):
standings = models.ForeignKey('Standings', blank=True, null=True)
I just did the following:
standings = Standings.objects.get(pk=pk)
standings.delete()
And it deleted the related tournament as well. This should not have happened, since standings is a nullable field.
Why did it happen and what can I do to prevent this from happening again?
Django 1.8 defaults to CASCADE:
When an object referenced by a ForeignKey is deleted, Django by default emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey.
To change that behavior, you should add the on_delete argument (mandatory as of Django 2.x) as follows:
standings = models.ForeignKey(
'Standings', blank=True, null=True, on_delete=models.SET_NULL)

Django IntegrityError while updating a record

I have a model with double columns as primary key. I do a filter on it and get the records I want, change a field and save it. As I know save will update the record and does not create a new instance of the model in db. so It should be all okay but I'm stuck with an integrityError Duplicate entry '10-2' for key 'PRIMARY' when I try to save the record
Here is the code snippet:
analysis = AnalysisResult.objects.filter(request=req.request_id)
for anal in analysis:
anal.analysisresult_path = some_string
anal.save() #this line is where the error occurs
And here is my model:
class AnalysisResult(models.Model):
analysisresult_path = models.CharField(db_column='analysisResult_path', max_length=255, blank=True,
null=True) # Field name made lowercase.
detectionresult_path = models.CharField(db_column='detectionResult_path', max_length=255, blank=True,
null=True) # Field name made lowercase.
targetcode = models.ForeignKey('TagetCode', models.DO_NOTHING,
db_column='targetCode_id') # Field name made lowercase.
request = models.ForeignKey('Request', models.DO_NOTHING, primary_key=True)
class Meta:
managed = False
db_table = 'analysis_result'
unique_together = (('request', 'targetcode'),)
Ah, yes, welcome to one of django's strongest opinions: all tables/models should have a single primary key field that can be used for updates. If you don't have this, you must write raw SQL for the update since save will assume that there is an implicit primary key field called id to use in the where clause.

django delete self and not a self referential entity

I have the following sample models:
class Note(models.Model):
text = models.TextField()
author = models.OneToOneField(User)
date_created = models.DateField(auto_now_add=True)
similar_note = models.ForeignKey("self", related_name='similar_note', null=True, blank=True)
Say there are two notes Winner and Loser.
Loser has a field similar_note that points to Winner Note.
When I delete any of the two, both gets deleted, how do I prevent this from happening?
I have tried doing the same from the django admin interface as well, it happens from there as well.
PS: I am using django1.2, please don't advice to upgrade, there are way too many constraints.
As mentioned here:
When Django deletes an object, by default it emulates the behavior of
the SQL constraint ON DELETE CASCADE -- in other words, any objects
which had foreign keys pointing at the object to be deleted will be
deleted along with it.
This cascade behavior is customizable via the on_delete argument to
the ForeignKey
Please check the on_delete parameter for model field:
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)

Categories