Dynamic database routing in Django - database

In my database, I have a Customer table defined in my database that all other tables are foreign keyed on.
class Customer(models.Model):
...
class TableA(models.Model):
Customer = models.ForeignKey(Customer)
...
class TableB(models.Model):
Customer = models.ForeignKey(Customer)
...
I'm trying to implement a database router that determines the database to connect to based on the primary key of the Customer table. For instance, ids in the range 1 - 100 will connect to Database A, ids in the range 101 - 200 will connect to Database B.
I've read through the Django documentation on routers but I'm unsure if what I'm asking is possible. Specifically, the methods db_for_read(model, **hints) and db_for_write(model, **hints) work on the type of the object. This is useless for me as I need routing to be based on the contents of the instance of the object. The documentation further states that the only **hints provided at this moment are an instance object where applicable and in some cases no instance is provided at all. This doesn't inspire me with confidence as it does not explicitly state the cases when no instance is provided.
I'm essentially attempting to implement application level sharding of the database. Is this possible in Django?

Solve Chicken and egg
You'll have to solve the chicken and egg problem when saving a new Customer. You have to save to get an id, but you have to know the id to know where to save.
You can solve that by saving all Customers in DatabaseA first and then check the id and save it in the target db too. See Django multidb: write to multiple databases. If you do it consequently, you won't run into these problems. But make sure to pay attention to deleting Customers.
Then route using **hints
The routing problem that's left is pretty straight forward if an instance is in the hints. Either it is a Customer and you'll return 'DatabaseA' or it has a customer and you'll decide on its customer_id or customer.id.
Try and remember, there is no spoon.
When there is no instance in the hints, but it is a model from your app, raise an error, so you can change the code that created the Queryset. You should always provide hints, when they aren't added automatically.
What will really bake your cookie
If for most queries you have a know Customer, this is ok. But think about queries like TableA.objects.filter(customer__name__startswith='foo')

Related

is there a way to have 2 dates under a customer's name in Microsoft access

I'm an intern student at a company that does both wiring and aircon services. The job that they gave me was to make a database for them. I don't have any experience in anything related to databases.
So, I started to look up videos and stuff to at least learn a bit about databases and made something that works and I made it after 1.5 months of learning.
in the database that I created,
I have 1 table (CustomerDetailsT):
CustomerID (pk)
CustomerName
PhoneNumber
Address
Aircond (type and model of ac,ex: WM daikin 1.0HP)
AcDetails (what has been done for the ac.)
Others (yes/no) (Wiring, installing a fan and so on)
WhatHasBeenDone (shows what has been done for others)
Then 3 queries (CustomerOthersDetailsQ, CustomerAcDetailsQ, CustomerDetailsQ).CustomerAcDetailsQ has CustomerName, PhoneNumber, Address, Aircond and AcDetails. CustomerOthersDetailsQ has CustomerName, PhoneNumber, Address, Others, and WhatHasBeenDone.CustomerDetailsQ has CustomerID, CustomerName, PhoneNumber and Address
And 1 form with 3 subforms.
it's a search form, which would search for customers as we're typing in their name/phone number and it will show what has been done for the customer.
With this, I have created what the company wants, but now they want to add dates. Dates which would show when we have done something for a customer. Dates for Aircond and the Others stuff.
I've tried with what I know and it didn't work. tried searching it on youtube and google, but still couldn't find it.
how can I go about doing this?. I have tried having separate tables for each service, but it became a hassle when I wanted to create a new customer. . I hope I could some help, I could send pictures if someone needs them.
[1]: https://i.stack.imgur.com/mtrmC.png [The Customer search form] [1]: https://i.stack.imgur.com/A3Y9d.png [example of a customer that has ac installation] [1]: https://i.stack.imgur.com/dsGL5.png [example of a customer that has both ac and wiring done]
Acknowledging the question is too broad, here is some guidance. One of the nice things about Access is that each database is a single file. First protect your work by finding that file and make two copies. Make a backup and a play around version. Only mess with the play around version.
Your question indicates you are still learning Table Normalization and 1 to many relationships. Both of these topics are general to all databases, so you don't have to restrict yourself to just Access when looking for guides and Youtube videos.
Part of normalization is putting separate entities into their own tables. Also, in Access there is a big payoff for using the Relationship Tool, so here is a rather lame example of normalization:
Make sure to select the checkboxes when setting up relationships.
WhatHasbeenDone should also have WhatHasbeenDoneDate. I've wrapped AC and Other as Unit because later it will be easier than having two WhatHasBeenDone tables(AC)(Other).
Now imagine someone taking the customer request call. They just want to see a form to enter the customer details, request, unit-type, etc. They don't want to see those tables. Even with training entering data in the tables is error prone. The person fulfilling the request just wants to enter what they did and when. That's how you start to figure out what your final Data entry forms will look like.
Since we normalized the tables and used the relationships tool, the payoff is Access can give us an assortment of working starter forms. Select Each Table and then hit Create and then hit Form. Choose your Favorites and start playing around from there. While playing, keep in mind that Access will not let you add an item on the many side of a relationship unless there is an item on the 1 side.
For example I selected the customers table and hit create form:
Access uses a concept of form and subform based on separate but related tables. So, to get a form that shows what has been done for each customer I created a form for the What has been done table, and dragged it onto the customers form:
Unless an ID is also being used as a part number or something there is probably no reason for the person entering data to see it. So I removed the texboxes bound to ID's. Except for UnitTypeID, where I replaced the textbox with a combobox that displays the userfriendly UnitDescription. The ID's are still part of the form recordsources, Access is still adding new IDs and using those IDs to put the appropriate data in the right tables.
Oh, didn't we need dates (went back and added a date to the table, and adjusted the subform accordingly). Also changed the subform format from single record to continuous records to show multiple dates:
In conclusion and in my opinion your final forms will use VBA behind the scenes to insert data from the forms into the tables. This is because either you will want to rapidly insert multiple records or How the end users think about the data will not match the default forms and subforms approach Access depends upon to figure out how to insert the data. However, the default approach is fast and I always use it for version 1 of my Access Databases.
P.S. For simplicity I avoided including any Many to Many relationships

Yii Check if entry exists in database before creating new one

I'm pretty new to yii.
I have a form that creates and saves multiple AR models to the database. The problem is that in many cases new entries are actually identical to existing ones. I would like to reduce/ eliminate this kind data redundancy.
The form has 3 entities:
- the main model
- client model
- product model
Many times, product and client will already exist in the database.
Product and Client are referenced through foreign keys in the main model.
I want to know how would it be possible to do the following:
as I type a client's name or phone number, yii searches in the client table and display results as suggestions, through ajax.
if I select one of the suggestions, the Client AR should be populated with that database entry.
when the form is submitted:
if an existing client was selected, use that client's id inside the main model. Do not create a duplicate client in the database.
if client wasn't found in the existing records, create a new one with the provided form data.
I apologize for the bad formatting, this is my second time posting a question. If I wasn't very clear in what I am looking for, please ask for clarification. This is something I would really like to learn.

User Management: Managing users in user-defined "groups", database schema and logistics

I'm a noob, development wise and logistically-wise.
I'm developing a site that lets people take a test...
My client wants the ability for a user with the roll/privledge "admin" (a step below a super-admin) to be allowed to create users and only see/edit the users that they create...
The users created in that "category" or group need some information that their superior provides.
For example, I log in as a "manager", I have the ability to invite people to take the test, and manage those people. Before adding those people, I will have filled out a short survey about myself...
Right now, the users that are invited will be asked some of the same questions as the manager. I'd like to cut down the redundancy by using the information put into the database by the manager and apply it to the invited users.
How do I set up my database to work with this criterion? I'm a little confused about how to do this! Let me know if I can add more details...
(This is a mysql and php app)
I am sure there are several ways to do this but here is one that comes to mind.
In the "users" database, I am sure you have a column to specify which manager is assigned to the user by some kind of user key. Well If this field has a value, then pull the info from that users (manager user) record.
Example:
table 'users'
key----name------managerid-----questionone------questiontwo----
1-------randy-----0------------------california----------c++--------------
2-------bob--------1------------------nevada------------------------------
Since record(key)1 has managerid == 0 then use questiontwo record to answer "Question 2".
Since record(key)2 has managerid == 1 then pull questiontwo from record(key)1 and use that for answer to question two.
You could either insert this information into the record or use it from the manager record dynamically as needed, which thought the space is still being used in the database, would be helpful since manager data might be updated and you might not want to have to update all records with that share the managerid wheh info is changed.
Make sense?

What would you do to avoid conflicting data in this database schema?

I'm working on a multi-user internet database-driven website with SQL Server 2008 / LinqToSQL / custom-made repositories as the DAL. I have run across a normalization problem which can lead to an inconsistent database state if exploited correctly and I am wondering how to deal with the problem.
The problem: Several different companies have access to my website. They should be able to track their Projects and Clients at my website. Some (but not all) of the projects should be assignable to clients.
This results in the following database schema:
**Companies:**
ID
CompanyName
**Clients:**
ID
CompanyID (not nullable)
FirstName
LastName
**Projects:**
ID
CompanyID (not nullable)
ClientID (nullable)
ProjectName
This leads to the following relationships:
Companies-Clients (1:n)
Companies-Projects (1:n)
Clients-Projects(1:n)
Now, if a user is malicious, he might for example insert a Project with his own CompanyID, but with a ClientID belonging to another user, leaving the database in an inconsistent state.
The problem occurs in a similar fashion all over my database schema, so I'd like to solve this in a generic way if any possible. I had the following two ideas:
Check for database writes that might lead to inconsistencies in the DAL. This would be generic, but requires some additional database queries before an update and create queries are performed, so it will result in less performance.
Create an additional table for the clients-Projects relationship and make sure the relationships created this way are consistent. This also requires some additional select queries, but far less than in the first case. On the other hand it is not generic, so it is easier to miss something in the long run, especially when adding more tables / dependencies to the database.
What would you do? Is there any better solution I missed?
Edit: You might wonder why the Projects table has a CompanyID. This is because I want users to be able to add projects with and without clients. I need to keep track of which company (and therefore which website user) a clientless project belongs to, which is why a project needs a CompanyID.
I'd go with with the latter, having one or more tables that define the allowable relationships between entities.
Note, there's no circularity in the references you have, so the title is misleading.
What you have is the possibility of conflicting data, that's different.
Why do you have "CompanyID" in the project table? The ID of the company involved is implicitly given by the client you link to. You don't need it.
Remove that column and you've removed your problem.
Additionally, what is the purpose of the "name" column in the client table? Can you have a client with one name, differing from the name of the company?
Or is "client" the person at that company?
Edit: Ok with the clarification about projects without companies, I would separate out the references, but you're not going to get rid of the problem you're describing without constraints that prevent multiple references being made.
A simple constraint for your existing tables would be that not both the CompanyID and ClientID fields of the project row could be non-null at the same time.
If you want to use the table like this and avoid the all the new queries just put triggers on the table and when user tries to insert row with wrong data the trigger with stop him.
Best Regards,
Iordan
My first thought would be to create a special client record for each company with name "No client". Then eliminate the CompanyId from the Project table, and if a project has no client, use the "No client" record rather than a "normal" client record. If processing of such no-client's is special, add a flag to the no-client record to explicitly identify it. (I'd hate to rely on the name being "No Client" or something like that -- too fuzzy.)
Then there would be no way to store inconsistent data so the problem would go away.
In the end I implemented a completely generic solution which solves my problem without much runtime overhead and without requiring any changes to the database. I'll describe it here in case someone else has the same problem.
First off, the approach only works because the only table that other tables are referencing through multiple paths is the Companies table. Since this is the case in my database, I only have to check whether all n:1 referenced entities of each entity that is to be created / updated / deleted are referencing the same company (or no company at all).
I am enforcing this by deriving all of my Linq entities from one of the following types:
SingleReferenceEntityBase - The norm. Only checks (via reflection) if there really is only one reference (no matter if transitive or intransitive) to the Companies table. If this is the case, the references to the companies table cannot become inconsistent.
MultiReferenceEntityBase - For special cases such as the Projects table above. Asks all directly referenced entities what company ID they are referencing. Raises an exception if there is an inconsistency. This costs me a few select queries per CRUD operation, but since MultiReferenceEntities are much rarer than SingleReferenceEntities, this is negligible.
Both of these types implement a "CheckReferences" and I am calling it whenever the linq entity is written to the database by partially implementing the OnValidate(System.Data.Linq.ChangeAction action) method which is automatically generated for all Linq entities.

Table Module vs. Domain Model

I asked about Choosing a method to store user profiles the other day and received an interesting response from David Thomas Garcia suggesting I use the Table Module design pattern. It looks like this is probably the direction I want to take. Everything I've turned up with Google seems to be fairly high level discussion, so if anyone could point me in the direction of some examples or give me a better idea of the nuts and bolts involved that would be awesome.
The best reference is "Patterns of Enterprise Application Architecture" by Martin Fowler:
Here's an excerpt from the section on Table Module:
A Table Module organizes domain
logic with one class per table in the
database, and a single instance of a
class contains the various procedures
that will act on the data. The
primary distinction with Domain
Model is that, if you have many
orders, a Domain Model will have one
order object per order while a Table
Module will have one object to handle
all orders.
Table Module would be particularly useful in the flexible database architecture you have described for your user profile data, basically the Entity-Attribute-Value design.
Typically, if you use Domain Model, each row in the underlying table becomes one object instance. Since you are storing user profile information in multiple rows, then you end up having to create many Domain Model objects, whereas what you really want is one object that encapsulates all the user properties.
Instead, the Table Module makes it easier for you to code logic that applies to multiple rows in the underlying database table. If you create a profile for a given user, you'd specify all those properties, and the Table Module class would have the code to translate that into a series of INSERT statements, one row per property.
$table->setUserProfile( $userid, array('firstname'=>'Kevin', 'lastname'=>'Loney') );
Likewise, querying a given user's profile would use the Table Module to map the multiple rows of the query result set to object members.
$hashArray = $table->getUserProfile( $userid );

Resources