Can a generic.GenericForeignKey() field be Null?
I am creating an object which tracks changes (Updates) regarding the creation, updating and deletion of other so called UUIDSyncable objects in the database.
This involves any object which extends the UUIDSyncable classes's save() and delete() methods being overriden, in such a way that it creates a new Update object recording the action (either insert, update or delete) and originally a models.CharField(max_length=64) field specifying the UUID pk of of the of UUIDSyncable objects.
At this point I wanted to update the implementation to use Django's generic.GenericForeignKey() field in stead of my single character field. This would enable be to access the object about which the update is being recorded in a much simpler way.
My problem arrises when you wish to delete an object and store that as an Update object, as you know Django preforms a cascade delete on the UUIDSyncable object being deleted, deleting all the previous Update records (which is not wanted).
When the UUIDSyncable object has been deleted in my original implementation, each Update object would still retain the UUID to inform external parties about its deletion. My first solution to emulate this was to set content_object = None just before deleting the object on all the Update objects, thus preventing the deletion cascade.
It seams that generic.GenericForeignKey() cannot be set to allow NULL values. Is there a way to do this, or if not how can a standard CharField holding a UUID primary key and a sperate CharField holding the model name be used in a similar fashion?
Answers
Perhaps you need to set null=True on the underlying content_type and object_id fields that make up the generic foreign key.
For the lazy/pragmatic:
class MyModel(models.Model): ...other fields... content_type = models.ForeignKey(ContentType, blank=True, null=True) object_id = models.PositiveIntegerField(blank=True, null=True) content_object = generic.GenericForeignKey('content_type', 'object_id')
What Daniel Roseman said is fine. Just make sure that you update your database to allow Null on those fields since you may have created the table without setting that.
Have you tried setting null=True on the GenericForeignKey? Generic foreign keys aren't a concept that is recognised by the low-level database application (i.e. MySQL, SQLite, etc.) so you should be able to specify that the field be null.
null=True on a database field in Django signifies that the database field representing that data is allowed to be empty, whereas blank=True tells the Django forms/model validation that the field is OK to be left empty by the user (or you, through the admin interface). Therefore, you might need to use both to achieve what you're after.