Making a field "blank=False" in production - django

I have deployed my Django website but just now realized that I didn't make one of the fields compulsory. For the field it is currently,
blank=True, null=True
Now if I go ahead and change it to
blank=False
will there be any effect on the database and already existing data in it?

No. blank is enforced solely at the application level.

As discussed at https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.Field.blank :
"blank" is about the form validation; you can change this at any time without affecting
your database.
"null" is about the storage in the database, not about form validation
So if you change from "blank=True, null=True" to "blank=False", you'll still be able to store null values in the table--but you won't have a way to actually get those null values into the database, since your forms will require input.
This might be exactly what you want (and no db migration would be needed).
If you want to get existing null values out of your database, update your data, then set both blank and null to False. At that point, though, you'd need to do a database migration (via South or by just directly changing your database with an ALTER TABLE ... ALTER command).

Related

Django create or update model only if field not equal to certain value

We have a potential race condition where multiple users can try to create or update a record. Wondering if there's a way to create a column, than when set (to say true), then an exception will be thrown, preventing the update.
The underlying database is postgres, but since we're using django to wrap it, we would like to limit ourselves to something django offers, and not mess with very specific database settings. Thanks!

Does Django support setting the beginning value for an id column?

I have seen several questions and answers on SO, most were three years old or older and I looked at the Django documentation (hoping I didn't miss it). I have to have a 9+ digit number for an id. Most responses were to do this at the database. I am guessing that means to create the model in Django and then go back to the database and change the id column Django created with a new starting/next value attribute on the column.
If not how can I create a database table from Django, Code First, that allows me to create a table with an id column that starts at 100000000? And, it be done with the stock model object methods in Django. I don't really want to do a special hack. If that is the case, I can go the database and fix the column. I was trying to adhere to the Code First ideas of Django (though I prefer database first, and am afraid using inspectdb will make a mess.)
Edit: I didn't want to use UUID. I believe BigAutoField is best.
You should be able to do this in two steps:
1 - Specify your primary key explicitly using primary_key=TRUE in your model definition. See the Django docs for more info. You can then specify BigAutoField or whatever other type you want for the primary key.
2A - If you're populating the database up front, just set pk: 100000000 in your fixture.
OR
2B - If you're not populating the database up front, use Django Model Migration Operations RunSQL as detailed here. For your SQL use ALTER TABLE tableName AUTO_INCREMENT=100000000.

How to revert changes, specifically deletions, with django-simple-history

We have django-simple-history set up for our models. Recently a whole bunch of models were mysteriously deleted. This was noticed a few days after the fact, so it would be nice to avoid a full DB backup restore since that would wipe manual changes that happened after the fact.
I cannot find any way to easily restore an model instance, specifically a deleted one. I can query the Historical version of the model and find everything that was deleted. With that I can also observe that all of them had deletions as their last change. I can use the instance property on history - 1 to get the state before deletion but if I try to save that it errors since the model instance was deleted and doesn't exist anymore.
So basically, what is the cleanest way to restore a deleted model instance if I have the Historical record of it with django-simple-history? I would like to retain the history if possible, so I am looking into any solution before totally recreating the objects.
As I understand, the question, it is about restoring a deleted model instance, not the class itself. So Kal's answer does not help here.
To restore a deleted instance, simple history can NOT be used. According to the documentation, simple history can only restore model instances that are still existing.
Since you have a full backup of the database, you can import this database into the django environment, load the old model instance from this backup database and save it to the production database (choose the database in django shell with "using"). See this post.
The best way to avoid such situations is to use the app "reversion". With this django-app, you actually can restore deleted instances. See the documentation.
Do you mean that your model, not just the instances, has been completely deleted? If that’s the case, it probably means some migration removed it.
You could try reverting the migration then restore from the Historical record.
The previous version of your model is stored in the _HISTORICAL<model_name> table. You could do a simple sql insert/select query to copy the data from that table back into the original table. Something like the below would work, but check the correct sql syntax for your database.
insert into app_mymodel (col_a, col_b)
select col_a, col_b from app_HISTORICALmymodel
where id in (1,2,3...)
If model using django-simple-history then,
Data can be restored from the historical model.
We need to filter from the historical model. for eg with some keyword or in some date range in which period the data got deleted accidentally.
For eg. the Model Name is Car, then by default django-simple-history creates a historical model as HistoricalCar.
historical_data = HistoricalCar.objects.filter(history_type='-')
for each in historical_data:
instance = each.instance # This return instance of car.
instance.pk = None # Create New Instance
instance.save()

Manually adding data causes IntegrityError

I have two Django sites: one for development and one for production. Every once in a while, the data from the development database needs to be transferred to the production database or the other way around. I use postgresql.
This works fine: I empty the tables from the database I want to copy to, I generate sql from the applicable tables, and insert the data in the emptied tables. So far, so good.
But when I enter data into the database via the admin interface, Django raises IntegrityErrors, because appname_modelname_pkey already exists.
I think this is because the admin interface wants to add data with id 1, but that's already an imported record. Django isn't aware that id '1' is already taken.
How do I fix this problem? I want Django to increment the id (like SQL auto_increment would do), no matter what data is already stored.
Any help is appreciated!
If you're using postgres on both sides, then the sequence associated with the primary keys are going to be different.
For example, suppose you're moving production data to development. Also, suppose the sequence value in production is 20 and the sequence in development is 10. Then the first new item you add in development will have an id of 11. That id (probably) already exists in the production data, so you get an integrity error.
When you restore tables from a dump, you can reset the sequences by dropping and recreating the existing tables before you restore.
(Or, you can probably use the ALTER SEQUENCE command to sync up the sequences. However, I'm not familiar enough with postgres to say whether that's the right way to do it.)

Changing a field's nullable attribute in Django after the model is committed?

So I have a model that has a field, which originally defaulted to not allow nulls. I want to change it to allow nulls, but syncdb doesn't make the change. Is it as simple as changing it in the database and reflecting it in the models.py file just for the next time its run against a new database?
To answer the question: Yes it should work if you change it in the model and in your database manually, otherwise check out django-south or django-evolution to help you evolving your database scheme!
another possibility would be to dump your current db as a fixture, drop the tables, run syncdb and reload the fixtures (guess this would work for changing the null setting, but not for bigger changes).
You can save yourself a whole world of hurt by using some kind of database migration app with Django. Then you can chop and change model fields and their attributes basically as much as you please.
I highly recommend South for its features and friendliness