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.
Related
I have django app with authentication in it. I have forms.py file like this:
<form class="login_form" method="post" novalidate>
{% csrf_token %}
<div class="col-md-3 col-md-auto text-center">
<b>First Name:<b>
{{ form.first_name }}
{% if 'first_name' in error %}
<div style='color:red'>{{error.first_name.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>Last Name:<b>
{{ form.last_name }}
{% if 'last_name' in error %}
<div style='color:red'>{{error.last_name.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>username:<b>
{{ form.username }}
{% if 'username' in error %}
<div style='color:red'>{{error.username.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>Email:<b>
{{ form.email }}
{% if 'email' in error %}
<div style='color:red'>{{error.email.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>Password<b>
{{ form.password }}
{% if 'password' in error %}
<div style='color:red'>{{error.password.0.message}}</div>
{% endif %}
</div>
<div class="col-md-3 col-md-auto text-center">
<b>Confirm password:<b>
{{ form.confirm_password }}
{% if 'confirm_password' in error %}
<div style='color:red'>{{error.confirm_password.0.message}}</div>
{% endif %}
</div>
<button type="submit" class="submit_btn">Sign Up</button>
<span class="peder"><p>If you already have account<br>Login</p></span>
</form>
and forms.py:
class CustomerSignUpForm(UserCreationForm):
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
email = forms.EmailField(required=True)
username = forms.CharField(max_length=40)
password = forms.CharField(max_length=30)
confirm_password = forms.CharField(max_length=30)
class Meta(UserCreationForm.Meta):
model = User
#transaction.atomic
def save(self):
user = super().save(commit=False)
user.is_customer = True
user.save()
customer = Customer.objects.create(user=user)
customer.first_name = self.cleaned_data.get('first_name')
customer.last_name = self.cleaned_data.get('last_name')
customer.username = self.cleaned_data.get('username')
customer.email = self.cleaned_data.get('email')
customer.password = self.cleaned_data.get('password')
customer.confirm_password = self.cleaned_data.get('confirm_password')
customer.save()
return user
My model looks like this:
class User(AbstractUser):
is_customer = models.BooleanField(default=False)
is_employee = models.BooleanField(default=False)
# first_name = models.CharField(max_length=100)
# last_name = models.CharField(max_length=100)
signup_confirmation = models.BooleanField(default=False)
class Customer(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE, primary_key = True)
first_name = models.CharField(max_length=100, blank=True)
last_name = models.CharField(max_length=100, blank=True)
username = models.CharField(max_length=40, blank=True)
email = models.EmailField(max_length=40, blank=True)
password = models.CharField(max_length=30, blank=True)
confirm_password = models.CharField(max_length=30, blank=True)
So when user clicks submit button on signup form it should save the form and send him an email.
view
class customer_register(CreateView):
model = User
form_class = CustomerSignUpForm
template_name = 'authentication/customer_register.html'
def form_valid(self, form):
user = form.save()
# current_site = get_current_site(request)
current_site = '127.0.0.1:8000'
subject = 'Please Activate Your Account'
message = render_to_string('authentication/email/activation_request.html', {
'user': user,
'domain': current_site,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user),
})
send_mail(
subject,
message,
'from#example.com',
['to#example.com'],
fail_silently=False,
)
return redirect('/')
But when I click submit button on my page nothing happens. In my terminal I do get [13/Sep/2022 08:18:39] "POST /accounts/customer_register/ HTTP/1.1" 200 9660 but user is not created and email is not sent. Could someone explain why this is happening and present the solution? Thanks:)
First of all.
We need to install few dependencies.
1. pip install django-crispy-forms
2. add 'crispy_forms', to your INSTALLED_APPS in your projects settings.py
3. add CRISPY_TEMPLATE_PACK = 'bootstrap4' to your settings.py
authentication/customer_register.html
We simplify the form through crispy forms that gives us a bootstrap 4 result.
{% load crispy_forms_tags %}
<form class="login_form" method="post" novalidate>
{% csrf_token %}
{% crispy form %}
<button type="submit" class="btn btn-success mt-3 float-end">Submit</button>
</form>
forms.py
We create a modelForm taking the model User and its fields as Meta:
from django import forms
class CustomerSignUpForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email',
'username', 'password', 'confirm_password']
views.py
#The generic view CreateView Polymorphism already benefits of the post method that will save the user
from django.views.generic import CreateView
from.forms import CustomerSignUpForm
class CustomerRegisterCreateView(CreateView):
model = User
form_class = CustomerSignUpForm
template_name = 'authentication/customer_register.html'
urls.py
We create a path so we can link it to a URL with not forgetting the .as_view() as it is a class based view ( function based views do not require this )
from .views import (
CustomerRegisterCreateView,
)
urlpatterns = [
path('customer-register/', CustomerRegisterCreateView.as_view(), name="customer-register"),
]
models.py
Once a user is created, we use a signal that will trigger on user creation.
from django.db.models.signals import post_save
def User_receiver(sender, instance, created, *args, **kwargs):
if created:
print('we went thought the User signal !')
subject = "Welcome"
email_template_name = "authentication/Register-email.txt"
user = User.objects.get(username=instance.username)
c = {
'username': user,
}
email = instance.email
email_1 = render_to_string(email_template_name, c)
send_mail(subject, email_1, 'your_email',
[email], fail_silently=False)
'''
post_save.connect(User_receiver, sender=User)
I am struggling with my code. I want to show data from a specific user on screen. When the second dropdown is selected with the user from a specific group, I want his records to be shown on screen. But what ever I try, the data stays the same from one user. In a later stadium I want to make an Else and say if there is no data, that there is no data of the person. Should I do something with a jquery, or is there an easier way to solve this?
The first dropdown is the group, the second dropdown the user.
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class DisplayGroups(models.Model):
group_name = models.CharField(max_length=200)
def __str__(self):
return self.group_name
class DisplayUsername(models.Model):
username = models.CharField(max_length=100)
def __str__(self):
return self.username
class CijferLijst(models.Model):
name = models.CharField(max_length=200, default='')
vak1 = models.CharField(max_length=200, default='')
cijfer1 = models.DecimalField(max_digits=3, decimal_places=1, default='1.0')
vak2 = models.CharField(max_length=200, default='')
cijfer2 = models.DecimalField(max_digits=3, decimal_places=1, default='1.0')
username = models.ForeignKey(User, on_delete=models.CASCADE, default='')
def __str__(self):
return '%s %s %s %s %s %s'%(self.name, self.vak1, self.cijfer1, self.vak2, self.cijfer2, self.username)
bekijk.html
{% extends 'home/base.html' %}
{% block title %}Cijfers studenten{% endblock %}
{% block javascript %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(document).ready(function()
{
var $select1 = $('#groupdd1'),
$select2 = $('#userdd1'),
$options = $select2.find('option');
$select1.on('change', function()
{
$select2.html($options.filter('[value="'+this.value+'"]'));
}).trigger('change');
});
</script>
{% endblock %}
{% block content %}
{% if user.is_staff %}
<h1>Studentresultaten</h1>
<select id="groupdd1">
<option disabled="true" selected>Kies een groep</option>
{% for result in DisplayGroups %}
<option>{{result}}</option>
{% endfor %}
</select>
<select id="userdd1">
<option disabled="true" selected>Kies een gebruiker</option>
{% for result in DisplayUsername %}
<option value="{{result.username}}">{{result}}</option>
{% endfor %}
</select>
{% endif %}
<br/>
{% for antwoord in CijferLijst %}
<h2>{{antwoord.name}}</h2>
<div class="container px-4">
<div class="row justify content-start gx-5">
<div class="col-5 border bg-light"><strong>Vaknaam</strong></div>
<div class="col-5 border bg-light"><strong>Cijfer</strong></div>
</div>
<div class="row gx-5 justify-content-start">
<div class="col-5 border bg-light">{{antwoord.vak1}}</div>
<div class="col-5 border bg-light">{{antwoord.cijfer1}}</div>
</div>
<div class="row gx-5 justify-content-start">
<div class="col-5 border bg-light">{{antwoord.vak2}}</div>
<div class="col-5 border bg-light">{{antwoord.cijfer2}}</div>
<div class="col-5 border bg-light">{{antwoord.username}}</div>
</div>
</div>
{% endfor %}
{% endblock %}
views.py
from django.shortcuts import render, redirect
from .models import DisplayGroups, DisplayUsername, CijferLijst
from .forms import Grades
from django.contrib.auth.models import User, Group
# Create your views here.
def index(request):
response = redirect('/login')
return response
def home(response):
return render(response, "home/home.html")
def bekijk(request):
DisplayGroup = Group.objects.all()
print(DisplayGroup)
DisplayNames = User.objects.all()
print(DisplayNames)
Cijfer = CijferLijst.objects.all()
print(Cijfer)
return render(request, "home/bekijk.html",
{"DisplayGroups": DisplayGroup, "DisplayUsername": DisplayNames, "CijferLijst": Cijfer})
def cijfers(request):
if request.method == "POST":
form = Grades(request.POST)
if form.is_valid():
form.save()
print(form)
return redirect('gelukt')
else:
form = Grades()
return render(request, "home/cijfers.html", {"form":form})
def done(response):
return render(response, "home/gelukt.html")
forms.py
from django import forms
from .models import CijferLijst
from django.contrib.auth.models import User
class Grades(forms.ModelForm):
name = forms.CharField(max_length=200)
vak1 = forms.CharField(max_length=200)
cijfer1 = forms.DecimalField(max_digits=3, decimal_places=1)
vak2 = forms.CharField(max_length=200)
cijfer2 = forms.DecimalField(max_digits=3, decimal_places=1)
username = forms.ModelChoiceField(queryset=User.objects.all())
check = forms.BooleanField()
class Meta:
model = CijferLijst
fields = ['name', 'vak1', 'cijfer1', 'vak2', 'cijfer2', 'username']
Thanks in advance.
I am trying to add a comment section to add a comment section to my blog detail using django but when i run my server i get no error in the development server and the comments are not being displayed. I added the comments from my admin site.
The snippet of my code is below.
views.py
from .models import Post
from django.utils import timezone
from .forms import PostForm, CommentsForm
from django.contrib.auth.decorators import user_passes_test
# Create your views here.
def home(request):
return render (request, 'blogapp/home.html')
def blog_list(request):
post = Post.objects.order_by('-published_date')
context = {
'posts':post
}
return render(request, 'blogapp/blog_list.html', context)
def blog_detail(request, pk=None):
detail = Post.objects.get(pk=pk)
context = {
'detail': detail
}
return render(request, 'blogapp/blog_detail.html', context)
def add_post(request, pk=None):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid:
body = form.save(commit=False)
body.published_date = timezone.now()
body.save()
return redirect('blog_list')
form = PostForm()
else:
form = PostForm()
context = {
'form': form
}
return render(request, 'blogapp/add_post.html', context)
def add_comments(request, pk=None):
if request.method == "POST":
form = CommentsForm(request.POST)
if form.is_valid:
comment = form.save(commit=False)
comment.date_added = timezone.now()
comment.save()
return redirect('blog_detail')
form = CommentsForm()
else:
form = CommentsForm()
context = {
'form': form
}
return render(request, 'blogapp/add_comments.html', context)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name="homepage"),
path('blog/', views.blog_list, name="blog_list"),
path('blog/post/<int:pk>/', views.blog_detail, name="blog_detail"),
path('blog/add_post/', views.add_post, name="add_post"),
path('blog/add_comments/', views.add_comments, name="add_comments"),
]
forms.py
from django import forms
from .models import Post, Comments
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('author', 'title', 'post_description', 'image', 'image_description', 'body',)
class CommentsForm(forms.ModelForm):
class Meta:
model = Comments
fields = ('post', 'name', 'body',)
models.py
from django.db import models
from django.utils import timezone
# Create your models here.
class Post(models.Model):
author = models.ForeignKey('auth.user', on_delete=models.CASCADE)
title = models.CharField(max_length=300)
body = models.TextField()
post_description = models.CharField(max_length=500, blank=True, null=True)
image = models.ImageField(blank=True, null=True, upload_to="image/")
image_description = models.CharField(max_length=500, blank=True, null=True)
published_date = models.DateTimeField(default=timezone.now, blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
class Comments(models.Model):
post = models.ForeignKey('Post', related_name="comments", on_delete=models.CASCADE)
body = models.TextField()
name = models.CharField(max_length=300)
date_added = models.DateTimeField(default=timezone.now, blank=True, null=True)
def __str__(self):
return '%s - %s' % (self.post.title, self.name)
blog_detail.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<article>
<strong>
<h1><b>{{ detail.title }}</b></h1>
</strong>
<h3>POST AUTHOR: {{ detail.author }}</h3>
<h4><i>{{ detail.post_description }}</i></h4>
<h4>PUBLISHED:{{ detail.published_date }}</h4>
<p>
<hr>
{% if detail.image %}
<center>
<br>
<img src="{{ detail.image.url }}" width="1000" height="700">
<br><br>
<i>IMAGE DESCRIPTION: {{ detail.image_description }}</i>
</center>
{% endif %}
<hr>
<br><br><br>
{{ detail.body|linebreaksbr }}
</p>
<hr class="solid">
<h2>COMMENTS ...</h2>Add One
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}-{{ comment.date_added }}
</strong>
{{ comment.body }}
{% endfor %}
</article>
{% endblock %}
add_comments.html
{% extends 'base.html' %}
{% block content %}
<article>
{% if user.is_authenticated %}
<h1>CREATE NEW BLOG POST.</h1>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">ADD COMMENT</button>
<input type="hidden" name="next" value="{% url 'blog_detail' pk=post.pk %}"/>
</form>
{% else %}
<h2>Login HERE to add comments.</h2>
{% endif %}
</article>
{% endblock %}
in your template you use
{% for comment in post.comments.all %}
but in template context there is no post variable
you should use {% for comment in detail.comments.all %}
I created a model and respective ModelForm, view and Template for it, but ModelForm does not save data to the model even though .save() function is used.
I have tried reviewing forms and views but I do not know what is wrong.I have posted the respective models, forms, views and templates in the question.
models.py:
class Centre(models.Model):
Location = (
('rashmi_heights', 'Rashmi Heights Centre'),
('Levana', 'Levana Centre')
)
name= models.CharField(max_length=50, blank=False, choices=Location, unique=True)
address = models.CharField(max_length =250)
contact = models.CharField(max_length=100, blank=False)
phone = PhoneField(blank=True, help_text='Contact phone number')
def __str__(self):
return self.name
forms.py:
class CentreForm(forms.ModelForm):
class Meta():
model = Centre
fields = '__all__'
views.py:
def centre(request):
forms = CentreForm()
if request.method == 'POST':
forms = CentreForm(request.POST)
if forms.is_valid():
centre = forms.save(request.POST)
centre.save()
else:
forms = CentreForm()
return render(request,'NewApp/centreinfo.html',{'forms':forms})
template:
<!DOCTYPE html>
{% extends 'NewApp/base.html' %}
{% load staticfiles %}
{% block body_block %}
<div class="jumbotron">
<h2>Fill details about your centre.</h2><br>
<h3> </h3>
<form method="post" enctype="multipart/form-data">
{{forms.as_p}}
{% csrf_token %}
<a class="btn btn-primary" href="{% url 'NewApp:centreinfo' %}">Submit</a>
</form>
</div>
{% endblock %}
forms.py:
class CentreForm(forms.ModelForm):
class Meta: -> change here
model = Centre
fields = '__all__'
def centre(request):
forms = CentreForm()
if request.method == 'POST':
forms = CentreForm(request.POST)
if forms.is_valid():
forms.save(request.POST)
else:
forms = CentreForm()
return render(request,'NewApp/centreinfo.html',{'forms':forms})
html
<form method="post" enctype="multipart/form-data">
{{forms.as_p}}
{% csrf_token %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
I've created a new form for comments the articles on a website. When I add the new comment from django admin everything works ok, but when I try to add the new comment directly from detail page nothings happen and I'am redirecting to the page with list of articles.
here are my files
models.py:
class Komentarz(models.Model):
post = models.ForeignKey(Wpisy, related_name="komentarze", verbose_name="Komentarze do artykułu", on_delete=models.CASCADE)
name = models.CharField(max_length=80, verbose_name="Imię")
email = models.EmailField(verbose_name="Email")
content = models.TextField(verbose_name="Treść komentarza")
created_date = models.DateTimeField(verbose_name="Utworzono", auto_now_add=True)
active = models.BooleanField(verbose_name="Aktywny?", default=True)
class Meta:
ordering = ('created_date',)
verbose_name="Komentarz"
verbose_name_plural="Komentarze"
def __str__(self):
return 'Komentarz dodany przez {} dla strony {}'.format(self.name, self.post)
vies.py with the function of details
from django.shortcuts import render, get_object_or_404
from .models import Wpisy, Komentarz
from .forms import KomentarzeForma
....
def detale_bajki(request, slug, ):
detale_bajki = get_object_or_404(Wpisy, slug=slug)
komentarze = detale_bajki.komentarze.filter(active=True)
if request.method == 'POST':
formularz_komentarza = KomentarzeForma(data=request.POST)
if formularz_komentarza.is_valid():
nowy_komentarz = formularz_komentarza.save(commit=False)
nowy_komentarz.detale_bajki = detale_bajki
nowy_komentarz.save()
else:
formularz_komentarza = KomentarzeForma()
return render(request, 'bajki/detale_bajki.html', {'detale_bajki': detale_bajki, 'komentarze': komentarze, 'formularz_komentarza': formularz_komentarza})
forms.py
from .models import Komentarz
from django import forms
class KomentarzeForma(forms.ModelForm):
class Meta:
model = Komentarz
fields = ('name', 'email', 'content')
and detail.html
...
{% with komentarze.count as total_komentarze %}
<h2>
{{ total_komentarze }} komentarz{{ total_komentarze|pluralize:"y" }}
</h2>
{% endwith %}
{% for komentarz in komentarze %}
Komentarz dodany przez <strong>{{komentarz.name}}</strong>
{{komentarz.created_date}}
<p>
{{ komentarz.content|linebreaks }}<br>
{% empty %}
<p>Nie dodano jeszcze żadnych komentarzy</p>
{% endfor %}
{% if nowy_komentarz %}
<h2>Twój komentarz został dodany</h2>
{% else %}
<h2>Dodaj nowy komentarz</h2>
<form action="." method="post">
{{formularz_komentarza.as_p}}
{% csrf_token %}
<p><input type="submit" value="Dodaj komentarz"></p>
</form>
{% endif %}
clas Wpisy in models.py
class Wpisy(models.Model):
title = models.CharField(max_length=400, verbose_name="Tytuł")
slug = models.SlugField(unique=True, max_length=400,verbose_name="Przyjazny adres url")
content = models.TextField()
status_audio = models.BooleanField(default=False, verbose_name="Czy dostępny będzie plik audio?")
audio_file = models.FileField(upload_to='uploads/',verbose_name="Plik audio")
created_date = models.DateTimeField(blank=True, null=True, verbose_name="Data utworzenia")
category = models.ForeignKey(Kategorie, verbose_name="Kategoria", on_delete=models.CASCADE)
class Meta:
verbose_name="Wpis"
verbose_name_plural="Wpisy"
def __str__(self):
return self.title
Your url pattern is
path('bajki/<slug>', views.detale_bajki, name='detale_bajki')
Note that it doesn't have a trailing slash. Your form's action is "."
<form action="." method="post">
That means you are submitting to /bajki/, which is the wrong URL.
You could fix this by adding a trailing slash to the url (which is common in Django URLs)
path('bajki/<slug>/', views.detale_bajki, name='detale_bajki')
Or you could change the form action to "" instead of ".". In the comments it looks like you fixed the issue by changing the form action to {{ detale_bajki.slug }}.
However these changes to the form action are fragile, and could break if you change your URL patterns again. The best approach is to use the {% url %} tag to reverse the correct URL.
<form action="{% url 'detale_bajki' detale_bajki.slug %}" method="post">
Try out:
nowy_komentarz.post = detale_bajki
...
return render(request, 'html page', {'key': 'what you want to return to your context'}) # don't fornget to add some return to your view.