Search code examples
djangotypeerroradditionattributeerrorbookmarks

Bookmarks in django object got simplelazyobject when adding user instance Why


Have wasted alot of time researching and trying to figure out how to implement bookmarks in django. I tried CBV but i gave up. I tried fbv but I keep on getting this error:

TypeError at 'Bookmark' instance expected, got SimpleLazyObject: User: ****

Here is my View:

@login_required
def company_bookmark(request, slug):
    user = request.user
    model = get_object_or_404(Company, slug=slug)
    if user.is_authenticated:
        if model.bookmark.filter(id=user.id).exists():
            model.bookmark.remove(request.user)
        else:
            model.bookmark.add(request.user)
            return HttpResponseRedirect(model.get_absolute_url())
    else:
        messages.warning(request, 'you must be authenticated first')

I wrap it in condition statement and still got same error, I added the condition in html to no avail

    {% if request.user.is_authenticated %}
    <a href="{% url 'company:bookmark' slug=company.slug %}"
       value="{{ company.slug }}" type="submit" class="btn_1 full-width outline wishlist">
      <i class="icon_heart"></i> Add to Favourite
    </a>
    {% endif %}

I even tried to add id to view like this

model.bookmark.remove(request.user.id)

it bring another error:

AttributeError at
'int' object has no attribute '_state'

Here is model

class Company(models.Model):
    name = models.CharField(max_length=120, help_text='Name of your company', )
    slug = models.SlugField(unique=True, blank=True, null=True)
    bookmark = GenericRelation(Bookmark,  related_query_name='company_bookmark')

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        slug = slugify(self.name)
        self.slug = slug
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('company:detail', kwargs={'slug': self.slug})


class Bookmark(models.Model):
    user = models.ForeignKey(User, on_delete=models.PROTECT)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

and Error

Traceback:

File "C:\Users\postgres\desktop\job\env\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\postgres\desktop\job\env\lib\site-packages\django\core\handlers\base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\postgres\desktop\job\env\lib\site-packages\django\core\handlers\base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\postgres\desktop\job\env\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
  21.                 return view_func(request, *args, **kwargs)

File "C:\Users\postgres\desktop\biz\src\bookmarks\views.py" in company_bookmark
  18.             model.bookmark.add(request.user)

File "C:\Users\postgres\desktop\job\env\lib\site-packages\django\contrib\contenttypes\fields.py" in add
  598.                     check_and_update_obj(obj)

File "C:\Users\postgres\desktop\job\env\lib\site-packages\django\contrib\contenttypes\fields.py" in check_and_update_obj
  585.                         self.model._meta.object_name, obj

Exception Type: TypeError at /company/inceptor-kenya/bookmark
Exception Value: 'Bookmark' instance expected, got <SimpleLazyObject: <User: Gracelynn>>

If I can get help I would be much grateful. Thanks in advance.


Solution

  • The error is raised because you need to add a Bookmark instance and not an User instance to model.bookmark (where model is a Company instance).

    Your code:

    if model.bookmark.filter(id=user.id).exists():
        model.bookmark.remove(request.user)
    else:
        model.bookmark.add(request.user)
    

    That could be reworked to something like this, for example:

    # search bookmarks of this 'Company' with this 'user'
    bookmark = model.bookmark.filter(user=user).first()
    
    if bookmark is not None:
        bookmark.delete()
    else:
        bookmark = Bookmark()
        bookmark.user = request.user
        bookmark.content_object = model
        bookmark.save()