Reputation: 451
I'm working on project managment tool for improve my django-skills.
I have a problem with contenttypes.
I have next models:
Project
Ticket - has ForeignKey to Project
Discussion - has ForeignKey to Project
Comment - has ForeignKey to Discussion
UserProfile - extension of django User
ProfileWatch - Projects or Discussions which users watch, contenttype use here
ProfileActions - contains users actions (add comment to discussion, start discussion, add ticket) contenttype also use here. Records in this table creating by signals from Ticket, Discussion and Comment
User recive notification about things that he watch(somebody leave new comment or start discussion or add ticket).
In view I get all notification for current user.
I know wich objects(Project, Discussion) have user actions but I don't know which object trigger this UserAction(Ticket, Comment, Discussion).
Ideally in template I need something like this (in brackets fields of ProfileAction model):
13:55 19.11.2012(action_date) admin(profile) add ticket(action_type) deploy this(?) to JustTestProject(content_object)
But now I have this:
13:55 19.11.2012(action_date) admin(profile) add ticket(action_type) to JustTestProject(content_object)
Any ideas about how organize models for store trigger objects?
Thanks for any help
View:
from django.views.generic import ListView
from app.models import ProfileAction
class ActionsList(ListView):
context_object_name = "actions"
template_name = 'index.html'
def get_queryset(self):
profile = self.request.user.get_profile()
where = ['(content_type_id={0} AND object_id={1})'.format(\
x.content_type_id,\
x.object_id\
) for x in profile.profilewatch_set.all()\
]
recent_actions = ProfileAction.objects.extra(
where=[
' OR '.join(where),
'profile_id={0}'.format(profile.pk)
],
order_by=['-action_date']
)
return recent_actions
Models:
#models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _
class UserProfile(models.Model):
user = models.OneToOneField(User, verbose_name=_("Django user"))
first_name = models.CharField(_("First name"), blank=True, max_length=64, null=True)
last_name = models.CharField(_("Last name"), blank=True, max_length=64, null=True)
info = models.TextField(_("Additional information"), null=True)
phone = models.CharField(verbose_name=_("Phone"), max_length=15, blank=True, null=True)
class ProfileWatch(models.Model):
profile = models.ForeignKey(to=UserProfile, verbose_name=_(u"User profile"))
start_date = models.DateTimeField(verbose_name=_(u"Start date"), auto_now_add=True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class ProfileAction(models.Model):
ACTION_TYPE_CHOICES = (
(0, _(u"Add comment")),
(1, _(u"Add discussion")),
(2, _(u"Add ticket")),
)
profile = models.ForeignKey(to=UserProfile, verbose_name=_(u"User profile"))
action_date = models.DateTimeField(verbose_name=_(u"Start date"), auto_now_add=True)
action_type = models.PositiveSmallIntegerField(
verbose_name=_("Status"),
choices=ACTION_TYPE_CHOICES
)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Project(models.Model):
title = models.CharField(_("Project title"), max_length=128)
description = models.TextField(_("Project description"), blank=True, null=True)
members = models.ManyToManyField(UserProfile, through='Participation', verbose_name=_("Members"), blank=True, null=True)
actions = generic.GenericRelation(ProfileAction)
class Ticket(models.Model):
title = models.CharField(_("Title"), max_length=256)
project = models.ForeignKey('Project', verbose_name=_("Project"))
description = models.TextField(_("Ticket description"), blank=True, null=True)
creator = models.ForeignKey(UserProfile, verbose_name=_("Creator"), related_name='created_tickets')
@receiver(post_save, sender=Ticket)
def add_action_for_ticket(sender, instance, created, **kwargs):
if created:
ProfileAction.objects.create(
profile=instance.creator,
action_type=2,
content_object=instance.project
)
class Discussion(models.Model):
project = models.ForeignKey(
to=Project,
verbose_name=_(u"Project"),
)
creator = models.ForeignKey(
to=UserProfile,
verbose_name=_(u"Creator"),
)
updated = models.DateTimeField(
verbose_name=_("Last update"),
auto_now=True
)
title = models.CharField(
verbose_name=_(u"title"),
max_length=120
)
actions = generic.GenericRelation(ProfileAction)
@receiver(post_save, sender=Discussion)
def add_action_for_discussion(sender, instance, created, **kwargs):
if created:
ProfileAction.objects.create(
profile=instance.creator,
action_type=1,
content_object=instance.project
)
class Comment(models.Model):
discussion = models.ForeignKey(
to=Discussion,
verbose_name=_(u"Discussion")
)
creator = models.ForeignKey(
to=UserProfile,
verbose_name=_(u"Creator"),
)
pub_date = models.DateTimeField(
verbose_name=_("Publication date"),
auto_now_add=True
)
text = models.TextField(
verbose_name=_("Comment text")
)
@receiver(post_save, sender=Comment)
def add_action_for_comment(sender, instance, created, **kwargs):
if created:
ProfileAction.objects.create(
profile=instance.creator,
action_type=0,
content_object=instance.discussion
)
Upvotes: 3
Views: 939
Reputation: 451
I solved the problem. Just add next adtitional fileds to ProfileAction model and change signals handlers.
trigger_content_type = models.ForeignKey(ContentType, related_name='triggers')
trigger_id = models.PositiveIntegerField()
trigger_object = generic.GenericForeignKey('trigger_content_type', 'trigger_id')
Upvotes: 1