Django routing to database based on model table - django

I have a Django (1.6) project with two databases. I have one app with one model, and multiple tables.
I want to use the database routers to set specific tables in the model to a specific database. All the documentation I have found seems to explain how to route a particular app to a particular database.

Looks like you could use a custom router and model attribute for this.
YMMV: Haven't tested this.
https://docs.djangoproject.com/en/dev/topics/db/multi-db/#using-routers
class MyModel(models.Model):
_DATABASE = "foo"
class CustomRouter(object):
def db_for_read(self, model, **hints):
database = getattr(model, "_DATABASE", None)
return database
# repeat for db_for_write, etc.

Related

Django - Model.py

Just a simple question.
After I connect my django app to a remote database, I don't need to use Model.py to create tables in the database, then what is the function for Model.py at that moment?
If you want to use the Django ORM, you'll need to create models in the models.py file that match your remote database. If you don't want django creating or deleting tables on this DB, the managed=False option needs to be set for each model.
https://docs.djangoproject.com/en/1.11/ref/models/options/#managed
As you said after running migrations all tables in models.py file will be created. Later on, if you want to do some database operations, you may be using Django ORM. If you don't have models.py you won't be able to do such operations.
For example:
To create an entry to the table MyModel.
from your_app.models import MyModel
MyModel.objects.create(<field_name>=<value>)
I hope this gives you some idea.

Django: get table name of a model in the model manager?

I have a model and have a model manager for this model. I'm writing some sql in the model manager, and I need the table name of the model in sql. I know the name of table is combined by metadata app_label and db_name, but is it possible that I can access them from manager class? I know I can create an model instance in the manager, but I would rather not do that..
Thanks very much!
Model manager has the field model:
Model.objects.model._meta.db_table
For a given instance, you can use instance._meta.db_table but that also works for the model class too, so if you can step up from the manager to its model, that'll work too
Let's say you have a model named Service
You can use
Service._meta.db_table # this will work too
This as well
Service.objects.model._meta.db_table # this will work too
This as well
Let's say you had an instance of the service Model like this
service = Service.objects.get(pk=1)
# get table name like this
table_name = service._meta.db_table # this will work too

Create a django project from an existing database

I have a n existing MySQL database. I want to create a new django application with that database.
I read that I need to run "syncdb" each and every time when add a new model in django. That time adding a new table in database in <database_name>.<table_name> format. And fetching data from that table.
What is the correct method to fetch data from an existing database in django ?
This is my model:
from django.db import models
class Users(models.Model):
employee_id = models.CharField(max_length=30)
def __unicode__(self):
return self.employee_id
Use the Django model meta options to set db_table and db_column on your Models and Fields respectively. See these links for more info on how to use them:
https://docs.djangoproject.com/en/dev/ref/models/options/#db-table
https://docs.djangoproject.com/en/dev/ref/models/fields/#db-column

How to apply a query on 2 databases (having no foreign keys) in Django?

File myapp/models.py has this sample code..
from django.db import models
# model for 'user' table in database oracle_dbuser1:user
class User(models.Model):
. . .
customerid = models.BigIntegerField()
# model for 'customer' table in database oracle_dbuser2:customer
# Note that there is no Foreign key integrity among these legacy tables.
class Customer(models.Model):
. . .
customerid = models.BigIntegerField()
and the file myapp/admin.py has the following code:
from maasusers.models import User, Customer
from django.contrib import admin
class UserAdmin(admin.ModelAdmin):
# A handy constant for the name of the alternate database.
db_one = 'dbuser1'
db_two = 'dbuser2'
# display in a list
list_display = (. . .) # question 1
def queryset(self, request):
result = super(UserAdmin, self).queryset(request).using(self.db_one) # question 2
return result
# Register the Poll class
admin.site.register(User, UserAdmin)
admin.site.register(Customer, UserAdmin)
Question 1: Refer above: I want to display columns of both the tables. How can I achieve this? Eg. Select usr.col1, usr.col2, cust.col1, cust.col10 from user usr, customer cust where usr.col2 = cust.col3;
Question 2: How to write a corresponding queryset() function using the using function?
Database Routers can help you avoid the need to use using() on a queryset. You inform django which databases to use for which models. I suggest you read the documentation around routers thoroughly, as they can be a pain (we use them at our work).
Note the following though:
This example won't work if any of the models in myapp contain relationships to models outside of the other database. Cross-database relationships introduce referential integrity problems that Django can't currently handle.
Django doesn't handle cross database joins, whether you want to use keys to join or not. If you need data from both models, you can execute two separate queries, and do the join yourself in code. I don't know how this would apply to the Admin though.
An alternative would be to create a view, joining the cross database tables within the database itself. However, you won't be able to save instances back.
Hopefully this is a good starting point for your investigations.

Django admin - instance needs to have a primary key value before a many-to-many relationship can be used

edit: I wasn't clear before, I am saving my object in the django admin panel, not in a view. Even when I save the object with no many-to-many relationships I still get the error.
I have a model called TogglDetails that has a ForeignKey relationship with the standard django User model and a MayToManyField relationship with a model named Tag. I have registered my models with django admin but when I try to save a TogglDetails instance I get the error in the title.
Here are my models:
class Tag(models.Model):
name = models.CharField(max_length=30)
def __unicode__(self):
return self.name
class TogglDetails(models.Model):
token = models.CharField(max_length=100)
user = models.ForeignKey(User)
tags = models.ManyToManyField(Tag, blank=True, null=True)
def __unicode__(self):
return self.user.username
class Meta:
verbose_name_plural = "toggl details"
As far as I can tell, there should be no issues with my models and django admin should just save the instance without any issues. Is there something obvious that I have missed?
I am using Django 1.3
The answer to my question was this: Postgres sequences without an 'owned by' attribute do not return an id in Django 1.3
The sequences in my postgres database did not have the "Owned by" attribute set and so did not return an id when a new entry was saved to the db.
As stated by other users:
Postgres sequences without an 'owned by' attribute do not return an id in Django 1.3
The sequences in my postgres database did not have the "Owned by" attribute set and so did not return an id when a new entry was saved to the db
In addition:
This is most likely caused by a backwards incompatible change that renders some primary key types in custom models beyond reach for Django 1.3. See Django trac tickets https://code.djangoproject.com/ticket/13295 and http://code.djangoproject.com/ticket/15682 for more information.
I solved the problem by running the follow commands for the affected tables/sequences.
Specifically running the command:
manage.py dbshell
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
change tablename_colname_seq and tablename.colname
Don't let us guess and add the Error message to your question, this gives most information about where it fails.
Have you imported the User model?
from django.contrib.auth.models import User
I've had this problem as well and the only thing I could do was make the M2M fields blank and not set them until I hit Save and Continue Editing.
I think this just may be a framework wart, as you will notice the User section of the Admin site also has a very strict "You can only edit these fields until you save the model".
So my recommendation is to adopt that scheme, and hide the M2M form field until the model has a Primary Key.
I tried Django 1.3 using CPython, with different database setups. I copy-pasted the models from the question, and did some changes: first I added
from django.contrib.auth.models import User
at the top of the file and I put the reference to Tag between quotes. That shouldn't make any difference. Further, I created the following admin.py:
from django.contrib import admin
import models
admin.site.register(models.Tag)
admin.site.register(models.TogglDetails)
For Sqlite3, the problem described doesn't occur, neither for MySQL. So I tried PostgreSQL, with the postgresql_psycopg2 back end. Same thing: I can't reproduce the error.
So as far as I can figure, there's nothing wrong with the code in the question. The problem must be elsewhere.