'Table doesn't exist' on django makemigrations - mysql

On a django 1.11 application which uses mysql , I have 3 apps and in one of them I have a 'Country' model:
class Country(models.Model):
countryId = models.AutoField(primary_key=True, db_column='country_id')
name = models.CharField(max_length=100)
code = models.CharField(max_length=3)
class Meta:
db_table = 'country'
Whaen I try to makemigrations I get this error:
django.db.utils.ProgrammingError: (1146, "Table 'dbname.country' doesn't exist")
If I run making migration for another app which is not related to this model and its database table using ./manage.py makemigrations another_app, I still get this error.

I've had this problem and it's because I was initializing a default value somewhere in a model using... the database that I had just dropped. In a nutshell I had something like forms.ChoiceField(choices=get_some_data(),...) where get_some_data() used the database to retrieve some default values.
I wish you had posted the backtrace because in my case it's pretty obvious by looking at the backtrace that get_some_data() was using the orm (using something like somemodel.objetcs.filter(...)).

Somehow, Django thinks you've already created this table and are now trying to modify it, while in fact you've externally dropped the table and started over. If that's the case, delete all of the files in migrations folders belong to your apps and start over with ./manage.py makemigrations.

Review, if you have any dependencies, is possible same Model need the Model Country in the same app or other app like:
class OtherModel(models.Model):
country = models.ForeignKey(Country)
1.- If is True, you need to review if installed_apps in settings.py have the correct order of apps, if is in the same app, you need to declare first a Country app and then the dependents.
2.- If dependent is in the same app, the dependent Model need to be declared after Country model in models.py.
3.- Review if the error track on console talk about same erros on models.py or forms.py
4.- Review if when executing makemigrations and migrate is the correct order of apps: python manage.py makemirgations app_of_country, other_app_name

Related

Unable to connect to a MySQL DB with peewee

In PyCharm I created a MySQL schema using pymysql on my computer. Now I want to use Peewee to create tables and write the SQL queries. However, I always receive an error message (see below) when trying to connect to the DB.
The user has sufficient rights to create tables in the DB schema as it works flawlessly with pymysql (creating tables as well as the schema works fine).
I looked at similar questions on Stackoverflow and couldn't find a similar problem. Moreover, this problem wasn't experienced in any of the tutorials I looked at, so I'm not entirely sure what could be the culprit causing the error. Below is a minimal working example.
from peewee import*
import peewee
user = 'root'
password = 'root'
db_name = 'peewee_demo'
# The schema with the name 'peewee_demo' exists
db = MySQLDatabase(db_name, user=user, passwd=password)
class Book(peewee.Model):
author = peewee.CharField()
title = peewee.TextField()
class Meta:
database = db
db.connect() # Code fails here
Book.create_table()
book = Book(author="me", title='Peewee is cool')
book.save()
for book in Book.filter(author="me"):
print(book.title)
I would expect the above code to connect to MySQL and then create a new table in the schema "peewee_demo". But instead, the code throws an error message when trying to connect to the DB:
/usr/bin/python3.6: Relink '/lib/x86_64-linux-gnu/libsystemd.so.0' with /lib/x86_64-linux-gnu/librt.so.1' for IFUNC symbol clock_gettime'
/usr/bin/python3.6: Relink /lib/x86_64-linux-gnu/libudev.so.1' with /lib/x86_64-linux-gnu/librt.so.1' for IFUNC symbol `clock_gettime'
Do you have any ideas how to fix this issue?
Thanks in advance
As #coleifer pointed out in his comment, the error was probably related to a shared library issue in Python. After setting up a new virtual environment and installing all required packages, everything runs perfectly fine.
I just added the answer to be able to close the question. If #coleifer converts his comment into an answer, I'll delete mine and accept his.

Django admin - model visible to superuser, not staff user

I am aware of syncdb and makemigrations, but we are restricted to do that in production environment.
We recently had couple of tables created on production. As expected, tables were not visible on admin for any user.
Post that, we had below 2 queries executed manually on production sql (i ran migration on my local and did show create table query to fetch raw sql)
django_content_type
INSERT INTO django_content_type(name, app_label, model)
values ('linked_urls',"urls", 'linked_urls');
auth_permission
INSERT INTO auth_permission (name, content_type_id, codename)
values
('Can add linked_urls Table', (SELECT id FROM django_content_type where model='linked_urls' limit 1) ,'add_linked_urls'),
('Can change linked_urls Table', (SELECT id FROM django_content_type where model='linked_urls' limit 1) ,'change_linked_urls'),
('Can delete linked_urls Table', (SELECT id FROM django_content_type where model='linked_urls' limit 1) ,'delete_linked_urls');
Now this model is visible under super-user and is able to grant access to staff users as well, but staff users cant see it.
Is there any table entry that needs to be entered in it?
Or is there any other way to do a solve this problem without syncdb, migrations?
We recently had couple of tables created on production.
I can read what you wrote there in two ways.
First way: you created tables with SQL statements, for which there are no corresponding models in Django. If this is the case, no amount of fiddling with content types and permissions that will make Django suddenly use the tables. You need to create models for the tables. Maybe they'll be unmanaged, but they need to exist.
Second way: the corresponding models in Django do exist, you just manually created tables for them, so that's not a problem. What I'd do in this case is run the following code, explanations follow after the code:
from django.contrib.contenttypes.management import update_contenttypes
from django.apps import apps as configured_apps
from django.contrib.auth.management import create_permissions
for app in configured_apps.get_app_configs():
update_contenttypes(app, interactive=True, verbosity=0)
for app in configured_apps.get_app_configs():
create_permissions(app, verbosity=0)
What the code above does is essentially perform the work that Django performs after it runs migrations. When the migration occurs, Django just creates tables as needed, then when it is done, it calls update_contenttypes, which scans the table associated with the models defined in the project and adds to the django_content_type table whatever needs to be added. Then it calls create_permissions to update auth_permissions with the add/change/delete permissions that need adding. I've used the code above to force permissions to be created early during a migration. It is useful if I have a data migration, for instance, that creates groups that need to refer to the new permissions.
So, finally i had a solution.I did lot of debugging on django and apparanetly below function (at django.contrib.auth.backends) does the job for providing permissions.
def _get_permissions(self, user_obj, obj, from_name):
"""
Returns the permissions of `user_obj` from `from_name`. `from_name` can
be either "group" or "user" to return permissions from
`_get_group_permissions` or `_get_user_permissions` respectively.
"""
if not user_obj.is_active or user_obj.is_anonymous() or obj is not None:
return set()
perm_cache_name = '_%s_perm_cache' % from_name
if not hasattr(user_obj, perm_cache_name):
if user_obj.is_superuser:
perms = Permission.objects.all()
else:
perms = getattr(self, '_get_%s_permissions' % from_name)(user_obj)
perms = perms.values_list('content_type__app_label', 'codename').order_by()
setattr(user_obj, perm_cache_name, set("%s.%s" % (ct, name) for ct, name in perms))
return getattr(user_obj, perm_cache_name)
So what was the issue?
Issue lied in this query :
INSERT INTO django_content_type(name, app_label, model)
values ('linked_urls',"urls", 'linked_urls');
looks fine initially but actual query executed was :
--# notice the caps case here - it looked so trivial, i didn't even bothered to look into it untill i realised what was happening internally
INSERT INTO django_content_type(name, app_label, model)
values ('Linked_Urls',"urls", 'Linked_Urls');
So django, internally, when doing migrate, ensures everything is migrated in lower case - and this was the problem!!
I had a separate query executed to lower case all the previous inserts and voila!

'Relation does not exist' error after transferring to PostgreSQL

I have transfered my project from MySQL to PostgreSQL and tried to drop the column as result of previous issue, because after I removed the problematic column from models.py and saved. error didn't even disappear. Integer error transferring from MySQL to PostgreSQL
Tried both with and without quotes.
ALTER TABLE "UserProfile" DROP COLUMN how_many_new_notifications;
Or:
ALTER TABLE UserProfile DROP COLUMN how_many_new_notifications;
Getting the following:
ERROR: relation "UserProfile" does not exist
Here's a model, if helps:
class UserProfile(models.Model):
user = models.OneToOneField(User)
how_many_new_notifications = models.IntegerField(null=True,default=0)
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
I supposed it might have something to do with mixed-case but I have found no solution through all similar questions.
Yes, Postgresql is a case aware database but django is smart enough to know that. It converts all field and it generally converts the model name to a lower case table name. However the real problem here is that your model name will be prefixed by the app name. generally django table names are like:
<appname>_<modelname>
You can find out what exactly it is by:
from myapp.models import UserProfile
print (UserProfile._meta.db_table)
Obviously this needs to be typed into the django shell, which is invoked by ./manage.py shell the result of this print statement is what you should use in your query.
Client: DataGrip
Database engine: PostgreSQL
For me this worked opening a new console, because apparently from the IDE cache it was not recognizing the table I had created.
Steps to operate with the tables of a database:
Database (Left side panel of the IDE) >
Double Click on PostgreSQL - #localhost >
Double Click on the name of the database >
Right click on public schema >
New > Console
GL

Rails 3 active record observer not working when updating through MySQL command line/workbench

I'm working on ROR 3 app . I have added the following observer but I dont see any output as expected in the console or log file ( i have tried in both development and production modes)
cmd : rails g observer auditor
models:
class AuditorObserver < ActiveRecord::Observer
observe :excel_file
def after_update(excel_file)
excel_file.logger.info('New contact added!')
AuditTrail.new(execl_file, "UPDATED")
puts "*******************"
logger.info "********************************************"
end
end
application.rb:
config.active_record.observers = :auditor_observer
What am I missing in here? When I change the database (thru Mysql workbench/command line) I don't see any of the above lines getting executed.. neither after_update/after_save. But after_save works if I'm executing a query thru the app itself and do #excel.save
How else are we supposed to update data in DB so that we see the observer working????
When you bypass activerecord by modifying the database directly, you naturally bypass all of the activerecord callbacks.
So the answer is to update the data through the application, or to use database triggers instead.

how to add a new field in django model

this is my model :
class zjm_model(models.Model):
a = models.CharField(max_length=36)
b = models.CharField(max_length=36)
and the table zjm_model has many data in my mysql , and now ,
i want to add a new field :
class zjm_model(models.Model):
a = models.CharField(max_length=36)
b = models.CharField(max_length=36)
c = models.CharField(max_length=36)
but , when i run manage.py syncdb , it show this :
No fixtures found.
so how can i to add a new field to my database ,
thanks
Database migrations are not built-in to Django, so you'll need to use a third party library. I highly recommend south.
south is very nice and all that, but if this is a very rare one-off thing then just fire up your favourite mysql tool and do something like: ALTER TABLE foo ADD COLUMN wotsit VARCHAR(100) - I can't remember the exact syntax...
But +1 for south.
You have to dump your previous data.
manage.py dumpdata > dump.json
And you can load your data after syncdb. ("c" column have to permit null)
manage.py loaddata dump.json