html django bookmark button is not changing from 'add' to 'remove'

The bookmark functionality does work. It displays the bookmarked posts in bookmark-list.html. The only problem is that the button is not changing from ‘add’ to ‘remove’.

This is the bookmark form in food.html

{% csrf_token %} {% if is_bookmarked %}

Remove

{% else %}

Add

{% endif %}

These are view logics:
def food(request):
country_list = Country.objects.all()

context = {'country_list ': country_list }
return render(request, 'base/food.html', context)

@login_required
def bookmarkFood(request, post_id):
user = request.user
country = get_object_or_404(Country, id=post_id)
bookmark, created = FoodBookmark.objects.get_or_create(user=user)
is_bookmarked = bookmark.post.filter(id=post_id).exists()

if request.method == "POST":
    if user.is_authenticated:
        if is_bookmarked:
            bookmark.post.remove(jobinfo)
            print('removed')
            print(f"is_bookmarked: {is_bookmarked}")
        else:
            bookmark.post.add(jobinfo)
            print('added')
            print(f"is_bookmarked: {is_bookmarked}")

is_bookmarked = bookmark.post.filter(id=post_id).exists()  

return redirect('food')

models.py
class Country(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name=‘country’)
created = models.DateTimeField(auto_now_add=True)
form_submitted = models.BooleanField(default=False)

class Food(models.Model):
country = models.ForeignKey(Country, on_delete=models.CASCADE)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)

class FoodBookmark(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ManyToManyField(Country, related_name=“bookmarkfood”)

urls.py
path(‘food/’, views.food, name=“food”),
path(‘bookmark-food/int:post_id/’, views.bookmarkFood, name=“bookmarkFood”),

First of all put your code here between (" ``` ", in the beginning and in the end to make a block of code) that make your question code more readable .

  • type your variable " (is_bookmarked) " in your template above the (if) block as ({{is_bookmarked}}) to ensure that this variable returns with a value or not (for debugging)

  • Another thing I think you miss to pass your variable " (is_bookmarked) " in the edit function (def bookmarkFood(request, post_id):), So it’s return empty

good luck

Thank you! You are right the is_bookmarked variable is None in the template. How to pass the variable correctly? I tried many different ways, but it is not working.

You must access and pass your variable in the (def bookmarkFood(request): function itself) not in the(def food(request):)

if request.method == "POST":
    if user.is_authenticated:
        if is_bookmarked:
            bookmark.post.remove(jobinfo)
            print('removed')
            print(f"is_bookmarked: {is_bookmarked}")
            
        else:
            bookmark.post.add(jobinfo)
            print('added')
            print(f"is_bookmarked: {is_bookmarked}")

is_bookmarked = bookmark.post.filter(id=post_id).exists()
context = {'is_bookmarked': is_bookmarked}  
return render(request, 'base/bookmarkfood.html', context)

Thank you. But already tried it and then it is rendering also to the new page. I think the problems goes deeper. The thing is that the bookmark functionality works… but just this button.

I think it’s not deeper , but you haven’t a template for this (bookmarkFood) URL

@login_required
def bookmarkFood(request, post_id):

In your case you redirect from (Edit screen) To (Add screen), And this is not a normal behavior.
The normal case is to redirect From (Add screen) To (Edit screen).

You must know that if you have an (Add screen with a template) you must have an (Edit screen with its template) as a normal behavior. Or you must use (request.path) to differentiate between (Add template inputs and Edit template input) because you relay on ONE template for Add and Edit processes. In your template you can do as the next line

{% url 'food' as add_food_url %}
{% if request.path == add_food_url %}
     ... Do something
{% else %}
   Do another 
{% endif %}

But you must remember that you can not access the (post_id) from the ('food/') URL.

Hope this make sense and help you to find a solution

hey. Thank you appreciate your help. Put this code in def food(request): Now it works.

def food(request):
country_list = Country.objects.all()

if request.user.is_authenticated:
        for country in country_list:
            country.is_bookmarked = FoodBookmark.objects.filter(user=request.user, 
            post=country).exists()

context = {'country_list ': country_list, 'is_bookmarked': True }
return render(request, 'base/food.html', context)

OK, I’m glad to hear that .

But (is_bookmarked) variable will be always “True” this means the button will be always with “Remove” label.

And you said you need to change the button from (“Remove” To “Add”) and vice versa.

Anyways, hope you reach to the good scenario.
Good luck