Restoring Django Model Field after accidental deletion - django

I have an existing events model in my django app that lists events. The events has a poster field that was using the models.ImageField for storing the related poster. The uploading of events was controlled from the admin only so no public uploading. The database had about 50 entries of events and things were working fine.
Since the images was getting heavier, I tried adding the sorl.thumnail to django. In my models.py file, I imported the ImageField from sorl.thumbnails and added it to the poster field.
When I ran makemigrations, it reported 'alter field poster' Then I ran migrate and on reloading, I do not see the Poster field in the admin.
Even the existing events have lost the poster field and the images cannot be shown in the templates too.
I have reverted the changes and run migrations again, but the poster field is still not visible. Is there any way to restore the model, and reconnect it with existing poster images?
I am using python 3.5 and django 1.11 Everything else works fine, this seems like a stupid mistake for the sake of getting a little more speed.
Will be grateful for any suggestions.
Here is what my Events model looks likeclass Events(models.Model):
title = models.CharField(max_length=200)
note = RichTextUploadingField()
category = models.CharField(max_length=1, choices=EVENT_TYPES, verbose_name=_('Event Category'))
date_from = models.DateTimeField(auto_now=False, blank=False)
date_to = models.DateTimeField(auto_now=False, blank=False)
poster = models.ImageField(upload_to='Programs/', blank=True, max_length=100, width_field=None, height_field=None)
video = models.URLField(max_length=500, blank=True)
capacity = models.SmallIntegerField(blank=True)
venue = GeopositionField(blank=True)
Admin.py is simply a register function
class EventAdmin(admin.ModelAdmin):
list_display = ('title', 'date', 'venue', 'category')
admin.site.register(Event, EventAdmin)

So, it doesn't seem likely to recover a lost field with the data intact. I am using MySQL for the project. So here is what I did after making all possible efforts to salvage it.
First I deleted all migrations in the applications/migrations folder. Then I changed the name of the field in the model. Then when I ran makemigrations, it showed me the the message 'Alter Field in Events' I proceeded with migrate after that.
It is good to tell you that I am on the Amazon EC2 instance running Ubuntu Server. So I had to reboot the instance and then reload the admin page. But the changes in the model admin were still not visible.
Then I had to stop the server, and start it after 5 minutes. This changed the public IP and on reloading the site, I saw the ImageUpload field in admin. The rest of the data was intact. Now I just have to re-upload the images in the respective events. This is not the proper solution that I was expecting, but this seems to be the best that could be done.

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.

Add more fields in the model and get the error "column ... does not exist"

I have a model like this :
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=100)
city= models.CharField(max_length=100)
, after a while, I add 2 more fields to this:
zip_code = models.CharField(max_length=20, blank=True, null=True)
state = models.CharField(max_length=50, blank=True, null=True)
, then I do the routine
python manage.py makemigrations
python manage.py migrate
But when I go to website/admin and check that model in Django Administration, I got the error "column user_profile.zip_code does not exist"
I search for the solution and some threads suggested to use South but then I learned that from django >= 1.7 we don't need to use South for migrations.
Please show me where I am wrong.
Thank you!
Check that you use the same settings when running migrate and the server.
If you are using django debug toolbar in your installed apps. Make sure to comment that, that gives the issue. If not, you can also check if your models are used by forms in another app or not. If they are its better to move the logic into views.
I commented out the debug toolbar, but that did not solve the problem.
I was adding a field to the user model. I have a utility that returns the default user. When I tried to migrate (adding the new field), that utility was getting called and was causing the error.
The solution that worked for me: in the utility that returns the default user, temporarily commenting out calls to the user table, and returning None for the default user. Migrate then ran successfully. Then of course I restored the code in the utility.
I found out that my utility was causing the problem by finding a line from my code in long list of exceptions displayed in the terminal.

Django ManyToMany Through not syncing or migrating

I have this model (truncated here for brevity):
class Meal(models.Model):
host = models.ForeignKey(User, related_name="cooking")
cost = models.IntegerField(default=1)
summary = models.CharField(max_length=1024, default="A good dinner")
diners = models.ManyToManyField(User, through='Attendance',
related_name="diners", blank=True)
When I sync it, the diners Field is completely ignored. It doesn't appear in the database and there is no error when running syncdb. It's as if it's not there. The User and Attendance tables are all fine.
I discovered this problem when trying to add this field with South, so I've tried that as an alternative too.
Any ideas?
Thanks
Did you already run syncdb fyrir Meal before you added the diners field?
Because syncdb will not alter existing tables as you can read here:
Django docs
Side note - I have not used south personally but I have used Django evolution while developing.
Edit:
After reading your comment I think I know what the problem is.
When using through with ManyToManyField Django doesn't add a field to that table, all the necessary information is in the attendance table.

Migrate data from one Model to another with Django South

I currently have a structure that needs to be rewritten in order to cope with Django-CMS
Currently the setup is as follows
class Video(models.Model):
#embed_code_or_url = models.CharField(max_length=2000)
permalink = models.URLField(verify_exists=True, unique=True, max_length=255, default="http://", validators=[validate_youtube_address])
thumbnail = models.CharField(max_length=500, blank=True, null=True)
# Data
title = models.CharField(max_length=255, blank=True)
...
class VideoPlugin(CMSPlugin):
video = models.ForeignKey(Video)
when I now transfer all my fields from Video to VideoPlugin, run my schemamigration, I'd also like to transfer ALL the info from Video to VideoPlugin when I run the migration.
Does anyone have an example on how this can be achieved?
Here is the beginnig of the migration to be run
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'VideoPlugin.permalink'
db.add_column('cmsplugin_videoplugin', 'permalink', self.gf('django.db.models.fields.URLField')(default='http://', unique=True, max_length=255), keep_default=False)
# Adding field 'VideoPlugin.thumbnail'
db.add_column('cmsplugin_videoplugin', 'thumbnail', self.gf('django.db.models.fields.CharField')(max_length=500, null=True, blank=True), keep_default=False)
# Adding field 'VideoPlugin.title'
db.add_column('cmsplugin_videoplugin', 'title', self.gf('django.db.models.fields.CharField')(default='', max_length=255, blank=True), keep_default=False)
...
Your help is much appreciated
You create a datamigration:
$ python manage.py datamigration yourapp name_of_this_migration
This freezes the models in your app. If another app(s) is/are involved in the migration, you'll need to add --freeze app1 --freeze app2, etc., to that line to include those in your migration as well.
This sets up the basic migration file structure for you, but the forwards and backwards migrations are empty. It's up to your to determine the logic that will migrate data from one to the other. But this works like anything else in Django, except you use the South ORM. For any model in your app in which this migration resides, you use orm.MyModel.objects for any other app that your added with the --freeze parameters, you use orm['someapp.SomeModel'].objects.
Other than that, you just get/filter/create, etc., the objects as normal moving the data from one to the other. Obviously, your forwards migration needs the logic that moves the data where you want it now, and your backwards migration should have the logic required to restore the data to where it was originally.
You can then migrate forwards and backwards in your dev environment to ensure it works properly. One important note: this is only for moving data around. DO NOT alter or delete any table structures in your datamigration. If you need to delete tables after the data has been moved. Create a schemamigration after the datamigration.

django many2many field make not required

I created a form based on a model. The model has a many2many field. I defined the field like this:
contacts = models.ManyToManyField(Contact, blank=True, null=True)
I`m wondering now why the generated form says that this field cannot be blank. I always get the error message "This field is required.", when i do not select a contact for the contacts field.
Whats`s wrong?
In your form declaration mark this field as required=False
class MyForm(forms.ModelForm):
contacts=forms.ModelMultipleChoiceField(queryset=Contact.objects.all(),required=False)
class Meta:
model=MyModel
Possibly you did syncdb before adding blank=True, null=True?
syncdb will only create tables if they don't exist in the database. Changes to models have to be done manually in the database directly with SQL or using a migration tool such as South.
Of course, if you are still in early development, it will be easier to drop the database and run syncdb again.
Your use of null=True is confusing here. A manyToMany field results in a 3rd table relating one model to another. e.g.
Business <-> Contact
If business.contacts is empty, no records are entered into this table. null=True would make me think you are intending for NULL records to be added to this table, which doesn't seem valid.
Typically you would leave both of these attributes off.