Having said that, I just remembered there's a common practice in designing database that I could never done in any ORM (not only django's), and that is to have a group of fields as primary key. Ie:

   Company table
     - company id (pk)
     - name

   Employee
     - company id (pk)
     - employee id (pk)
     - employee name

   EmployeeExpense
     - company id (pk)
     - employee id (pk)
     - expense id (pk)
     - amount

The reason of why doing that, is to keep the query faster (use less join), simpler, can be grouped easily (get sum of employee's expense amount per company), sometimes can avoid a database query in logic (ie: expense id sequence format => "company_id-employee_id-running_Number"), and useful in history/auditing-style table where changes in foreignkey must not propagate (ie: EmployeeExpenseHistory table keep employee id and expense id the way it originally inserted no matter if the employee has been deleted etc).

Evidently, since pk always one field, above design translates into:

   Company table
     - company id (pk)
     - name

   Employee
     - id (pk)
     - employee id (pk)
     - employee name
     - company id (FK)
     => unique(company id, employee id)

   EmployeeExpense
     - id (pk)
     - expense id (pk)
     - amount
     - company id (FK)
     - employee id (FK)
     => unique(company id, employee id, expense id)

Where as we can see, requires dummy id as primary key (ie: on Employee table) since it is possible having the same employee id but for different company, and still require a unique index to enforce uniqueness of the logical key. This design will quickly become unwieldy for big tables especially the more deeper relationship tables (ie EmployeeExpenseDetail) because of the table joining (that's why adding company id in EmployeeExpense helps).

But what is good about it does not translate equally well to the framework. The orm framework (and everything that depends on it) would become much more complex if it supported multiple pk, and since most people seems to be quite content with having 1 pk, then who cares?


Dody Suria Wijaya wrote:


My approach is, if you would often be needing to get list of news both by company and user, for performance reason I would put both foreignkey (one 2 many) to company and user in newsposting model. That way, the resulting join query only need to join maximum of two tables and be faster. Although this requires some codes (maybe in _pre/post_save) to keep the user field is consistent with the company field.

Otherwise, #1 is better since as Adrian said, you could simply do newspostings.get_list(user__company__id__exact=123).

Reply via email to