Different schemas containing same tables names - django

I'm finding myself with a django project handling two distinct classes mapped on a similar table name:
class BarA(models.Model):
[...]
class Meta:
db_table = 'bar' # doesn't specify any schema
class BarB(models.Model):
[...]
class Meta:
db_table = u'foo"."bar'
The project is using a database containing two schemas: public and foo.
The way this application is templated and deployed makes things even more confusing: on some servers, django connects to database with the user "John", not member of any role, but on other servers it connects with user "Eric", member of a foo role.
Two questions here:
If django's meta class doesn't mention any specific schema, how does Postgres decide which table it will work with ? So far, it appears that user Eric will always hit the foo.bar table, and never the public.bar one, regardless of the called class.
With user "John", I'm only using BarA class and it properly hits public.bar.
Django doesn't seem to handle schemas; is this solution considered as a good practice for that kind of case (please note that I cannot rename the existing tables)?

In postgres search_path variable set the priority for choosing the schema for the table:
search_path (string)
This variable specifies the order in which
schemas are searched when an object (table, data type, function, etc.)
is referenced by a simple name with no schema specified. When there
are objects of identical names in different schemas, the one found
first in the search path is used.
[...]
The current effective value of the search path can be examined via the SQL function current_schemas.
A quick way to do so:
SELECT current_schemas(True);
You can find details on how to manage search_path in section 5.7.3. of this article: http://www.postgresql.org/docs/current/static/ddl-schemas.html

Related

how to build a vapor app from an already existing database?

I have built a MySQL database with multiple tables and complex relationships, but when I go through the vapor documentation, specifically, in the building the model phase, there is a method for creating the table (that my model class will interact with).
static func prepare(_ database: Database) throws {
try database.create("users") { users in
users.id()
users.string("name")
}
}
However, I don't want to use it because the table that I already have contain foreign keys and types like DATETIME (which I don't know how to declare within the swift context.) is there a way to link my already built tables with vapor?
This is somewhere Vapor (or more correctly Fluent, which is the database level of Vapor) is a bit limited.
Yes, you can use your existing tables. In your prepare(_:) method, you can simply leave the implementation empty without creating a table at all. You should also leave revert(_:) empty as well.
In your init(node:in:) initialiser and makeNode(context:) method, you will need to map between the column names and types in your table and the property types in your Swift model.
In the model object class (User here), the prepare method can be left unimplemented since we don't need to create the tables explicitly from the code. So should be like
static func prepare(_ database: Database) throws {
...
}
But should add a static variable named entity which will map the table name in db without model class, like following
final class User: Model {
static let entity = "users"
...
}
And finally, we should add the model to the droplet's preparations array with drop.preparations.append(User.self)
So that we can use any existing table in a database which has complex relationships, to map from a model object in Vapor.

SQLalchemy: multiple tables one schema, and dynamically creating tables at startup

I'm building a Flask app, which, at startup, should read some number of tsv files, each of which has the same schema, put them in tables (one for each file), and then users will specify which table/file they want to query, and some number of keys.
I'm not sure how to do this, but the best way seems to be to specify one schema and then, once the app starts, read the files and dynamically create tables for each file. I can't find anywhere in the SQLalchemy docs any mention of how to use the same schema multiple times. Perhaps I need to extend my schema class, but i'm not sure how to do this at startup.
Thanks in advance!
-- EDIT --
It looks like this answers half of my question:
Flask-SQLAlchemy. Create several tables with all fields identical
So my question now is: Can you do the above in Flask, and can you do it as the app starts?
You can take 2 approaches.
Sub-classing - You create a base Mixin for schema and subclass it for each concrete tables. This approach is useful, if you expect that in future the schema for different tables might diverge. If a new field needs to be added in only one table you can add it only in sub-class. (variables db, Model etc is used from flask sqlalchemy quickstart)
class BaseMixin(object):
name = db.Column(String(80), unique=True)
field2 = db.Column ...
class SubClass1(BaseMixin, db.Model)
pass
class Subclass2(BaseMixin, db.Model)
additional_field_for_subclass2 = db.Column(...
pass
Common table for all - If you are confident that the schema will remain the same for all tables. I would suggest you create one table for all you data, with a additional field data_source which will indicate where the row/data came from.
class CommonTable(db.Model):
data_source = db.Column(String(100) ..)
field1 = ...
field2 = ...

Django Database Prefix

I need to merge two databases for two different apps. How can add prefix to all Django tables to avoid any conflict?
For example, option should look like:
DB_PREFIX = 'my_prefix_'
You can use meta options for model,
class ModelHere():
class Meta:
db_table = "tablenamehere"
Edit
If you want to add prefix to all of your tables including auth_user, auth_group, etc. Then you are looking for something like django-table-prefix. Just install and add some settings to settings file and you are done.
Add 'table_prefix', to installed apps,
Set the table prefix as DB_PREFIX = 'nifty_prefix'
Then run syncdb and the output will be,
Creating tables ...
Creating table nifty_prefix_auth_permission
Creating table nifty_prefix_auth_group_permissions
Creating table nifty_prefix_auth_group
Creating table nifty_prefix_auth_user_groups
Creating table nifty_prefix_auth_user_user_permissions
Creating table nifty_prefix_auth_user
Creating table nifty_prefix_django_content_type
Creating table nifty_prefix_django_session
Creating table nifty_prefix_django_site
An alternative to prefixing all the names is to put one of the two DBs into a different schema
(multiple schemas can coexist in the same database, even if the objects have the same names) This will also take care of objects other than tables, such as indexes, views, functions, ...
So on one of the databases, just do
ALTER SCHEMA public RENAME TO myname;
After that, you can dump it (pg_dump -n myname to dump only one schema), and import it into the other database, without the chance of collisions.
You refer to tables or other objects in the new schema by myname.tablname or by setting the search_path (this can be done on a per-user basis eg via ALTER USER SET search_path = myschema, pg_catalog;)
Note: there may be a problem with frameworks and clients not being schema-aware, so you might need some additional tweaking. YMMV.
http://www.postgresql.org/docs/9.4/static/sql-alterschema.html

Tastypie, Django, joining unrelated resources

My question is how do i join unrelated resources that have a similar variable
Both resources have an 8 length VARCHAR variable, both named code.
Due to how to data is constructed I cannot make any assumption that would lead to this being a foreign key relation but I do however need to join this two tables together if they have similar code values, how do I join these resources together to be displayed in tastypie/django?
class CodeDescription(models.Model):
code = models.CharField(db_column='Code', max_length=10)
description = models.CharField(db_column='Description', max_length=255)
class TechnicalDif(models.Model):
code = models.CharField(db_column='Code', max_length=10)
As you can see these tables hold the same sort of value but CodeDescription holds the details of what the code means, but doesn't necessarily have the definition for all the codes, so a foreignkey relation cannot be applied, How would i join these two tables for display using them as a tastypie resource?
The only way I think you can do this is programatically in the dehydrate method of the relevant TastyPie ResourceClass. So for each loaded object you could do a query and set an appropriate value in the bundle.
Alternatively, I suppose you could create a join table, that joins related CodeDescriptions to TechnicalDifs, and populate it programatically with a query that you run over the tables intermittently (e.g. when something changes).

Do Django models really need a single unique key field

Some of my models are only unique in a combination of keys. I don't want to use an auto-numbering id as the identifier as subsets of the data will be exported to other systems (such as spreadsheets), modified and then used to update the master database.
Here's an example:
class Statement(models.Model):
supplier = models.ForeignKey(Supplier)
total = models.DecimalField("statement total", max_digits=10, decimal_places=2)
statement_date = models.DateField("statement date")
....
class Invoice(models.Model):
supplier = models.ForeignKey(Supplier)
amount = models.DecimalField("invoice total", max_digits=10, decimal_places=2)
invoice_date = models.DateField("date of invoice")
statement = models.ForeignKey(Statement, blank=True, null=True)
....
Invoice records are only unique for a combination of supplier, amount and invoice_date
I'm wondering if I should create a slug for Invoice based on supplier, amount and invoice_date so that it is easy to identify the correct record.
An example of the problem of having multiple related fields to identify the right record is django-csvimport which assumes there is only one related field and will not discriminate on two when building the foreign key links.
Yet the slug seems a clumsy option and needs some kind of management to rebuild the slugs after adding records in bulk.
I'm thinking this must be a common problem and maybe there's a best practice design pattern out there somewhere.
I am using PostgreSQL in case anyone has a database solution. Although I'd prefer to avoid that if possible, I can see that it might be the way to build my slug if that's the way to go, perhaps with trigger functions. That just feels a bit like hidden functionality though, and may cause a headache for setting up on a different server.
UPDATE - after reading initial replies
My application requires that data may be exported, modified remotely, and merged back into the master database after review and approval. Hidden autonumber keys don't easily survive that consistently. The relation invoices[2417] is part of statements[265] is not persistent if the statement table was emptied and reloaded from a CSV.
If I use the numeric autonumber pk then any process that is updating the database would need to refresh the related key numbers or by using the multiple WITH clause.
If I create a slug that is based on my 3 keys but easy to reproduce then I can use it as the key - albeit clumsily. I'm thinking of a slug along the lines:
u'%s %s %s' % (self.supplier,
self.statement_date.strftime("%Y-%m-%d"),
self.total)
This seems quite clumsy and not very DRY as I expect I may have to recreate the slug elsewhere duplicating the algorithm (maybe in an Excel formula, or an Access query)
I thought there must be a better way I'm missing but it looks like yuvi's reply means there should be, and there will be, but not yet :-(
What you're talking about it a multi-column primary key, otherwise known as "composite" or "compound" keys. Support in django for composite keys today is still in the works, you can read about it here:
Currently Django models only support a single column in this set,
denying many designs where the natural primary key of a table is
multiple columns [...] Current state is that the issue is
accepted/assigned and being worked on [...]
The link also mentions a partial implementation which is django-compositekeys. It's only partial and will cause you trouble with navigating between relationships:
support for composite keys is missing in ForeignKey and
RelatedManager. As a consequence, it isn't possible to navigate
relationships from models that have a composite primary key.
So currently it isn't entirely supported, but will be in the future. Regarding your own project, you can make of that what you will, though my own suggestion is to stick with the fully supported default of a hidden auto-incremented field that you don't even need to think about (and use unique_together to enforce the uniqness of the described fields instead of making them your primary keys).
I hope this helps!
No.
Model needs to have one field that is primary_key = True. By default this is the (hidden) autofield which stores object Id. But you can set primary_key to True at any other field.
I've done this in cases, Where i'm creating django project upon tables which were previously created manually or through some other frameworks/systems.
In reality - you can use whatever means you can think of, for joining objects together in queries. As long as query returns bunch of data that can be associated with models you have - it does not really matter which field you are using for joins. Just keep in mind, that the solution you use should be as effective as possible.
Alan