How to establish a many to many relationship in SQLAlchemy? - sqlalchemy

I'm trying to build a simple app where users can follow other users so, I have a table "Users" that has all the user's info, and since a user can follow many users and that user can have many followers we get a Many-to-Many relationship, so I created a linking table. Here's my code:
As you can see the "UsersFollowing" table has composite Primary Key that is build from the Foreign Keys taken from the "User" table (user, and who is following).
Now I want to get the following: "Given a user id return all the users that follows".
I'm new in SQLAlchemy and I don't know how to get the result.

If you're using the SQLAlchemy ORM, you should be able to get the users by issuing a join and filtering:
db_session.query(User)\
.join(UsersFollowing, User.id == UsersFollowing.user_following_id)\
.filter(UsersFollowing.user_id == <userid>)

Related

Database Tables for User management

I would like to get some advice from you about best practices in user role management.
I would like to create an application where user register and will have different roles. Now the obvious thing is, to create the users table and save the user data there like this:
users
id
userUUID
username
role
But I think about separated tables for different groups. So like:
admins
id
userUUID (-> foreign key users table)
accessRight1
accessRight2
subscribers
id
userUUID (-> foreign key users table)
etc
Does this make sense? So should all users, regardless of their role be in one database? And what is then about the specific information for different roles?
Thanks!
If your roles are rarely going to change that would probably work. But, you should always plan for change, and a more flexible option allowing you to add roles without needing to change your database schema would be something like this:
Users:
uid
user info...
Roles:
rid
name
UserRoles:
uid (FK to user table)
rid (FK to roles table)
In your code you could then check the UserRoles table to determine if the user has a given role and therefore should be allowed to do whatever.
Additionally, if you want to mix and match permissions for actions across multiple roles (i.e. both Admin's and Moderators have permission to delete posts or something). You could add another level with a Permissions table, and a join table (RolePermissions) linking that to the Roles table. You're access checks would become slightly more complicated then, requiring you to join the UserRoles table and RolePermissions join table to determine if a user has a given permission to do something.
Something like this:
SELECT *
FROM UserRoles u INNER JOIN RolePermissions p
ON u.rid=p.rid
WHERE u.ID=<USER> AND p.pid=<PERMISSION>

Laravel ORM: unique combination of fields from pivot table

This question extends the example Eloquent : Working With Pivot Tables provided in the Laravel Documentation.
The relationship here is that a User has many Role objects that it can relate to, and each Role is made up of a number of Task's.
The relationships between these models are:
User and Role:
Each Role may only relate to one User, however a User may have many Role's
A one-to-many relationship
Role and Task
Each Role can have many Task's associated with it, and each Task can belong to several Roles
A many-to-many relationship
In terms of a database schema (MySql), we therefore have:
A users table that has no foreign keys
A roles table with a user_id foreign key
A tasks table
A role-task pivot table
In plain English, the constraint I need to apply is that a user can not be associated with multiple roles that are made up of exactly the same tasks, however two role's can be made up of exactly the same task's
Is there an in-built way to apply this constraint using Laravels Eloquent ORM system? If not, what would be a tidy workaround?
edit:
Eloquent-like description:
User hasMany Role
Role belongsToMany Task
Question: How to prevent assigning to a user multiple roles having exactly the same related collection of tasks

facebook group alike database design and foreign key

Here are my requirements:
one user can have many tasks
one group can have many task
one group can have many users
think of it like a facebook group. Invited user in a group can post more than one status. Each user can create many groups.
so it's my database correct? Do I need to specify FK in bridge key?
The design in mysql is correct. If you want to be strict, yes, you do have to enforce integrity using foreign keys in bridge tables.
If a task can belong to only one group you must remove "Task_Group" and add "group_id" into Task table.

Model a table that can have a relationship with several tables

I have a table called 'notes', on this table I need to track who made that note, but the problem is that the creator of the note can be a user stored in one of three possible tables:
users
leads
managers
I have though of simply create three fields on 'notes' to represent the three possible relations: note.user, note.lead, note.manager
With this approach I would be forced to create three table joins when requesting the notes to gather the creators information, and I don't think that is the way to go, so I would like to hear your ideas or comments and what would be the best approach on this.
For me personally this smells like a design problem on a totally different part of the schema: Are manageers not users? Do leads carry person information?
With any approach that creates a relation between one column and one of three others, you will need three joins for the select. If you can't rectify the underlying problem, I recommend you use
note_type ENUM('users','leads','managers')
as an additional field and
SELECT
...
IFNULL(users.name(IFNULL(managers.name,leads.name))) AS name
..
FROM notes
LEFT JOIN users ON notes.note_type='users' AND users.id=notes.note_source
LEFT JOIN managers ON notes.note_type='managers' AND managers.id=notes.note_source
LEFT JOIN leads ON notes.note_type='leads' AND leads.id=notes.note_source
...
for the query
I think you need to abstract out the concept of a user id, so that it does not depend on their role. The author of a note could then be specified by the user id.
Users could be assigned roles, and maybe more than one.
The correct way to structure this would be to pull all common data out of users, leads, and managers. Unify this data into a "contact" table. Then if you want to get all notes for a given manager:
managers->contacts->notes
for a lead:
leads->contacts->notes
Notice your original post: "the problem is that the creator of the note can be a user stored in one of three possible tables"
From the structure of your sentence you even admit that all these entities have something in common; they are all users. Why not make the DB reflect this?
you have to model a parent table for the three tables you already have. Define a table that depicts generally user, leads and manager tables. Something like "Person". So you have all of the ids of the three tables and any common attributes on the Person table. And when you must define the relationship you put the foreign id "Person_ID" on the note table. And when you model user, leads and manager tables you also put the primary key as a foreign key to the Person table.
So you would have something like this:
Table users:
Users(
person_id primary key
...(attributes of Users)
foreign key person_id references Person.person_id
)
This model i depict is common to any relational model you have to model using parents and childs

User Login with Staff and Customers MySQL

I finally got permission to redesign our database (yay, everybody cheer)!
One of the problems that I need to overcome is user login.
The way the database is currently designed, there is a User table, with a 1:n relationship to UserStaff (user can have multiple staff - think of a manager). There is also a completely unrelated Customer table.
I need to create a table to consolidate the login so that all of these people (User, UserStaff, and Customer) can login to the same area, but each of these tables above has completely different information inside and different relationships to data.
How/where should I start moving things around to get this to work?
You could create a "Login" table containing "loginID", "email", and "password" fields. Each of the other tables (User, UserStaff, Customer) would also contain the "loginID" field. Then at login-time you could SELECT from the login table, and (left) JOIN on loginID to the other tables to get your user's data.