Trying to implement an "Attending" button. It's simple (or so I thought). A user with a profile clicks "Attending", and a checkmark appears. Can't quite get this to work on the Django/Python side of things. ie: Put that user who clicked 'Attending' into the attendee(list) within the Event.
Template:
{% if is_attending %}
<button class="btn" disabled="disabled">
<i class="icon-ok-sign"></i> Attending
</button>
{% else %}
<form class="left" method="POST" action="/profile/event/{{ event.id }}/">
{% csrf_token %}
<input type="hidden" name="profile_id" value="user" />
<button class="btn">
Attending
</button>
</form>
{% endif %}
Models:
class Event(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
owner = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=200)
location = models.CharField(max_length=200)
start_date = models.DateTimeField(auto_now=False, auto_now_add=False)
end_date = models.DateTimeField(auto_now=False, auto_now_add=False)
about = models.TextField(null=True, blank=True)
attendees = models.ManyToManyField(Profile, null=True, blank=True)
View:
#login_required
def attending_event(request, event_id):
event = get_object_or_404(Event, id=event_id)
if request.method == 'POST':
try:
id = request.POST.get('profile_id')
attendee = Profile.objects.get(id=id)
relationship = Event.objects.create(attendees__user=attendee)
is_attending = True
except:
pass
return HttpResponseRedirect('/profile/event/' + event_id + '/')
else:
if not Event.objects.filter(attendees__user=request.user).exists():
is_attending = False
data = {
'is_attending': is_attending
}
return render_to_response('profiles/event.html', data, context_instance=RequestContext(request))
Maybe there's something I'm missing and can't see what it is I'm doing wrong. But if anyone could offer some insight/advice about how to go about completing this; I'd really appreciate it.
Just giving you hint, change it according to your needs
Template:
{% if is_attending %}
<button class="btn"> # this code will executes when is_attending is True
<i class="icon-ok-sign"></i> Attending
</button>
{% else %}
<form class="left" method="POST" action="/profile/event/{{ event.id }}/"> # Always user reverse urls instead of Hard coded
{% csrf_token %}
<input type="hidden" name="profile_id" value="{{profile.id}}" />
<button class="btn">
Attending
</button>
</form>
{% endif %}
View:
#login_required
def event_profile(request, event_id)
event = get_object_or_404(Event, id=event_id)
if request.method == 'POST':
try:
id = request.POST.get('profile_id')
attendee = Profile.objects.get(id=id)
relationship = Event.objects.create(attendees__user=attendee, .... ) # set other variable you want
is_attending = True
else:
# check in your event either your profile user is already attending or not? and set is_attending variable according to it
data = {
'is_attending': is_attending,
....
}
return render_to_response('my_template.html',
data,
context_instance=RequestContext(request))
Related
I have the following models, and as you can see they are related to each other
class Leads(models.Model):
project_id = models.BigAutoField(primary_key=True, serialize=False)
created_at = models.DateTimeField(auto_now_add=True)
expected_revenue = MoneyField(decimal_places=2,max_digits=14, default_currency='USD')
expected_licenses = models.IntegerField()
country = CountryField(blank_label='(select_country)')
status = models.CharField(choices=[('Open', 'Open'), ('Closed', 'Closed'), ('Canceled', 'Canceled'),
('Idle', 'Idle')
], max_length=10)
estimated_closing_date = models.DateField()
services = models.CharField(choices=[('Illumination Studies', 'Illumination Studies'),
('Training', 'Training'),('Survey Design Consultancy', 'Survey Design Consultancy'),
('Software License', 'Software License'),
('Software Development','Software Development')], max_length=40)
agent = models.ForeignKey(Profile, default='agent',on_delete=models.CASCADE)
company = models.ForeignKey(Company,on_delete=models.CASCADE)
point_of_contact = models.ForeignKey(Client, default='agent',on_delete=models.CASCADE)
updated_at = models.DateTimeField(auto_now=True)
application = models.CharField(choices=[('O&G','O&G'),('Renewables','Renewables'),('Mining','Mining'),
('Other','Other'),('CSS','CSS')],
default='O&G',max_length=20)
sub_category = models.CharField(choices=[('Wind','Wind'),('Geo-Thermal','Geo-Thermal'),('Solar','Solar'),
('Tidal','Tidal')], max_length=20, blank=True)
#property
def age_in_days(self):
today = date.today()
result = self.estimated_closing_date - today
return result.days
def __str__(self):
return f'{self.project_id}'
class LeadEntry(models.Model):
revenue = MoneyField(decimal_places=2,max_digits=14, default_currency='USD',blank=True)
date = models.DateField()
lead_id = models.ForeignKey(Leads,on_delete=models.CASCADE)
id = models.BigAutoField(primary_key=True, serialize=False)
probability = models.DecimalField(max_digits=2, decimal_places=2, default=0, blank=True)
#property
def est_revenue(self):
result = self.revenue * probabiity
return result
Essentially a lead entry is related to the lead, and I'm using HTMX to essentially add data to LeadEntry database using a form.
Form
class LeadEntryForm(forms.ModelForm):
class Meta:
model = LeadEntry
fields = ('lead_id','date','revenue','probability')
widgets = {'date': DateInput()}
I have 2 views, one that will simply pass an HTML with a button for the user to add entries to the database, and another view with the actual form
views
#login_required
def add_to_forecast(request):
id = request.GET.get('project_id')
request.session['lead_id'] = id
return render(request, 'account/lead_forecast.html')
#login_required
def forecast_form(request):
if request.method=='POST':
form = LeadEntryForm(data=request.POST or None)
if form.is_valid():
form.save(commit=False)
messages.success(request,"Successful Submission")
return redirect('add_to_forecast')
lead_id = request.session['lead_id']
data = {'lead_id':lead_id}
context = {
"form":LeadEntryForm(initial=data)
}
return render(request, 'account/lead_entry_forecast.html', context)
Lastly, there are 2 HTML pages, the first one is associated with add_to_forecast and renders a simple page, this is where the HTMX happens and this adds the form from the next HTML page
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load static %}
{% block title %}Client Information {% endblock %}
{% block content %}
<h1> Add Lead to Sales Forecast </h1>
<p>Click the Button below to add a Payment Date</p>
<button type="button" hx-get="{% url 'lead_entry_forecast' %}" hx-target="#leadform" hx-swap="beforeend" >
Add Lead </button>
<div id="leadform">
<br>
</div>
{% endblock %}
The form that is added by the user as many times they want to do so
{% load crispy_forms_tags %}
{% load static %}
{% block content %}
<div class="container-fluid">
<form method="post" enctype="multipart/form-data" action=".">
{% csrf_token %}
<div class="row justify-content-center">
<div class="col-sm-1">
{{ form.lead_id|as_crispy_field }}
</div>
<div class="col-sm-2">
{{ form.date|as_crispy_field }}
</div>
<div class="col-sm-2">
{{ form.revenue|as_crispy_field }}
</div>
<div class="col-sm-1">
{{ form.probability|as_crispy_field }}
</div>
<div class="col-sm">
<input type="submit" value="Submit" >
</div>
</div>
</form>
</div>
<hr>
{% endblock %}
The problem I have is that after submitting the form, everything seems to be working, obviously, at the moment you can only submit one lead, as I still have to add more logic, but at the moment the form is not sending data to the DB, after some debugging, I was not able to pass the POST, it seems like is just not submitting anything.
Any help will be highly appreciated
Update - 12/4/2021
I have tried to submit data using the form and it actually works, so there is nothing wrong with the form submitted the POST.request, if I go directly to the URL, it works fine, so the form is submitted correctly and the database is updated.
I still don't understand why is not working when the form is rendered by the htmx, so it has something to do with that.
When you are designing an HTMX page, you have to be careful with the post request, so I was processing the form in the wrong view, please see below the views:
#login_required
def add_to_forecast(request):
form = LeadEntryForm(data=request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.save()
return HttpResponse("Success")
else:
return render(request, 'account/lead_entry_forecast.html', {"form": form})
id = request.GET.get('project_id')
request.session['lead_id'] = id
return render(request, 'account/lead_forecast.html')
#login_required
def forecast_form(request):
lead_id = request.session['lead_id']
data = {'lead_id':lead_id}
context = {
"form":LeadEntryForm(initial=data)
}
return render(request, 'account/lead_entry_forecast.html', context)
Now it works as it should
I'm stuck I try a lot of things to make it work, but always the same problem the form dose note save the data at all
and the any error that I get is the message error (what I writ in the message)
all i get is a change in the url like this
http://127.0.0.1:8000/appointement/create_appointement_2?patient=patient+12&initial-patient=patient+12&doctor=2&date=2021-04-02&start_time=16%3A30
is there anything that can show me the error or if anyone have this problem be for a few hits will be awesome?
this is my models .py
class Appointment(models.Model):
user_ho_add = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_ho_add_appointment')
patient = models.CharField(null=True,max_length = 200, default=defaultTitle)
doctor = models.ForeignKey(User, on_delete=models.CASCADE, related_name='doctor_app')
date = models.DateField(null=False, blank=False, default=timezone.now)
start_time = models.TimeField(null=True, blank=True, default=timezone.now)
end_time = models.TimeField(null=True, blank=True, default=timezone.now)
and this is my forms.py
class AppointmentForm_2(forms.ModelForm):
doctor = forms.ModelChoiceField(queryset=User.objects.filter(type_of_user=TypeOfUser.DOCTOR))
# patient = forms.ModelChoiceField(queryset=User.objects.filter(type_of_user=TypeOfUser.PATIENT))
date = forms.DateField(widget=forms.DateInput(attrs={'type': 'date'}), input_formats=settings.DATE_INPUT_FORMATS)
start_time = forms.DateField(widget=forms.DateInput(attrs={'type': 'time'}), input_formats=settings.TIME_INPUT_FORMATS)
class Meta:
model = Appointment
fields = ('patient', 'doctor', 'date', 'start_time')
and this is the views.py
#login_required
def create_appointement_2(request):
user = get_user_model()
patients = User.objects.filter(type_of_user=TypeOfUser.PATIENT)
form_appointment_2 = AppointmentForm_2(request.POST or None)
if request.user.is_doctor() or request.user.is_reception():
if request.method=='POST':
form_appointment_2 = AppointmentForm_2(request.POST or None)
user = get_user_model()
if form_appointment_2.is_valid():
form_appointment_2.save(commit=False)
form_appointment_2.user_ho_add = request.user
# form_appointment.end_time = form_appointment.start_time + timedelta(minutes=30)
start_time = form_appointment_2.start_time
future_time = dt.datetime(1970, 1, 1, start_time.hour, start_time.minute, start_time.second, start_time.microsecond) + timedelta(minutes=30)
form_appointment_2.end_time = dt.time(future_time.hour, future_time.minute, future_time.second, future_time.microsecond)
form_appointment_2.save()
messages.success(request, 'appointment added')
else:
messages.error(request, 'Error')
else:
return render(request, 'appointement/add_appointement2.html', {'user_form':form_appointment_2,'patients':patients })
return render(request, 'appointement/add_appointement2.html', {'user_form':form_appointment_2,'patients':patients })
and this the html file
<body>
{% if form.errors %}
<div class="alert alert-danger alert-dismissible col-12 mx-1" role="alert">
<div id="form_errors">
{% for key, value in form.errors.items %}
<span class="fieldWrapper">
{{ key }}:{{ value }}
</span> {% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="container">
<form>
{{ user_form.media }} {{ user_form }} {% csrf_token %}
<button type="submit" value="create_appointment">
ok
</button>
</form>
</div>
</body>
I try to add the error tag, but it shows nothing, all i get is a change in the url like this
http://127.0.0.1:8000/appointement/create_appointement_2?patient=patient+12&initial-patient=patient+12&doctor=2&date=2021-04-02&start_time=16%3A30
if you are getting the data in the url that means you need to add method="POST" to your form tag in the html file
I'm trying to get a list of objects in Django from a model.
I just want to get the list of 'dht node' from the request user, but it shows nothing in the html file (as if the list was empty). The user that I'm using has 2 'dht nodes' and they're shown in the django admin.
I don't know what is wrong, because if I use the instruction "member.dht.create(...)" in the views function and a create a new 'dht node' like this, this is shown. Only 'dht nodes' that I enter by form do not show. Can be the form?
Thanks a lot, Here's my code:
Models.py
class Node(models.Model):
name = models.CharField(primary_key=True, null=False, max_length= 50)
description= models.CharField(default=None, null=False, max_length= 250)
topic=models.CharField(default=None, null=False, max_length= 50, unique=True)
def __unicode__(self):
return self.name
class dht(Node):
temp = models.IntegerField(default=None, null=True)
hum = models.IntegerField(default=None, null=True)
class UserProfile(User):
uid = models.CharField(default=None, null=False, max_length= 250)
dht = models.ManyToManyField(dht, blank=True)
def __unicode__(self):
return self.user.username
Views.py -dht list-
#login_required(login_url = '/web/login')
def listDhtSensor(request):
member = request.user.userprofile
list = member.dht.all()
return render(request, 'web/listDhtSensor.html', {'list':list})
Html -listDhtSensor.html-
{% block content %}
{% for dht in list %}
{{ dht.name }}
{{ dht.topic }}
{% endfor %}
{% endblock %}
Forms.py
class newDHTSensorForm(forms.ModelForm):
class Meta:
model = dht
field = ['name',
'description',
'topic',]
labels = {'name': 'Name' ,
'description': 'Description',
'topic': 'Topic',}
exclude = ['temp', 'hum']
Views.py -dht form-
#login_required(login_url = '/web/login')
def newDHTSensor(request):
if request.method == "POST":
form = newDHTSensorForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('/web/dhtDetail')
else:
form = newDHTSensorForm()
return render(request, 'web/newDhtSensor.html', {'form': form})
Html -newDhtSensor.html-
{% block content %}
<div class="boxReg">
<form method="post">
{% csrf_token %}
<h2>{{ form.name.errors.as_text }}</h2>
<p><label for="id_name">Name:</label> <input class="barraForm" type="text" name="name" maxlength="150" autofocus="" required="" id="id_name"></p>
<p><label for="id_description">Description:</label> <input class="barraForm" type="text" name="description" maxlength="150" id="id_description"></p>
<h2>{{ form.topic.errors.as_text }}</h2>
<p><label for="id_topic">Topic:</label> <input class="barraForm" type="text" name="topic" maxlength="254" id="id_topic"></p>
<div class="boxButtonReg">
<button class="buttonReg" type="submit">Save</button>
</div>
</form>
</div>
{% endblock %}
It shows nothing because you did not link you dht objects to that UserProfile, so if you later query for the dhts for that UserProfile, evidently the list is empty. You should add it to the dht relation, like:
#login_required(login_url = '/web/login')
def newDHTSensor(request):
if request.method == "POST":
form = newDHTSensorForm(request.POST)
if form.is_valid():
post = form.save()
request.user.userprofile.dht.add(post)
return redirect('/web/dhtDetail')
else:
form = newDHTSensorForm()
return render(request, 'web/newDhtSensor.html', {'form': form})
Note that you first need to save the post, so you should omit the commit=False aprameter.
This Code is working perfectly. The only thing I want to change is submit button "Vote" into "Voted" after user voted the option ,instead of displaying error message " You Already Voted".So that the user can know which options he voted already when he logs in to vote the option next time
urls.py
path('<slug>/',views.options,name='options'),
path('<slug>/vote/', views.vote, name='vote'),
models.py
class Category(models.Model):
name = models.CharField(max_length=250)
slug = AutoSlugField(populate_from='name')
details = models.TextField(blank=True)
image = models.ImageField(blank=True,upload_to='categories')
views = models.IntegerField(default=0)
created = models.DateTimeField(auto_now=True)
modified = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Categories"
class Option(models.Model):
name = models.CharField(max_length=250)
slug = AutoSlugField(populate_from='name')
image = models.ImageField(blank=True,upload_to='options')
details = models.TextField()
category = models.ForeignKey(Category, on_delete=CASCADE)
votes = models.IntegerField(default=0)
active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Vote(models.Model):
option = models.ForeignKey(Option, on_delete=CASCADE)
voter = models.ForeignKey(User, on_delete=CASCADE)
slug = AutoSlugField(populate_from='option')
def __str__(self):
return self.voter
views.py
def options(request,slug):
category = Category.objects.get(slug=slug)
category.views += 1
category.save()
options = category.option_set.all().order_by('-votes')
if request.method == "POST":
if request.user.is_authenticated:
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.category = category
comment.user = request.user
comment.save()
messages.success(request, 'Comment Posted.')
else:
messages.error(request, 'You have to login first to give comment')
return redirect('rank:login')
else:
form = CommentForm()
return render(request, 'rank/options.html', {'options': options,'form':form,'title': 'options','category':category})
def vote(request,slug):
if request.user.is_authenticated:
option = Option.objects.get(slug=slug)
category = option.category
if Vote.objects.filter(slug=slug,voter_id=request.user.id).exists():
messages.error(request,'You Already Voted!')
return redirect('rank:options', category.slug)
else:
option.votes += 1
option.save()
voter = Vote(voter=request.user,option=option)
voter.save()
messages.success(request,'Voted.{} peoples also agree with you.'.format(option.votes-1))
return redirect('rank:options',category.slug)
else:
messages.error(request,"You have to login first to vote.")
return redirect('rank:login')
options.html
<ol type="1">
<center>{% bootstrap_messages %}</center>
{% for option in options %}
<div class="col-lg-6 col-md-6 mb-6">
<div class="card h-100">
<div class="card-body">
<b><li>
<img src="/media/{{option.image}}" width="400" height="300">
<h4>{{option.name}}
</h4>
<h5 class="card-text">{{ option.details}}</h5>
<h5>{{ option.votes }} votes</h5>
<form action="{% url 'rank:vote' option.slug %}" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-success" value="Vote" >
</form>
</li></b>
</div>
<div class="card-footer">
<small class="text-muted"></small>
</div>
</div>
</div>
{% empty %}
<div class="card w-100">
<div class="card-body">
<h4>Item not available</h4>
</div>
</div>
{% endfor %}
</ol>
The simplest way to achieve this might be to add an attribute to each option to indicate whether the currently logged in user has voted on that option before you pass the options to the template.
For example:
def options(request,slug):
category = Category.objects.get(slug=slug)
category.views += 1
category.save()
options = category.option_set.all().order_by('-votes')
# Indicate whether the user has voted or not
for option in options:
option.has_voted = option.vote_set.filter(voter=request.user).exists()
...
return render(request, 'rank/options.html', {'options': options,'form':form,'title': 'options','category':category})
And then you can check the has_voted attribute in the template when you render the button:
{% if option.has_voted %}
You already voted
{% else %}
<input type="submit" class="btn btn-success" value="Vote" >
{% endif %}
I'm working on a school project. Right now any user can ask a question.
In order to notify all the users when any users asks a question I've created a new app & notifying them through the simple 'view' whenever a question is asked. But it's just plain notifications yet.
How can I mark them read once a user opens the Notification tab? Just like on social networks!
I suggest you to use ContentType to make a dynamic notifications fo any models. This snippet below is an example how to implement the notification system;
1. in your models.py
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey
from django.utils.translation import ugettext_lazy as _
class ContentTypeToGetModel(object):
"""
requires fields:
- content_type: FK(ContentType)
- object_id: PositiveIntegerField()
"""
def get_related_object(self):
"""
return the related object of content_type.
eg: <Question: Holisticly grow synergistic best practices>
"""
# This should return an error: MultipleObjectsReturned
# return self.content_type.get_object_for_this_type()
# So, i handle it with this one:
model_class = self.content_type.model_class()
return model_class.objects.get(id=self.object_id)
#property
def _model_name(self):
"""
return lowercase of model name.
eg: `question`, `answer`
"""
return self.get_related_object()._meta.model_name
class Notification(models.Model, ContentTypeToGetModel):
# sender = models.ForeignKey(
# User, related_name='notification_sender')
receiver = models.ForeignKey(
User, related_name='notification_receiver')
content_type = models.ForeignKey(
ContentType, related_name='notifications', on_delete=models.CASCADE)
object_id = models.PositiveIntegerField(_('Object id'))
content_object = GenericForeignKey('content_type', 'object_id')
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
STATUS_CHOICES = (
('reply', _('a reply')),
('comment', _('a comment')),
('message', _('a message'))
)
status = models.CharField(
_('Status'), max_length=20,
choices=STATUS_CHOICES, default='comment')
is_read = models.BooleanField(
_('Is read?'), default=False)
def __str__(self):
title = _('%(receiver)s have a %(status)s in the %(model)s:%(id)s')
return title % {'receiver': self.receiver.username, 'status': self.status,
'model': self._model_name, 'id': self.object_id}
class Meta:
verbose_name_plural = _('notifications')
ordering = ['-created']
2. in your views.py
from django.views.generic import (ListView, DetailView)
from yourapp.models import Notification
class NotificationListView(ListView):
model = Notification
context_object_name = 'notifications'
paginate_by = 10
template_name = 'yourapp/notifications.html'
def get_queryset(self):
notifications = self.model.objects.filter(receiver=self.request.user)
# mark as reads if `user` is visit on this page.
notifications.update(is_read=True)
return notifications
3. in your yourapp/notifications.html
{% extends "base.html" %}
{% for notif in notifications %}
{{ notif }}
{# for specific is like below #}
{# `specific_model_name` eg: `comment`, `message`, `post` #}
{% if notif._model_name == 'specific_model_name' %}
{# do_stuff #}
{% endif %}
{% endfor %}
So, when I creat that notifications?
eg: when the other user send a comment to receiver on this post.
from django.contrib.contenttypes.models import ContentType
def send_a_comment(request):
if request.method == 'POST':
form = SendCommentForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
#instance.sender = request.user
...
instance.save()
receiver = User.objects.filter(email=instance.email).first()
content_type = ContentType.objects.get(model='comment')
notif = Notification.objects.create(
receiver=receiver,
#sender=request.user,
content_type=content_type,
object_id=instance.id,
status='comment'
)
notif.save()
How about menu? Like this stackoverflow, facebook, instagram, or else?
you can handle it with templatetags, eg:
# yourapp/templatetags/notification_tags.py
from django import template
from yourapp.models import Notification
register = template.Library()
#register.filter
def has_unread_notif(user):
notifications = Notification.objects.filter(receiver=user, is_read=False)
if notifications.exists():
return True
return False
and the navs.html menu:
{% load notification_tags %}
{% if request.user.is_authenticated %}
<ul class="authenticated-menu">
<li>
<a href="/notifications/">
{% if request.user|has_unread_notif %}
<i class="globe red active icon"></i>
{% else %}
<i class="globe icon"></i>
{% endif %}
</a>
</li>
</ul>
{% endif %}
First you need ManyToManyField for user module who is readed a post.
profile.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
subscribed = models.ManyToManyField(User, related_name='subscribed', blank=True)
readed = models.ManyToManyField("blogs.BlogPost", related_name='readed', blank=True)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.user.username)
class Meta:
ordering = ("-created",)
If you have a blog model like this:
class BlogPost(models.Model):
author = models.ForeignKey(Profile, on_delete=models.CASCADE)
post_title = models.CharField("Post Title", max_length=150, unique=True)
post_content = models.TextField("Content")
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.post_title
class Meta:
ordering = ("-created",)
You need to create a button function in blog posts view.
def mark_as_read_button(request):
if request.method == "POST":
my_profile = Profile.objects.get(user=request.user)
post = request.POST.get("post_pk")
obj = BlogPost.objects.get(pk=post)
if obj in my_profile.readed.all():
my_profile.readed.remove(obj)
else:
my_profile.readed.add(obj)
return redirect(request.META.get("HTTP_REFERER"))
return redirect("blogs:subscribed-blogs")
Then you can use is in the template file like this:
{% extends 'base.html' %}
{% block title %}Subscribed Blog Posts{% endblock %}
{% block content %}
{% for post in posts %}
<h5 class="card-title">{{ post.post_title }}</h5>
{% if post in readed %}
<form action="{% url "blogs:mark_as_read" %}" method="POST">
{% csrf_token %}
<input type="hidden" name="post_pk" value={{ post.pk }}>
<button type="submit" class="btn btn-danger btn-sm">Mark as unread</button>
</form>
{% else %}
<form action="{% url "blogs:mark_as_read" %}" method="POST">
{% csrf_token %}
<input type="hidden" name="post_pk" value={{ post.pk }}>
<button type="submit" class="btn btn-success btn-sm">Mark as read</button>
</form>
{% endif %}
<p class="card-text">{{ post.created }}</p>
<p class="card-body">{{ post.post_content }}</p>
<hr>
{% endfor %}
{% endblock %}
Good coding.