Django model design best practice guidance

119 views
Skip to first unread message

Joshua Corlin

unread,
Dec 8, 2022, 11:04:58 AM12/8/22
to Django users
Hello Django Community,  

I am working on implementing a feature in a project that I built and I am looking for some guidance on how implement the database side of this feature most efficiently.

The models in question:
The two models in question are the user model and a model that tracks tickets raised by users.   A ticket has a requester, self explanatory, and an owner, the owner being the person who winds up getting assigned and working the ticket to action the underlying request.   Both of these columns on tickets are foreign keys to user.  

example models
User:
id = auto pk
username = charfield
other things....

Ticket:
id = auto pk
requester = fk to user
owner = fk to user
other things....

The problem Im now trying to solve:
We have a desire to be able to allow other users outside the requestor/owner to get notified in the event of a ticket being updated by either the owner or the requestor, effectively a list of subscribers.  What would be the best practice for implementing a column to track 1 or more subscribers from a user model to some other model using a single column in a project like this?
  
My initial brainstorming: 
I am sending notifications using logic that just requires username so I know I could just store a list of users in a charfield but ive got to imagine theres a more elegant way of doing this.  Is this a use case for a manytomany field?  Ive not used this field before so if it is im having a hard time wrapping my head around how this would work in this use case.  

Any guidance from the community on this would be greatly appreciated!

Mike Dewhirst

unread,
Dec 8, 2022, 7:02:05 PM12/8/22
to django...@googlegroups.com
On 9/12/2022 3:04 am, Joshua Corlin wrote:
Ive not used this field before so if it is im having a hard time wrapping my head around how this would work in this use case. 

Many-to-many is simple to conceptualise if you realise it is not a field in the table you think it is.

It is actually a separate table containing two foreign key fields. One points to a particular record in your target table and the other points to a particular target record in either the same table or a different table.

Django makes this easy by defining a many-to-many field in the model definition but it actually uses that definition to create the separate relationship table (the "through" table) with two foreign keys.

The nice thing is the "through" model can also be included explicitly among other model definitions. Doing so lets you add other fields to it which can describe the relationship.

It is definitely worthwhile studying the docs to get this right because it lets you model the real world much more accurately.

There are migration gotchas when you explicitly define models which have already been created implicitly with Django's many-to-many field but there are documented solutions.

Cheers

Mike

-- 
Signed email is an absolute defence against phishing. This email has
been signed with my private key. If you import my public key you can
automatically decrypt my signature and be sure it came from me. Just
ask and I'll send it to you. Your email software can handle signing.
OpenPGP_signature

Joshua Corlin

unread,
Dec 8, 2022, 8:37:19 PM12/8/22
to Django users

Thanks Mike, i think the lack of understanding of the underlying implementation is what was tripping me up.  Data tracked by this "field" actually being a different table at the DB level makes complete sense. I have added the M2M field to my ticket model and now have this working at the DB level.  

For anyone who stumbles on this in the future, lets take my sudo-models below, if i add a field subscribers to ticket, as a M2M field to User, I can now add 1 or more User objects to said "field" which is actually a table, in this example appname_ticket_subscribers which i can add/remove users to with ticket.subscribers.[add/remove].(userObject).  

example models
User:

username = charfield
other things....


Ticket:

requester = fk to user
owner = fk to user
subscribers = models.ManyToManyField(User) <-- the new field
other things....

and in the DB 
db=# select * from app_ticket_subscribers;
 id | ticket_id | user_id
----+---------------+---------
  1 | 000001      |       1
(1 row)



The relevant KB for anyone trying to implement a similar thing:
https://docs.djangoproject.com/en/4.1/topics/db/examples/many_to_many/
Reply all
Reply to author
Forward
0 new messages