0

I want to know is there any way where we can get the updated many to many field in one model using signals and post them to another model

class Post(models.Model):

    name=models.CharField(max_length=24)
    nc=models.ManyToManyField(settings.AUTH_USER_MODEL)
    def __str__(self):
        return self.name
        # return self.name
m2m_changed.connect(receiver=like_post,sender=Post.nc.through)

I want to collect the updated record in the nc field of post model and using signals I want to create an object using function here is the signal that connects to Post model

def like_post(sender, *args, **kwargs):
    # if kwargs['action'] in ('post_update'):
    if kwargs['action'] in ('post_add', 'post_remove','post_update'):

        print(kwargs['instance'])
        instance = kwargs['instance']
        print(instance)
        notify = Notify.objects.create(
                 recipient=instance,
                 creator=Post.objects.get(pk=50),
                  state='unread',
                   type=kwargs['action'],
                )
    else:
        print('no instance') 

in the recipient and the creator section I want to update those fields with an existing user object the creator is the person who updated the manytomanyfield and the recipient is the person who created that post

notify model:
class Notify(models.Model):
    recipient = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='notify_recipient',on_delete=models.CASCADE)
    creator = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='notify_sender',on_delete=models.CASCADE)
    state = ('read', 'unread', 'unseen')
    type = models.CharField(max_length=30, blank=True)
    url = models.CharField(max_length=50, blank=True)

whenever I run this the instance just prints the post object name and fires this error

ValueError at /admin/posts/post/50/change/
Cannot assign "<Post: ok>": "Notify.recipient" must be a "User" instance.
Alessio
  • 3,404
  • 19
  • 35
  • 48
john
  • 539
  • 2
  • 9
  • 24
  • Well like the error says, recipient is a foreign key to User. Why are you assigning a Post there? – Daniel Roseman Jul 01 '19 at 08:38
  • no the question isnt about the error ,i want to know how to send the Foriegn key user(in the place of recipient) to that object from manytomanyfield in post model through signals – john Jul 01 '19 at 08:45

1 Answers1

1

You can see that your Notify class defines receipent as a ForeignKey element to the AUTH_USER_MODEL, but you are creating a Notify in your signal as:

notify = Notify.objects.create(
                 recipient=instance,
                 creator=Post.objects.get(pk=50),
                  state='unread',
                   type=kwargs['action'],
                )

Here, the instance is an instance of Post rather than User, also you are using post instance in the creator field too. This is what causes the error.

To solve this error, you need to pass the user instance in those fields. For example, you can use something like:

notify = Notify.objects.create(
                     recipient=instance.nc, # find out how to pass the user of the post here
                     creator=Post.objects.get(pk=50), # replace by an user instance here instead of a post instance 
                      state='unread',
                       type=kwargs['action'],
                    )

EDIT: To make sure that the user instance is saved you need to override the save_model method of your ModelAdmin for post model as:

class PostAdmin(admin.ModelAdmin):
    def save_related(self, request, form, formsets, change):
    if not form.cleaned_data['nc']:
        form.cleaned_data['nc'] = [request.user]
    form.save_m2m()
Sanip
  • 1,772
  • 1
  • 14
  • 29
  • Cannot assign ".ManyRelatedManager object at 0x06E5E150>": "Notify.recipient" must be a "User" instance ,i got this error now – john Jul 01 '19 at 08:56
  • and when i print instance.nc the terminal shows up as auth.User.None – john Jul 01 '19 at 09:02
  • It is because even tough the post instance is saved, its user instance is not being saved instantly. So, first you need to make sure that data for nc is saved before the signal is executed. This error is seen in most cases where many-to-many field is used. – Sanip Jul 01 '19 at 09:21
  • i understood it partially but i don't understand one thing the signal gets triggered only if the nc of that post model has been changed right? so in that case why it isnt showing the updated User and can you just elaborate the possible ways to solve this issue – john Jul 01 '19 at 09:33
  • I don't quiet understand your query about using **m2m_changed** signal here. You stated it correct that the signal gets triggered only if the nc of that post model has been changed. So, thinking of activating the signal with change of any other fields rather than nc is of no use. – Sanip Jul 01 '19 at 09:42
  • the reason why i use m2m_changed is to check the followers feature to that particular post, the user may follow that post or unfollow it. so the user who created that post will come to know that the so and so users are following your post – john Jul 01 '19 at 09:50
  • but i cant understand how to add that User foriegnkey thing to the notify model using signals – john Jul 01 '19 at 09:51
  • check my edited answer where I have mentioned how to add the user instance in the post object. – Sanip Jul 01 '19 at 09:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/195792/discussion-between-mounikes-mintu-and-sanip). – john Jul 01 '19 at 10:04