Reputation: 2527
I'm implementing a feature for an app involving users being able to send event invites to other users. The invite itself needs to be able to get information about the group performing at the event, the info about the event itself (i.e. date/time, venue, location), and info about the sender and recipient. Coming from having worked with databases using PHP, I would more trivially think to create a database table for invite which has fields for the id of the event, the id of the group, and user ids for both the sender and recipient, in addition to the message to be sent with it. This structure would make it so that all invites are stored in the same table and whenever a user wants to check their invites, the app would query that table for all of the rows with their id.
The problem is that for one, django uses models (which I'm not really used to using yet) where the ids are implicitly set every time an object is created. In addition to this, since I'm using the built in model for users, which django provides, I'm not really sure how to go about invoking the user model when creating the invites table. Another idea that I had was to extend Django's user model adding a many to many field which would add foreign keys for the recipient and the sender (both of type user) which would be backward related objects from what I understand. The Django docs advise against this however, so I don't think it would be the best way to structure the invites table.
How should I go about structuring this feature? Any help would be appreciated.
Here is the current implementation I have for the invites table (which is returning a name error for the related name attribute):
class User(AbstractBaseUser):
email = models.EmailField()
# full_name = models.CharField(max_length = 120, blank = True, null = True)
user_name = models.CharField(max_length = 40, unique =True)
USERNAME_FIELD = "user_name"
REQUIRED_FIELDS = ['email']
timestamp = models.DateTimeField(auto_now_add = True, auto_now = False)
updated = models.DateTimeField(auto_now_add = False, auto_now = True)
invites = models.ManyToManyField(
'self', through = 'Invite',
symmetrical = False )
def __unicode__(self):
return self.full_name
def get_full_name():
return self.
class Invite(models.Model):
sender_id = models.ForeignKey(User, related_name= invite_sender, on_delete = models.CASCADE )
recipient_id = models.ForeignKey(User, related_name= invite_recipient, on_delete = models.CASCADE)
concert_id = models.AutoField()
artist_id = models.AutoField()
message = models.CharField(max_length = 120, blank = True, null = True)
date_sent = models.DateTimeField(auto_now_add = True, auto_now = False)
Upvotes: 0
Views: 751
Reputation: 3067
The problem with the related_name is that it should be a string, like so:
sender_id = models.ForeignKey(User, related_name= 'invites_sent', on_delete = models.CASCADE )
recipient_id = models.ForeignKey(User, related_name= 'invites_received', on_delete = models.CASCADE)
this solves your problem with getting the users invites, as that is what a related name is for. assuming you have an user instantiated as this user you can get all the invitations he sent by doing:
invites = thisuser.invites_sent.all()
or al the invitations he received by doing:
invites = thisuser.invites_received.all()
Maybe there's a purpose that I don't know about, since I'm fairly new to all this, but I don't see the point in the concert_id
and the artist_id
field, since they're both auto_field's and are always gonna have the same value, which is also gonna be the same value of the id
field that, as you pointed out, django automatically creates (when you don't have another field set as the primary key for the model).
What I'd do is the following. Define invite as such:
class Invite(models.Model):
sender = models.ForeignKey(User, related_name= 'invites_sent', on_delete = models.CASCADE )
recipient = models.ForeignKey(User, related_name= 'invites_received', on_delete = models.CASCADE)
message = models.CharField(max_length = 120, blank = True, null = True)
date_sent = models.DateTimeField(auto_now_add = True, auto_now = False)
then you could create new invites like this:
from appname.models import User, Invite
inviter = User.objects.get(id=57) #enter whatever id is the inviter's id
invitee = User.objects.get(id=42) #enter id of person that is being invited
new_invite = Invite(sender=inviter, recipient=invitee, message='Hello, you are invited')
new_invite.save()
and get users invites like this:
from appname.models import User, Invite
thisuser = User.objects.get(id=42)
invites_sent_by_user = thisuser.invites_sent.all()
invites_received_by_user = thisuser.invites_received.all()
invites_received_after_march_seventh= thisuser.invites_received.filter(date_sent__gt='2015-03-07')
Since you're able to access the invites through the related_name you specified in the foreign key declaration that manytomanyfield on the user model serves no purpose.
Hope I covered most everything
(there might be typos since I typed all the code here)
Upvotes: 1
Reputation: 4634
Ok so this was originally going to be a comment but I ran over the character limit.
Concert and artist should both be independent models that you ForeignKey to. Sender and Recipient should be User models that you ForeignKey to. Are you intentionally trying to store the IDs and not the actual things themselves? In Django you don't want to store the sender id and perform lookups on it when you need to use it. Rather you want to just ForeignKey link to it from the start and then you directly get information out of it.
Also in your User field I don't necessarily know that it makes sense for the User to keep track of its own invites like that. It seems like you're hacking a ManyToMany into a OneToMany so you could just lookup invites by sender or recipient id when necessary and it would probably be cleaner. The way it is now you'll have to make sure you add all invites to a user and I am always wary of any situation where you have to have one object constantly claiming ownership of another. For instance if you accidentally create code that can create invites without assigning them to a user then you will have invites stuck in the ether. This could be avoided by just looking the pertinent invites up at run time.
I suggest that you read up on using an object relational mapping (ORM) so that this whole process will make more sense.
Upvotes: 1