django get model with foreign key - sql

Let's say I have 2 tables in my DB. One of them is called Person which has attributes 'name' and 'id' and the other one is called Role which has attributes 'person'(which is a foreign key to the id in Person table) and 'id'.
Now I'd like to make a query that given a name like David, finds all the persons with that name and also returns the Roles associated with them. We know that every Person is associated to at most 1 role.
I know that I cannot use Person.objects.filter(name=David).select_related('Role') Because Role is not Person's attribute. Is there anyway I can get this with only 1 hit to DB?

This is in fact a very simple query, contrary to some of the other answers. The thing to remember is that if you want Roles, you should start with the Role model. So just follow the relationships backwards from there:
Role.objects.filter(person__name='David')

To get the persons, it is as you already wrote:
Person.objects.filter(name='David')
To get all the roles related to any person called David:
Role.objects.filter(person__name='David')
To get the roles of a given person:
Role.objects.filter(person=person)
So what I understand from your question is that you want to do something like this:
for person in Person.objects.filter(name='David'):
person_roles = Role.objects.filter(person=person)
# ...
# do something with person_roles (that should contain
# at most one object according to your constraints).

Related

Laravel - HasManyThrough in a different way

In the laravel docu is the following example for has-many-through relationship: Country has many posts through user.
But in my case i need something like this:
User has many roles through customer.
I would like to have the has-many-through relationship from user to role.
Is there a way to get it working this way?
EDIT
I solved my problem with a collection method:
public function roles() {
$roles = $this->hasMany('SC\Customer')->get()->each(function($item) {
return $item->role();
});
return $roles;
}
It all depends on what you're trying to accomplish.
In most cases where someone needs to define roles, creating a separate pivot table that joins tables would be a good way to do it.
Luckily, Laravel's documentation covers this pretty well, you will likely find the answer in this section: http://laravel.com/docs/5.1/eloquent-relationships#many-to-many
Keep reading through that section and all the way down, Taylor goes deeper into the subject and various solutions for different scenarios..
Let's say you have many users and many roles (admin, user, moderator) etc. Many of these users can have different roles and perhaps other attributes, such as if they are a customer or not. You start by creating the user, roles tables (or whatever else needed).
You can then create a joining pivot table, let's say role_user. In it, you can specify foreign keys like user_id which represents id from the user table and role_id which represents id from the role table.
By specifying the foreign keys, you attach a user to a role and then to whatever attribute you would like in another column. So if you have another column in the pivot table that is "customer", which can 1/0 (is customer / is not customer) or maybe you want to add another foreign key which can be customer_id that represents id column in a customer table.
It all depends on what you're trying to accomplish, but it's easy to get snowed in. Using a UML software to model it all out before actually coding to get a abstract overview, could be a good idea. I would recommend StarUML.
Then in your User model you can just bind them by specifying the relationships, something like this:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');

Db design - table dependency and naming conventions

I'm about to design a db for a new project and I'm kinda stuck on some "concept" stuff.
My initial question is very similar to this one.
Relational table naming convention
That is:
"If I got a table "user" and then I got products that only the user
will have, should the table be named "user-product" or just "product"?
This is a one to many relationship."
In the above thread I found the answer by PerformanceDBA very useful and well written,
but I'm not sure about some points. Quoting part of the answer:
"It doesn't matter if user::product is 1::n. What matters is whether product is a separate entity and whether it is Independent, ie. it can exist on its own. Therefore product, not user_product. And if product exists only in the context of an user, ie. it is Dependent,
then user_product."
This is a very interesting point, but generates another question:
what exactly are the definitions of Independent and Dependent table?
Example 1, we have two tables:
The table User
Id
Username
FullName
The 1::n table Message, representing a collection of messages sent by the users
UserId (FK to User.Id)
Text
The Message table is dependent from the User table or not?
The question I'm asking to myself here, is: "Would the message entity exist without the user?" but I'm not sure about the answer, because it would be "the message would exist but would be anonymous." is this enough to make the Message table dependent from the User table (so i should name the table "UserMessage")?
Example 2, we have two tables:
The table User
Id
Username
FullName
The 1::1 table Profile, representing a user profile
UserId (FK to User.Id)
First Name
Last Name
Gender
Same question, is the table Profile dependent by the User table? I think it is, because a profile without a user would not really make sense.
I'm not sure though, so how can I decide safely if a table is dependent by another or not?
I think you may really have 3 entities to consider. User, product and user_product. Test relationships by describing them with a verb. The relationship between a user and a product is most likely a many-to-many (a user can order many products, and a product can be ordered by many users). This indicates that a composite table between them that takes the primary keys of both tables is needed (and maybe attributes only if they describe a fact about the user/product combination). user_product is what links a user with his products (and a product with who ordered it) and is thus dependent.
That said, in your examples the message and profile tables are dependent, since they cannot exist without a user (their primary key). Use user - user_message and user - user_profile.
Another example of an independent table would be a lookup table (code/description table).
To answer your last question, an entity is considered dependent if its primary key must exist in another entity before it can exist i.e you can't have a profile without a user so it is dependent.

Relationship redundant?

I'm designing a database and I have a user table with users, and a group table with user's group.
These groups will have a owner (a user that has created it), and a set of users that are part of the group (like a Whatsapp group).
To represent this I have this design:
Do you think the owner column on Group table is necessary? Maybe I can add an owner column on Group table I can know easily the group's owner.
If you don't add the owner in the group then where are you going to add it? The only way I see apart from this is adding a boolean isowner to the usergroup. Anyway, this would not make sense if there will only be 1 owner. If there can be N owners then that would be the way to go.
You are on the right track, but you'll need one more step to ensure an owner must actually belong to the group she owns:
There is a FOREIGN KEY in Group {groupID, owner} that references UserGroup {groupID, userID}.
If your DBMS supports deferred foreign keys, you can make owner NOT NULL, to ensure a group cannot be owner-less. Otherwise you can leave it NULL-able (and you will still be able to break the "chicken-and-egg" problem with circular references if your DBMS supports MATCH SIMPLE FKs - almost all do).
You need 4 tables:
User
UserGroup
Group
UserRole (associated with UserGroup) - Shows the role of a user in a group (admin/owner, etc.) - If your roles are Admin and Ordinary user, you could use a Binary column on UserGroup instead.
I know a solution has already been proposed, but I am so convinced there is a better one ...
At the higher level, the concept of owner can be seen as a property of the relation existing between users and groups. It should then ideally be set as a field in the UserGroup table.
It could be either a boolean field or, even better, a generalized userGroupNatureOfRelation field, that could hold values such as 'owner', 'participant', 'user', or whatever could be the status.
Of course, such a solution allows you to implement any specific business rule, like 'there is only one owner per group'. It will let you implement any other more sophisticated business rule when needed, and it will even allow you to add a level of complexity by adding fields such as:
userGroupRelationStartDate
userGroupRelationEndDate
where you'll be able to follow the nature of the relation between a group and a person through time ...
Of course you could say 'I don't need it'. But implementing such an 'open' model does not cost anything more than what you are thinking of now. Then, if for any reason, in a near or far future, business rules have to be changed or improved, your model stays valid and efficient ...
This said, building views and manipulating data should be a lot easier with this model. So this a good and immediate reason to adopt it!

Database design relations in User and Profile

I'm designing a web application for a school. So far, I'm stuck with the database which has these tables:
users
id
username
password
profile
user_id (FK)
name
last_name
sex
group_id (FK)
(other basic information)
... And other tables irrelevant now, like events, comitees, groups and so on.
So, the users table stores basic information about the login, and the profiles table stores all the personal data about the user.
Now, the *group_id* column in the profile table has a foreign key that references the ID column of the group in which the user is currently enrolled, in the groups table. A user can only be enrolled in one group at once, so there's no need for any additional tables.
The thing is that it doesn't make much sense to me declaring a relation like group HAS MANY profiles. Instead, the relation should be group HAS MANY users, but then, I would have to put a *group_id* column on the users table, which doesn't really fit in, since the users table only stores auth information.
On the other side, I would like to list all the users enrolled in a group using an ORM and getting the a users collection and not profiles. The way I see it, is that the users table is like the 'parent' and the profiles table extends the users table.
The same problem would occur when setting attendances for events. Should I reference the profile as a foreign key in the events_attendance table? Or should I reference the user ID?
Of course both solutions could be implemented and work, but which of them is the best choice?
I have dug a little and found that both solutions would comply with 3NF, so in theory, would be correct, but I'm having a hard time designing the right way my database.
This is a question of your own conventions. You need to decide what is the main entity, right after that you can easiy find a proper solution. Both ways are good, but if you think of User as of the main entity while Profile is a property then you should put GroupId into User, otherwise, if you mean User and Profile as a single entity, you can leave GroupId in Profile, and by this you're not saying group HAS MANY profiles but group HAS MANY users.
By setting a proper one-to-one relation (User-Profile) you can force your data integrity good enough.

Simple database table design

I'm trying to design a database structure using best practice but I can't get my head around something which I'm sure is fundamental. The DB is for the users(100+) to subscribe to which magazines(100+) they read.
I have a table for the usernames, user info and magazine titles, but I'm unsure where to list the magazines that each user follows. Do I add a column in the user table and link it to the magazine table or would each user be setup with their own "follow" table that lists the magazine there? I'm getting myself confused I think so any help would be great.
Regards
Ryan
What you're struggling with is called a many-to-many relationship.
To solve this problem, you need a third table--perhaps called user_magazines. This third table should two key fields, one from the user table and the other from the magazine table. For example, user_id column and a magazine_id column. This is called a compound key. With both of these columns, you are now able to discern which books have been read by a whichever user.
This is best understood visually:
In the picture above you can see that the third table (the middle table, stock_category) enables us to know what stock item belongs to which categories.
First of all, you must understand a many-to-many relationship, like take your example of users and magazines. First understand the scenario : A single user can follow many magazines, and a single magazine can be followed by many users, so there exists a many-to-many relationship between users and magazines.
Whenever there exists many-to-many relationship between two entities, we have to introduce a third entity between them which is called an associative entity!
so you have to introduce a third entity named as per your choice and it will be containing information about which user is following which magazine
you can go to http://sqlrelationship.com/many-to-many-relationship/ for better understanding using diagrams
You should have a users table, with an auto-incrementing primary key, username, and anything else you want to store about that user.
Next, a magazines table which contains another auto-incrementing primary key, the name of the mag and anything else you need to store about that magazine.
Finally, a subscriptions table. this should have an auto-incrementing primary key (actually that's not really necessary on this table but personally I would add it), a user_ID column and a magazine_ID column.
To add a subscription, just add a new record to the subscription table containing the ID of the user and the ID of the relevant magazine. This allows for users to subscribe to multiple magazines.
If you want to get fancy you can add referential integrity constraints to the subscriptions table - this tells the database management system that a particular column is a reference to another table, and can specify what to do upon modifying it (for example you could have the DBMS automatically delete subscriptions owned by a particular user if that user is deleted)
You definitely do NOT want to add a column to the user table and have it refer to the magazine table. Users would only be able to follow or subscribe to one magazine which doesn't reflect the real world.
You'll want to have a join table that has a userId and a magazineId. For each magazine that a user subscribes to there will be one entry in the join table.
I'm inferring a little bit about your table structure but if you had:
User (id, login)
Magazine (id, name)
User_Magazine (userId, magazineId)
Perhaps this last table should be called subscription because there may be other information like the subscription end date which you'd want to track and that is really what it is representing in the real world.
You'd be able to put an entry into the User_Magazine table for every subscription.
And if you wanted to see all the magazines a user with the login jdoe had you'd do:
SELECT name
FROM User, Magazine, User_Magazine
WHERE login = 'jdoe'
AND User.id = User_Magazine.userId
AND Magazine.id = User_Magazine.magazineId
You should create a separate table called UserMagazineSubs. Make the UserID + MagazineTile ID as a composite key.
This table will capture all User and Magazine relationship details.
A User_To_Magazine table, that has two columns - UserId and MagazineId, and the key is composite containing both columns