Search code examples
pythondjangounit-testingview

" 'AnonymousUser' object has no attribute 'Attribute_name' " while perfroming test


The test class :

class UpadtePadlockTest(TestCase):
    username = "testusername"
    email = "[email protected]"
    username2 = "testusername2"
    email2 = "[email protected]"

    def test_update_padlock(self):
        User = get_user_model()    
        user1 = User.objects.create_user(
            self.username, self.email ,
        )
        user2 = User.objects.create_user(
            self.username2, self.email2 , user_locked_with=user1
        )
        user1.user_locked_with=user2
        
        new_padlock= PadLock.objects.create(start_date=datetime.date(datetime.today()),motto_field="Jodo is my motto",creator=user1,modifier=user2)
        
        response = self.client.post(
            reverse('edit_padlock'),
        {'start_date':datetime.date(datetime.today()),
            'motto_field':"Jodo is not my motto"})
        
        self.assertEqual(response.status_code,302)

        new_padlock.refresh_from_db()
        self.assertEqual(new_padlock.motto_field,"Jodo is not my motto")

The view that is causing the problem


def edit_padlock(request):
    # dictionary for initial data with
    # field names as keys
    context ={}
    user = request.user 
# this is the attr that the AnonymousUser is lacking "user_locked_with"
# So filtering users by this attr is not possible 
    user2 = CustomUser.objects.get(username= user.user_locked_with)
    
    # fetch the object related to passed id
    try:
        obj = PadLock.objects.get(modifier=request.user)
    except Exception:
        obj = PadLock.objects.get(creator=request.user)
    
    # pass the object as instance in form
    form = PadLockForm(request.POST or None, instance = obj)
 
    # save the data from the form and
    # redirect to detail_view
    if form.is_valid():
        
        user.lock_published = True 
        user2.lock_published = True
        user.save()
        user2.save()
        form.save()
        try:
            padlock = PadLock.objects.get(modifier=request.user)
            padlock.active_state = True 
            padlock.save()
        except:
            padlock = PadLock.objects.get(creator=request.user)
            padlock.active_state = True 
            padlock.save()
        return HttpResponseRedirect("/")
 
    # add form dictionary to context
    context["form"] = form
 
    return render(request, "edit_padlock.html", context)

My Custom User :

class CustomUser(AbstractUser):
    age= models.PositiveBigIntegerField(null=True,blank=True)
    lock_status = models.BooleanField(default=False)
    lock_count = models.PositiveIntegerField(default=7,validators=[MaxValueValidator(7),MinValueValidator(0)])
    user_is_sender = models.BooleanField(default=False)
    user_is_reciever = models.BooleanField(default=False)
    user_locked_with = models.CharField(max_length=125,null=True,blank=True)
    lock_exist = models.BooleanField(default=False)
    lock_published = models.BooleanField(default=False)

The blog post aka the PadLock model :

class PadLock(models.Model):
    start_date =  models.DateField()
    lock_nature = models.TextField(max_length=5,choices=lock_natures,default=story)
    motto_field = models.CharField(max_length=200)    
    story_field = models.TextField(max_length=20000,blank=True ,validators=[MinLengthValidator(4000)])
    active_state= models.BooleanField(default=False)
    creator = models.OneToOneField(get_user_model(),related_name="creator",on_delete=models.CASCADE,null=True)
    modifier = models.OneToOneField(get_user_model(),related_name="modifier",on_delete=models.CASCADE,null=True)

    def get_absolute_url(self):
        return reverse("padlock_detail", args=[str(self.id)])

I was writing the test for a certain functionality which is modifying a blog post and publishing the post which is referred to as a "padlock" in my code. Should I override the AnonymousUser class ? is there anyway to avoid any unnecessary complications ?


Solution

  • u/Quantra2112 answered the problem on r/djangolearning

    You are getting the user from the request and when that user is not authenticated it will be an instance of AnonymousUser. So you can use the login method on the test client: https://docs.djangoproject.com/en/4.2/topics/testing/tools/#django.test.Client.login

    You should then also protect your view with the login_required decorator: https://docs.djangoproject.com/en/4.2/topics/auth/default/#the-login-required-decorator

    If you don't want to restrict the view to authenticated users I would look for a solution using sessions instead of trying to do anything with the AnonymousUser class. https://docs.djangoproject.com/en/4.2/topics/http/sessions/#module-django.contrib.sessions "

    The solution is using the log in method on the client and adding the decorator @login required on the edit_padlock view.