Custom manager in Django MultiDB - python

I'am using MySQL and PostgreSQL in my Django project. Below are the settings:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mysql_db',
'USER': 'username',
'PASSWORD': 'password',
'HOST': 'hostname',
'PORT': '3306',
},
'postgres_db': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'pgsql_db',
'USER': 'username',
'PASSWORD': 'password',
'HOST': 'hostname',
'PORT': '5432',
}
}
And this is the sample model
from postgres_copy import CopyManager
class Items(models.Model):
class params:
db = "postgres_db"
sales_value = models.CharField(max_length=255, null=True, blank=True)
primary_email = models.CharField(max_length=255, null=True, blank=True)
objects = CopyManager()
I want to use Items.objects.all().to_csv('./path/to/csv) this ORM to export model data to CSV. I have used this before in exporting large dataset to csv.
But in this configuration it gives below error
psycopg2.errors.SyntaxError: syntax error at or near "."
LINE 1: COPY (SELECT `sales_item`.`id`, `sales_item`.`sales_value`,...
This seems to be an issue with multiDB.
If I run this ORM in single DB configuration, or even if I set default alias on PostgreSQL this works fine.
CopyManager seems to be getting default alias somehow which I have no idea about.
How can I run this ORM in current settings without any issues?
Any help would be appreciated.
Thanks in advance.

We use postgres and MariaDB in the same time in one project.
I can say - you dont need any additional data manager, in your case it can be:
from django.db.import models
class ItemsQuerySetManager(models.Manager):
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).using("postgres_db")
class Items(models.Model):
sales_value = models.CharField(max_length=255, null=True, blank=True)
primary_email = models.CharField(max_length=255, null=True, blank=True)
objects = ItemsQuerySetManager()
more info here: https://docs.djangoproject.com/en/4.1/topics/db/multi-db/

Related

psycopg2.errors.UndefinedTable: relation "authentication_author" does not exist: Django v4

I tried to start using Postgresql instead of sqlite in my Django project.
I installed postgreqL ON MY Windows, creatred a new database, user and password.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'database_name',
'USER': 'admin',
'PASSWORD': 'admin',
'HOST': 'localhost',
'PORT': '5432',
}
}
But when I try to migrate or makemigrations, I got this:
File
"C:\Users\s...\venv\lib\site-packages\django\db\backends\utils.py",
line 85, in _execute
return self.cursor.execute(sql, params) psycopg2.errors.UndefinedTable: relation "authentication_author" does
not exist LINE 1: ...hentication_author"."is_doctor" FROM
"authentic...
here is my model:
class Author(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, related_name="author")
slug = models.CharField(max_length=50, null=True, blank=True,)
is_doctor = models.BooleanField(default=False)
And yes, I deleted the sqlite3 database, all the migrations folders and I created new ones with the init.py inside of them.
But still get the same problem.
Updated
Traceback screenshots:
It happens with Django. Sometimes you can invoke some code that relies on a new DB schema at the time you're trying to makemigrations.
All you need in this situation is to temporarily comment out all the code that connects makemigrations with your new model's schema. As it was in this question, you can trace related blocks of code just using full traceback.

Django OperationalError: no such column

I'm trying to read values from an sqlite db I added to my Django project but it doesn't work.
I did a test in the Python shell and all it returned was the following error when I tried looking into the data:
from myapp.models import my_data
my_data.objects.all()
OperationalError: no such column: my_table_name.id
This is how my models.py file looks like:
class my_data(models.Model):
status = models.TextField(db_column='STATUS', blank=True, null=True)
name_1 = models.TextField(db_column='NAME_1', blank=True, null=True)
name_2 = models.TextField(db_column='NAME_2', blank=True, null=True)
dep = models.IntegerField(db_column='DEP', blank=True, null=True)
name_reg = models.TextField(db_column='NAME_REG', blank=True, null=True)
reg = models.IntegerField(db_column='REG', blank=True, null=True)
name_com = models.TextField(db_column='NAME_COM', blank=True, null=True)
avgp = models.IntegerField(db_column='AVGP', blank=True, null=True)
class Meta:
managed = True
db_table = 'my_table_name'
My settings.py file:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'my_table_name': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db_my_table_name.sqlite3'),
}
}
Also, I performed the python manage.py makemigrations and python manage.py migrate commands.
Any idea what I am doing wrong?
I write this according to this comment since you said it worked:
Add a id field to my_data model:
AutoField like: id = models.AutoField(primary_key=True)
Tip: In django model names should follow CamelCase convention.
I had the same issue before then i used the below code for my models.py file, this has resolved the issue
class ModelName(models.Model):
id = models.AutoField(primary_key=True)
This could help you to resolve the above Problem
Add this in your models.py:
id = models.AutoField(primary_key=True)

Python Django - Read data from multiple databases

I have a Django app that works with multiple databases and I'm having an issue trying to read data specifically from (testdb2) database.
I do know that you can choose which database that you want to read data using keyword (Using) but that didn't work. The result is it's always tries to read data from (testdb).
Here is the code for database in (Settings.py):
DATABASES = {
'default': {
'NAME': 'testdb',
'ENGINE': 'django.db.backends.postgresql',
'USER': 'username',
'PASSWORD': 'password',
'HOST': 'host',
'PORT': 'port',
},
'users': {
'NAME': 'testdb2',
'ENGINE': 'sql_server.pyodbc',
'USER': 'username',
'PASSWORD': 'password',
'HOST': 'host',
'PORT': 'port',
'OPTIONS': {
'driver': 'ODBC Driver 13 for SQL Server',
},
},
}
Here is the code for (Views.py):
from rest_framework import viewsets
from .models import MyModel
from .serializers import MyModelSerializer
# Create your views here.
class MyModelView(viewsets.ModelViewSet):
queryset = MyModel.objects.using('users').all()
serializer_class = MyModelSerializer
Here is the code for (Models.py):
from django.db import models
from django.db import connection
# Create your models here.
class MyModel(models.Model):
columnName = models.IntegerField(db_column='columnName', primary_key=True)
columnEmail= models.IntegerField(db_column='columnEmail')
columnAddress= models.IntegerField(db_column='columnAddress')
columnPhone= models.IntegerField(db_column='columnPhone')
class Meta:
managed = False # Created from a view. Don't remove.
db_table = 'UserTable'
MyModel is based on a view that is created inside the database.
My question: How can I read data from the database (testdb2)
Thanks :D
I think viewset uses using method only in list. Because using method is only in queryset, so don't use viewset, or use a database router.
I recommend you database router. Check Database Router Doc
In addition to Yongjin Jo's opinion, ModelViewSet in DRF inherits CreateModelMixin. And it's create function.
class CreateModelMixin(object):
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
function create model instance by Serializer. So using method is not used.
You can override save method in Serializer. Or Use database router as Yongjin Jo said.

Django Unitest: Table doesn't exist

I created a simple test case like this:
from unittest import TestCase
import user_manager
class UserTest(TestCase):
def test_register(self):
email = "dung7#gmail.com"
password = "123456"
result, user = user_manager.setup_new_user(email, password)
self.assertEqual(result, CodeID.SUCCESS)
Then I run the testcase:
python manage.py test users
And here is the log:
Creating test database for alias 'default'...
/Users/admin/Projects/MyApp/venv/lib/python2.7/site-packages/django/db/backends/mysql/base.py:112: Warning: Table 'mysql.column_stats' doesn't exist
return self.cursor.execute(query, args)
Creating test database for alias 'myapp_log'...
.FE
======================================================================
ERROR: test_register (users.tests.UserTest)
----------------------------------------------------------------------
Traceback (most recent call last):
...
ProgrammingError: (1146, "Table 'test_myapp.user' doesn't exist")
So it created a test database but seem like it didn't create the tables. Here is my DATABASES setting:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "myapp",
'USER': "root",
'PASSWORD': "",
'HOST': '127.0.0.1',
'PORT': '',
},
'myapp_log': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "myapp_log",
'USER': "root",
'PASSWORD': "",
'HOST': '127.0.0.1',
'PORT': '',
},
}
And my model:
class User(BaseModel):
uid = models.IntegerField(primary_key=True)
email = models.CharField(max_length=200)
password = models.CharField(max_length=200)
create_time = models.IntegerField()
update_time = models.IntegerField()
status = models.IntegerField()
social_token = models.CharField(max_length=200)
social_app = models.IntegerField()
class Meta:
db_table = 'user'
Anyone know why the table 'user' is not created?
UPDATE:
user_manager from my testcase will do some query and add new record on table user.
And I thought when I run the testcase, Django will somehow read my models and create a test database with all the table from those models. Am I right about this?
So I found out I need to put my models.py in my users' folder and add 'users' into the INSTALLED_APPS setting. Now it worked.
Your test database needs to be different than your production database. Test databases are destroyed once the test cases are run. In your case the database was not created. You should go through this documentation for detailed information https://docs.djangoproject.com/en/1.10/topics/testing/overview/
Can you also add the snippet of your user_manager module

Password Authentication Failure error when running Django's sqlall command

I am working allong with Django book. Now I'm on the fifth chapter(Models) and right now I'm dealing with some problems. For instance, when I'm trying to write in my shell: python.py manage.py sqlall my_app_name I am getting this message:
Where is my mistake?
P.S. My my_app.models.py:
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
My project settings.py databases configuration:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydb',
'USER': 'admin', # Not used with sqlite3.
'PASSWORD': '123', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used wit
}
}
And finally - my project settings.py INSTALLED_APPS and MIDDLEWARE_CLASSES:
INSTALLED_APPS = (
#'django.contrib.admin',
#'django.contrib.auth',
#'django.contrib.contenttypes',
#'django.contrib.sessions',
#'django.contrib.messages',
#'django.contrib.staticfiles',
'books', # MY APP NAME
)
MIDDLEWARE_CLASSES = (
#'django.contrib.sessions.middleware.SessionMiddleware',
#'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware',
#'django.contrib.auth.middleware.AuthenticationMiddleware',
#'django.contrib.messages.middleware.MessageMiddleware',
#'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
If you need any more information just say. Thank you in advance!
The error message is quite explicit that this is a problem with connecting to the database with that username and password. Have you set that account up in Postgres?

Categories

Resources