Django not setting MySQL ON DELETE = CASCADE - django

I'm using Django 1.3 with the MySQL 5.5 database backend. My assumption was that Django by default emulates the ON DELETE CASCADE effect for related objects when building the database via syncdb. However, inspecting the database reveals that the ON DELETE property is in fact set to "RESTRICT". Is this a bug? As I'm unable to delete related records I keep getting the IntegrityError message in the djang-admin when deleting an object that has a related object.
Thanks

Django emulates ON DELETE CASCADE in Python -- that's why is doesnt need it set on the database tables. In fact, setting RESTRICT might even make sense, since it means that you can't accidentally delete any related objects without being warned about it in the admin.
In your case, it seems like you may have foreign key constraints set up that Django doesn't know about -- or possibly you are trying to delete through raw SQL; I can't tell from your question.
If the issue is that you can't delete from the admin, or from the ORM, then you need to make sure that your models are defined correctly. django will take care of collecting the related objects and performing the cascade itself.
If the issue is that deletes don't work from raw SQL, then you will either need to manually delete the related objects first, or relax the SQL constraint -- in that case, changing it to cascade may be the right solution.

It would seem that Django 1.3.1 for some reason fails to apply the ON DELETE CASCADE property to the table. It could possibly have something to do with the MySQL-python 1.2.3 interface running on Windows. The only other way to resolve this issue is via custom SQL.

Django does cascade by default. I'm not really sure why you're getting an ON DELETE RESTRICT. Django 1.3 does let you select alternate ON DELETE procedures (using the on_delete kwarg when defining a field), and it's possible that if you inherited the codebase, someone might have done that previously and then removed it from the code, but neglected to update the database.
I would suggest altering the column manually to set it back to ON DELETE CASCADE. And simply move on from there. Like I said, this is something that the developer has to tell Django not to do; it cascades by default.

Related

Ignore invalid foreign for django migrations?

I'm migrating an application from an old DB system to django. I've imported a bunch of legacy data. I used a script to convert the table schemas from the old system into Django models, as it had a lots of tables. Then I used another script to write the content of the old db into Django fixtures, which I then imported. That all worked fine, the data is served in the views etc.
However, I now noticed that some ForeignKey in the old system were not properly identified as FK and were simply put in as Char/Int fields into the djando models. So I updated a field from IntegerField to ForeignKey, but that being legacy data I had the following issue:
django.db.utils.IntegrityError: The row in table 'pickings_detpick' with primary key '17170' has an invalid foreign key: pickings_detpick.fk_ent_id contains a value '30223' that does not have a corresponding value in pickings_entpick.id.
So basically, there are a number of (unsure how many yet) foreign key references that point to objects that actually do not exist in the source data (for whatever reason, I don't know the hold system much).
Is there a way that I can simply tell Django to ignore those & set them as null or something? Or do I actually have to comb thru the data & fix them?
Not a long term fix, but on the narrow question to let the constraint slide the db_constraint attribute of the ForeignKey field would work (set it to False).
Not a good idea in production, and the underlying data still needs to be fixed.
Use
db_constraint=False,on_delete=models.SET_NULL,null=True,blank=True
Also if it still gives an error delete the last 1 or few migrations then do makemigrations and migrate it solved my problem.

Django on_delete=CASCADE not working, can't delete parent row using raw SQL [duplicate]

I'm using Django 1.3 with the MySQL 5.5 database backend. My assumption was that Django by default emulates the ON DELETE CASCADE effect for related objects when building the database via syncdb. However, inspecting the database reveals that the ON DELETE property is in fact set to "RESTRICT". Is this a bug? As I'm unable to delete related records I keep getting the IntegrityError message in the djang-admin when deleting an object that has a related object.
Thanks
Django emulates ON DELETE CASCADE in Python -- that's why is doesnt need it set on the database tables. In fact, setting RESTRICT might even make sense, since it means that you can't accidentally delete any related objects without being warned about it in the admin.
In your case, it seems like you may have foreign key constraints set up that Django doesn't know about -- or possibly you are trying to delete through raw SQL; I can't tell from your question.
If the issue is that you can't delete from the admin, or from the ORM, then you need to make sure that your models are defined correctly. django will take care of collecting the related objects and performing the cascade itself.
If the issue is that deletes don't work from raw SQL, then you will either need to manually delete the related objects first, or relax the SQL constraint -- in that case, changing it to cascade may be the right solution.
It would seem that Django 1.3.1 for some reason fails to apply the ON DELETE CASCADE property to the table. It could possibly have something to do with the MySQL-python 1.2.3 interface running on Windows. The only other way to resolve this issue is via custom SQL.
Django does cascade by default. I'm not really sure why you're getting an ON DELETE RESTRICT. Django 1.3 does let you select alternate ON DELETE procedures (using the on_delete kwarg when defining a field), and it's possible that if you inherited the codebase, someone might have done that previously and then removed it from the code, but neglected to update the database.
I would suggest altering the column manually to set it back to ON DELETE CASCADE. And simply move on from there. Like I said, this is something that the developer has to tell Django not to do; it cascades by default.

How do I configure mongoDB indexes in django-nonrel without using Models?

I'm building a site using mongodb and django-nonrel. I've read in various places that for mongo, it's better to use straight pymongo than the django ORM. This jives with my experience as well -- django's ORM is awesome for relational databases, but for doesn't give you much that pymongo doesn't do already.
My problem is that I don't know how to set up the database tables (err... "collections") initially without using django's ORM. What do I need to do to cast off the shackles of models.py and syncdb, and just write the code myself?
Seems like somebody should have created a guide for this already, but I can't find one.
A little more detail:
Right now, I'm building models and running syncdb to configure the DB. So far, django's ORM magic has made it work. But I need to do some slightly fancier stuff, like indexing on sub-elements, so I don't think the ORM is going to work for me anymore.
On top of that, I don't use models (other than auth_users and sessions) anywhere else in the project. The real schemas are defined elsewhere in json. I don't want to maintain the model classes when and the json schemas at the same time -- it's just bad practice.
Finally, I have a "loadfixtures" management command that I use to flush, syncdb, and load fixtures. It seems like this would be a very good place for the new ORM-replacing code to live, I just don't know what that code should look like....
With MongoDB you don't need an extra step to predeclare the schema to "set up" collections. The document-oriented nature of MongoDB actually does not enforce a strict schema; documents within a collection may have different fields as needed. It's a different concept to get used to, but the collection will be created as soon as you start saving data to it.
Indexes can be added using pymongo's ensureIndex on a collection.
Similar to the collection creation on data insertion, a collection will also be created if it does not exist when an index is added.
An article that should help you get started: Using MongoDB with Django.
If you're new to MongoDB, you also might want to try the short online tutorial.

Django -- add model to database without losing data

I have a simple Django website (just a form, really) which asks a few questions and saves the data in a SQL database using Model.save(). Pretty simple. I want to add a model to do page counting, though -- it'll just be a single object with a field that gets incremented each time the page's view function is called.
Now, I know little to nothing about SQL. I imagine this is not terribly difficult to do, but I would like to avoid losing or breaking all my data because of a slight misunderstanding of how the database works. So how can I go about doing this? I've heard of some third-party apps that will implement such functionality, but I'd like to do it myself just for learning purposes.
I don't understand why your existing data would be affected at all. You're talking about adding a completely new table to the database, which is supported within Django by simply running manage.py syncdb. The case where that doesn't work is when you're modifying existing tables, but you're not doing that here.
I must say though that learning and using South would be of benefit in any case. It's good practice to have a tool that can maintain your model tables.
(Plus, of course, you would never lose any data, because your database is backed up, right? Right?)
Since you're adding new model, you can just run syncdb and it will create new table for your model. If you were to change existing model, then you'd need to manually update database schema using "ALTER TABLE" statements or use South instead.

How can I easily mark records as deleted in Django models instead of actually deleting them?

Instead of deleting records in my Django application, I want to just mark them as "deleted" and have them hidden from my active queries. My main reason to do this is to give the user an undelete option in case they accidentally delete a record (these records may also be needed for certain backend audit tracking.)
There are a lot of foreign key relationships, so when I mark a record as deleted I'd have to "Cascade" this delete flag to those records as well. What tools, existing projects, or methods should I use to do this?
Warning: this is an old answer and it seems that the documentation is recommending not to do that now: https://docs.djangoproject.com/en/dev/topics/db/managers/#don-t-filter-away-any-results-in-this-type-of-manager-subclass
Django offers out of the box the exact mechanism you are looking for.
You can change the manager that is used for access through related objects. If you new custom manager filters the object on a boolean field, the object flagged inactive won't show up in your requests.
See here for more details :
http://docs.djangoproject.com/en/dev/topics/db/managers/#using-managers-for-related-object-access
Nice question, I've been wondering how to efficiently do this myself.
I am not sure if this will do the trick, but django-reversion seems to do what you want, although you probably want to examine to see how it achieves this goal, as there are some inefficient ways to do it.
Another thought would be to have the dreaded boolean flag on your Models and then creating a custom manager that automatically adds the filter in, although this wouldn't work for searches across different Models. Yet another solution suggested here is to have duplicate models of everything, which seems like overkill, but may work for you. The comments there also discuss different options.
I will add that for the most part I don't consider any of these solutions worth the hassle; I usually just suck it up and filter my searches on the boolean flag. It avoids many issues that can come up if you try to get too clever. It is a pain and not very DRY, of course. A reasonable solution would be a mixture of the Custom manager while being aware of its limitations if you try searching a related model through it.
I think using a boolean 'is_active' flag is fine - you don't need to cascade the flag to related entries at the db level, you just need to keep referring to the status of the parent. This is what happens with contrib.auth's User model, remember - marking a user as not is_active doesn't prompt django to go through related models and magically try to deactivate records, rather you just keep checking the is_active attribute of the user corresponding to the related item.
For instance if each user has many bookmarks, and you don't want an inactive user's bookmarks to be visible, just ensure that bookmark.user.is_active is true. There's unlikely to be a need for an is_active flag on the bookmark itself.
Here's a quick blog tutorial from Greg Allard from a couple of years ago, but I implemented it using Django 1.3 and it was great. I added methods to my objects named soft_delete, undelete, and hard_delete, which set self.deleted=True, self.deleted=False, and returned self.delete(), respectively.
A Django Model Manager for Soft Deleting Records and How to Customize the Django Admin
There are several packages which provide this functionality: https://www.djangopackages.com/grids/g/deletion/
I'm developing one https://github.com/meteozond/django-permanent/
It replaces default Manager and QuerySet delete methods to bring in logical deletion.
It completely shadows default Django delete methods with one exception - marks models which are inherited from PermanentModel instead of deletion, even if their deletion caused by relation.