Django Signals how to allow comment from unauthenticated user?

I am trying to create an notification system which will be notify author if any new comment posted in his Blog post. I am getting this error if user is not login and try to post comment.

Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x0000017B3D819CA0>>": "BlogComment.user" must be a "User" instance. 

here is my code:

notifications models.py

class Notifications(models.Model):
    blog = models.ForeignKey('blog.Blog',on_delete=models.CASCADE)
    NOTIFICATION_TYPES = ((1,'Like'),(2,'Comment'), (3,'Follow'))
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="noti_from_user")
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="noti_to_user")
    notification_type = models.IntegerField(choices=NOTIFICATION_TYPES)
  

comment models.py

class BlogComment(models.Model):
      blog = models.ForeignKey(Blog,on_delete=models.CASCADE,null=True, blank=True)
      user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_comment',blank=True,null=True)
      def user_comment(sender, instance, *args, **kwargs):
        comment= instance
        blog = comment.blog
        sender = comment.user
        notify = Notifications(blog=blog, sender=sender, user=blog.author, notification_type=2)
        notify.save()
      
      
post_save.connect(BlogComment.user_comment, sender=BlogComment)  
  

views.py:

if request.method == "POST":
       if comment_form.is_valid():
                isinstance = comment_form.save(commit=False)
                isinstance.user = request.user
                isinstance.blog = blog
                isinstance.save()

how to allow comment from an unauthenticated user ?

Set isinstance to None if request.user is the Anonymous user.

As your instruction I tried this but didn’t work. Where I am doing mistake?

if request.user.is_anonymous:
                    isinstance.user = None

getting this error Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x000001A48DF39EB0>>": "BlogComment.user" must be a "User" instance.

Where is that code in the context of the rest of the view?

here is full code of views.py

def BlogDetail(request,slug=None):
    template_name = 'blog/blog_details.html'
    if slug is not None:
       blog = get_object_or_404(Blog,slug=slug)
    else:
      blog =None

     
    comment_form = CommentFrom(request.POST)
    queryset = BlogComment.objects.filter(is_published="published",blog=blog)
    
    if request.method == "POST":
       if comment_form.is_valid():
                isinstance = comment_form.save(commit=False)
                if request.user.is_authenticated:
                    isinstance.user = request.user
                elif  request.user.is_anonymous: # AnonymousUser code
                    isinstance.user = None
                isinstance.blog = blog
                isinstance.save()
                messages.add_message(request, messages.INFO, 'Your Comment Pending for admin approval')
                return redirect('blog:blog-detail',slug=blog.slug)
       else:
            messages.add_message(request, messages.INFO, 'Somethings Wrong. Please try again')
            

                
    else:
          comment_form = CommentFrom()
          
    context={
          "blog":blog,
          "comment_form":comment_form,
          "queryset": queryset
          
        }
    return  render(request,template_name,context)   

So then where did you insert the code regarding the AnonymousUser?

KenWhitesell I updated my previous reply. please see

And what is the complete error you are receiving with this version of the code?

KenWhitesell I am getting this error when any user trying to comment without login.

NOT NULL constraint failed: notifications_notifications.sender_id

As I am using Django Signals in my comment model so I think it’s not finding sender id for Anonymous user.

Possibly. By the way, that’s not the complete error. Posting a single line of a full traceback is potentially ignoring a lot of useful information. It’s going to be more helpful if you post full tracebacks and not just the bottom line.

KenWhitesell see this

IntegrityError at /blog/hello-world/

NOT NULL constraint failed: notifications_notifications.sender_id

Request Method: POST
Request URL: http://127.0.0.1:8000/blog/hello-world/
Django Version: 3.2.4
Exception Type: IntegrityError
Exception Value: NOT NULL constraint failed: notifications_notifications.sender_id
Exception Location: C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\sqlite3\base.py, line 423, in execute
Python Executable: C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\python.exe
Python Version: 3.9.3
Python Path: [‘P:\django\farhyn’, ‘C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\python39.zip’, ‘C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\DLLs’, ‘C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib’, ‘C:\Users\FARHAN\AppData\Local\Programs\Python\Python39’, ‘C:\Users\FARHAN\AppData\Roaming\Python\Python39\site-packages’, ‘C:\Users\FARHAN\AppData\Roaming\Python\Python39\site-packages\win32’, ‘C:\Users\FARHAN\AppData\Roaming\Python\Python39\site-packages\win32\lib’, ‘C:\Users\FARHAN\AppData\Roaming\Python\Python39\site-packages\Pythonwin’, ‘C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages’]
Server time: Tue, 06 Jul 2021 19:11:55 +0600

Not your browser page, the full traceback from the console where you’re running runserver / runserver_plus / gunicorn / etc. Or, you might possibly need to look in some log file - it really depends upon how you’ve got your server configured.

KenWhitesell here is the full error of my console

Internal Server Error: /blog/hello-world/
Traceback (most recent call last):
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\sqlite3\base.py", line 423, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: notifications_notifications.sender_id

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
    response = get_response(request)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "P:\django\farhyn\blog\views.py", line 48, in BlogDetail
    isinstance.save()
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\mptt\models.py", line 1095, in save
    super().save(*args, **kwargs)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 726, in save
    self.save_base(using=using, force_insert=force_insert,
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 774, in save_base
    post_save.send(
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\dispatch\dispatcher.py", line 180, in send
    return [
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\dispatch\dispatcher.py", line 181, in <listcomp>
    (receiver, receiver(signal=self, sender=sender, **named))
  File "P:\django\farhyn\blog\models.py", line 216, in user_comment
    notify.save()
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 726, in save
    self.save_base(using=using, force_insert=force_insert,
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 763, in save_base
    updated = self._save_table(
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 868, in _save_table
    results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\base.py", line 906, in _do_insert
    return manager._insert(
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\query.py", line 1270, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\models\sql\compiler.py", line 1416, in execute_sql      
    cursor.execute(sql, params)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 98, in execute
    return super().execute(sql, params)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 66, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers  
    return executor(sql, params, many, context)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\utils.py", line 90, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Users\FARHAN\AppData\Local\Programs\Python\Python39\lib\site-packages\django\db\backends\sqlite3\base.py", line 423, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: notifications_notifications.sender_id
[06/Jul/2021 19:22:17] "POST /blog/hello-world/ HTTP/1.1" 500 187004

Yes, I agree - that appears to be the most likely cause.

1 Like

KenWhitesell Do you have any idea how to get sender_id of Anonymous user so that I can pass it through Signals? or any suggestion how to solve this problem?

KenWhitesell I find out an solution if I use author id like this

if request.user.is_authenticated:

                    isinstance.user = request.user
elif  request.user.is_anonymous: # AnonymousUser code

                    isinstance.user = blog.author

it worked but this is not the solution for me. I want to pass actual AnonymousUser id. Can I pass AnonymousUser name as id which he will fill in comment forms.?

There is no AnonymousUser id. It’s not a real user. See the details on AnonymousUser in the docs for the differences between it and a User object.

it’s means AnonymousUser can’t comment in my Blog post when I am using Signals??? can’t we send any info through Signals to AnonymousUse???

Are you talking about “signals” in terms of Django signals, or are you talking about “signals” in terms of browser Server Side Events? Otherwise, it’s unclear to me why you think “signals” has anything to do with this problem.

I am talking about “signals” in terms of Django signals