Flask-SQLAlchemy many to many bidirectional relationship with extra parameters - flask-sqlalchemy

I am currently working on a database that stores USERS and ROOMS.
In order to connect those, I created an association class USERROOM that stores the USER.ID and ROOM.ID as a foreign key, and also has extra columns saying whether the room is owned, visited, or just rented. All good for now. Here is what my code looks like when I create a new room and associate it to a user:
userUser = User.query.filter_by(id=userID).first() # This finds the user
association = UserRoom(relationship="owner") # This sets the relationship
association.room = Room(_ROOM CREATION CODE) #This creates the room and associates it.
user.rooms.append(association) # This appends the association
db.session.commit()
Okay, so all of that works no problem.
However, when association.room is NOT creating a new room, I get an error:
sqlalchemy.exc.IntegrityError: (raised as a result of Query-invoked autoflush; consider using a session.no_autoflush block if this flush is occurring prematurely)
(psycopg2.errors.NotNullViolation) null value in column "user_id" of relation
"user_room" violates not-null constraint
DETAIL: Failing row contains (null, 1, rents).
It's literally the first code as the first snippet, only that instead of creating a new Room to populate association.room, I use an existing room.
The first one works, second one doesn't.
I want a user to be able to both visit and rent a room for example.

Related

EF: Inserting already present record in many to many relationship

For what I searched there are 2 ways to insert an already present record into a ICollection list:
group.Users.Add(db.Users.FirstOrDefault(x=> x.Id = 1));
var to_add = new User{Id: 1}; db.Users.Attach(to_add); group.Users.Add(to_add);
The problem with both the above approach is it makes a db call every time we want to add a record. While we already know the user's Id and the group's id and that's all it needs to create a relationship.
Imagine a long list to be added, both the above methods would make multiple calls to db.
So you have Groups and Users. Every Group has zero or more Users; every User has zero or more Groups. A traditional many-to-many relationship.
Normally one would add a User to a Group, or a Group to a User. However you don't have a Group, nor a User, you only have a GroupId and a UserId. and because of the large number of insertions you don't want to fetch the Users and the Groups of which you want to create relations
The problem is, if you could add the GroupId-UserId combination directly to your junction table, how would you know that you wouldn't be adding a Group-User relation that already exists? If you wouldn't care, you'd end up with twice the relation. This would lead to problems: Would you want them to be shown twice if you'd ask the Users of a Group? Which one should be removed if the relation ends, or should they all be removed?
If you really want to implement the possibility of double relation, then you'd need to Implement a a Custom Junction Table as described here The extra field would be the number of relations.
This would not help you with your large batch, because you would still need to fetch the field from the custom junction table to increment the NrOfRelations value.
On the other hand, if you don't want double relations, you'd have to check whether the value already exists, and you didn't want to fetch data before inserting.
Usually the number of additions to a database is far less then the number of queries. If you have a large batch of data to be inserted, then it is usually only during the initialization phase of the database. I wouldn't bother optimizing initialization too much.
Consider remembering already fetched Groups and Users in a dictionary, preventing them to be fetched twice. However, if your list is really huge, this is not a practical solution.
If you really need this functionality for a prolonged period of time consider creating a Stored Procedure that checks if the GroupId / UserId already exists in the junction table, and if not, add it.
See here For SQL code how to do Add-Or-Update
Entity Framework call stored procedure

django get model with foreign key

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).

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.

Rails When using dependent destroy and dependent nullify

I want to know about relation dependent destroy and dependent nullify on rails and relation with SQL.
Thanks
Example:
Table users and table cars
user has many cars
car belongs to users
in table car you have user_id on each row
if you set dependent destroy when defining the relationship in users, then when you delete a user, all cars having that user_id will be deleted also
if you set nullify, cars will remain, but the user_id column will be set to null (it is pointless to have any value there because the user with that id was deleted)
Hope that this helps
You use these options when you want to get rid of orphaned records.
Most common used is destroy because it removes all associated objects one by one.
You can use dependent when we want to get rid of orphaned records since they can lead to various problems. Orphaned records are created when we delete or destroy a model A that was associated with model B, but model B wasn't removed in the process.
You most often want to use destroy - all associated objects will remove one by one.
other common options are:
:delete_all – all associated objects will be deleted in a single query.
:nullify – foreign keys will be set to NULL
You can check more details about this here.

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