Allow null in foreign key to user. Django - django

I have this model
class Vacancy(models.Model):
user = models.ForeignKey(User, null=True, blank=True, default = None)
name = models.CharField(max_length=64)
When in admin i try to creat a vacancy without a user. And it throws an error " club_vacancy.user_id may not be NULL".
Am i doing something wrong?

club_vacancy.user_id may not be NULL
Looks very much like an error from your database, rather than from Django.
It seems most likely that you added null=True after running manage.py syncdb. You'll need to modify your database schema to allow null values in that column.

Aside from South, another option is to use django evolution for schema changes.
http://code.google.com/p/django-evolution/
Install it before making db changes. Then run
python manage.py evolve --hint --execute
Make sure that if you add a new field, you allow nulls (null=True) or else evolve will give you an error message.

you need to reset you database table (since just syncdb does not update fields that are alredy created with null=False)
./manage.py reset your_app
OR if there is some data that you do not want to loose use SQL commands to remove NOT NULL flag

Related

How to add new field to existing django model postgres

Let's suppose I have the following model:
class Test(models.Model):
field_one = models.CharField(max_length=80)
Now, we have created 2-3 Model objects with field_one field.
p1 = Test(field_one="Object1")
p1.save()
p2 = Test(field_one="Object2")
p2.save()
Later, I realised that I need to add another field field_two to my Test model.
class Test(models.Model):
field_one = models.CharField(max_length=80)
field_two = models.IntegerField(default=3)
Now, Doing makemigrations & migrate
and running server.
which will prompt the following error
django.db.utils.ProgrammingError: column mainapp_test.field_two does not exist
I understand that this error occurs due to my 2 existing objects in PostGresDB doesn't have field_two column.
Is there any effective way to add field_two column to my existing objects with some default value? or How to solve this problem?
Django Version: 2.0
Django ORM DB: PostGresql
When you add a field to an existing model, you must either provide a default value in the code, or set it to null/blank = True, or provide a one-off default while migrating.
Since you are providing a default in the code, the migration should run without issues. At least from experience, I've added several BooleanFields with default=False to my existing model with thousands of entries, and I never got a ProgrammingError.
Have you tried shutting down the Postgres backend before running makemigrations and migrate? I would think Django would do this but that's the only thing I can think of. Also, obviously, shut down the Django server if it's still running.

Change unique=True to unique=False from my model field

I have one field in my model with like this name = models.CharField(max_length=100, unique=True) but now that table/model have a lot of data and need to change the True to False but without having to drop the table and créate it again, How can I do that?
Generate the new migration using:
python manage.py makemigrations
The above will detect changes to your model and generate a migration class but no execute any sql yet.
To generate/apply the sql to the db:
python manage.py migrate
If you want to see the sql that will be executed before updating the db do this before migrate:
python sqlmigrate {app_label} {migration_module}
EDIT: The above will rename your table with suffix __old, create a new table and insert the data from the old to the new one, and then drop the original table. So not sure if this is what you want..
Another option would be to use plain sql to achieve what you want:
ALTER TABLE table_name DROP CONSTRAINT constraint_name;
But remember, in order keep your migrations updated for new runs, find the migration class that declares your field as unique and change unique=True to unique=False. If any other servers need to be updated you can run the drop constraint command there too so everything is in sync.
Just change the value to False in the model and then makemigrations and migrate. This will update all items in the DB to the new value. This is if you are using the newer version with South and not using syncdb.

Django: how to add a field to an existing model without much rewrite of the code

our website lists local city events. It's Django-based so there's a lot of code related to 'event' model. Until now, we work only in one city and so all the events mean to be local.
Now we need to extend the website to another city. This means 'event' model gets a new attribute 'city', and our middleware will set a global value CurrentCity based on geoip.
We need to extend 'event' model so it would filter only records where 'city' attribute equals to CurrentCity value. There is too much code in different views and models working with the 'event' so we can't update each module.
Is there any single place to patch that would make our 'event' model aware of the CurrentCity value?
Depending a lot in your structure and Django version I think you have 2 options.
South
The best one is to install the application "South". I don't know if you already know it or you're using it but I think it should be your first option.
In case you're not using it, you should do this steps:
Install with pip install South
Create your first migration with:
python manage.py schemamigration YOURAPPNAME --initial
You need to fake this migration, because you have already the fullfilled database so you need to do:
python manage.py migrate YOURAPPNAME --fake
Add the new field to the model Event in the file models.py
Generate the new migration to make South create the new field in your database with:
python manage.py schemamigration YOURAPPNAME --auto
Final step, execute the migration created with:
python manage.py migrate YOURAPPNAME
Tips
--initial for the first migration --auto for the rest
The initial migration is faked because you already have tables in your database, if you try to migrate without the fake it will return error "Table already exists"
New Model City
Another option, in case you can't modify your actual Model, or maybe if it's too messy, another option is to generate an externa Model City like this:
class City(models.Model):
event_foreign = models.ForeignKey(Event)
event_many = models.ManyToManyField(Event, blank=True, null=True)
name = models.CharField....
postal_code = models.CharField....
# etc...
I don't know wich is optimal for you, a Foreign Key or a ManyToMany, depends if a City can have more than 1 Event or no, it's your choice.
When you have a model like this you can access from this City model to the Event (because of the ForeignKEy or ManyToMany) but this relation goes also in the other direction, if you have an Event you can get the City/cities related to it I'm gonna show two examples:
Example 1 using Foreign Key
city = City.objects.get(id=1)
city.event # Returns event
event = Event.objects.get(id=1)
event.city # Returns city
Example 2 using Many to Many
city = City.objects.get(id=1)
city.event.all() # Returns a list of events
event = Event.objects.get(id=1)
event.city_set.all() # Returns a list of cities

django model integrity error

so before number field was uncommented i use to get this error Programmingerror: exampeuser.number has no relation to blahblah
class ExampleUser(models.Model):
#number = models.CharField(max_length=15)
phoneID = models.CharField(max_length=30)
verified = models.BooleanField(default=False)
verificationNumber = models.CharField(max_length=5)
now i comment it and syncdb and everything, it gives me an IntegrityError: null value in column "userPhone" violates not-null constraint when i try to save it in the admin website.
userPhone was a field i used a while back and changed it to number.
those errors occur everytime i try to save a model object in the admin site.
it seems that my model is still ineteracting with old changes i made previously. I am new to django.
i also have south on my installed_app and i have not yet migrated or made any configs with it. please help , this is very fustrating
It seems like you're trying to migrate your model, for example, you write a model, then you sync it, then you modify it, change some data types, delete some attributes and add some other and then sync it again.
Django does not support this by default, you need to use South(1) a library that migrates your models through this changes.
Unless you're using django 1.6, in this version they added migrations, here is the documentation. https://docs.djangoproject.com/en/dev/topics/migrations/
Whenever you need to sync a modified model, you need to do it with a migration, not with syncdb.
(1) http://south.aeracode.org/

How to rename a foreign key in django-south, the right way

I need to rename a foreign key in my django model using south migrations. I thought I was in luck when I found this thread How to rename a foreignkey field with South? However, all the methods described there fail, with various errors. Does someone actually know the proper way to do this?
I want to rename SomeModel.registered_to = models.ForeignKey( User ) to SomeModel.owner = models.ForeignKey( User ) and keep the relation between User and owner Any help would be appreciated!
Change the field name and run python manage.py schemamigration --auto yourapp. South will add code to drop the column and add a new one. Letting South generate the migration ensures that the ORM is frozen properly, so all you need to do is just change the actual migration to rename instead of drop and add. Just remove those lines from the forwards and backwards migration to and replace them with:
def forwards(self, orm):
db.rename_column('yourapp_yourmodel', 'registered_to_id', 'owner_id')
def backwards(self, orm):
db.rename_column('yourapp_yourmodel', 'owner_id', 'registered_to_id')
Save, and then migrate your app.