4

I am trying to make a wall in Django and I have reached an important design decision.

I have the following classes:

WallPost, UserProfile, Group, Event

The issue is that I have Users profiles, events and groups that all will have walls which can be posted to. Hence I can't make a foreign key relations from user who posted to the model which is being posted to because there are multiple models that could be posted(unless I use a generic key but I feel there must be some enclosure for all the wallposts like a wall object).

I then thought of having an intermediate type of object like a wall which the wallposts would ForeignKey to and then then the User Group and Event would foreignkey to a wall. This also seems inefficient to me because the wall doesn't have anything to store and would just be more of a enclosure object.

What is best practice when using ForeignKeys and ManyToManyFields and GenericForeignKeys in django? As in how do you tell which way the relationship should go?

Thanks for all the input.

Kara
  • 6,115
  • 16
  • 50
  • 57
Mohammed
  • 107
  • 6
  • I would use the Wall object strategy. It's efficient and makes sense – Will Aug 07 '12 at 16:19
  • The wall wouldn't have any data to hold though so it seems like a waste. – Mohammed Aug 07 '12 at 16:53
  • Could you please elaborate? What is access control? – Mohammed Aug 07 '12 at 17:05
  • 2
    in this case, limiting users and/or groups of users who can view, post, edit posts on the wall. Might make sense to place this logic and data in Wall. In general, Wall might start out light-weight but my instinct tells me you'll end up being glad you separated it, because there will probably be logic and/or data you'll want to put there. – Will Aug 07 '12 at 17:48
  • Yeah I think you're right. I'm sure there are things out there which I have not considered in my initial design. I think Im going to go with creating an encompassing wall object. – Mohammed Aug 07 '12 at 18:06

1 Answers1

2
class WallPost(models.Model):
    text = models.TextField()

class UserProfile(models.Model):
    name = models.CharField(max_length=128)
    wall_posts = models.ManyToManyField(WallPost, through='UserWall')

class UserWall(models.Model):
    profile = models.ForeignKey(UserProfile)
    post = models.ForeignKey(WallPost)

#same for groups
class Group(models.Model):
    name = models.CharField(max_length=128)
    wall_posts = models.ManyToManyField(WallPost, through='GroupWall')

class GroupWall(models.Model):
    group = models.ForeignKey(Group)
    post = models.ForeignKey(WallPost)

UserWall.objects.filter(profile_id=profile.id).select_related('post')
GroupWall.objects.filter(group_id=group.id).select_related('post')

#or
group = Group.objects.get(id=1).select_related('wall_posts')
posts = group.wall_posts.all()

or

class Wall(models.Model):
    TYPE = (
        (0, 'User'),
        (1, 'Group'),
        (2, 'Event'),
    )

    source = IntegerField() #id of user/group/event
    source_type = SmallIntegerField(choices=TYPE)


class WallPost(models.Model):
    text = models.TextField()
    wall = models.ForeignKey(Wall)

I would have done it so.

darthwade
  • 1,434
  • 1
  • 10
  • 5
  • you don't want profile on Wall, because Groups and Events can have walls as well. – Will Aug 07 '12 at 17:45
  • @Vadym I wanted to avoid making a wall for each type because it seems like a more generic design would be more elegant and would make expanding later down the line more simple. – Mohammed Aug 07 '12 at 18:04