Django - Success Message Mixin Does not work on Login - html

I'm trying to display a success message on login using the SuccessMessageMixin but the message is not displayed. Is there any reason why this would happen?
settings.py
LOGIN_REDIRECT_URL = 'home'
LOGIN_URL = 'login'
LOGOUT_REDIRECT_URL = 'home'
LOGOUT_URL = 'logout'
urls.py
from .views import HomeView, LoginFormView
urlpatterns = [
path('admin/', admin.site.urls),
path('home/', HomeView.as_view(), name = 'home'),
path('login/', LoginFormView.as_view(), name = 'login'),
]
views.py
class HomeView(FormView):
template_name = 'home.html'
class LoginFormView(auth_views.LoginView, SuccessMessageMixin):
template_name = 'login.html'
success_url = 'home/'
success_message = "You were successfully logged in."
login.html
<h4>Login to your Account:</h4>
<div>
<form action "" method = "POST">
{% csrf_token %}
{{form}}
<button type = "submit">Login</button>
</form>
</div>
home.html
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}

The SuccessMessageMixin needs to be first (or atleast before the generic view) in the order of inheritance, i.e. it should be LoginFormView(SuccessMessageMixin, auth_views.LoginView) instead of LoginFormView(auth_views.LoginView, SuccessMessageMixin):
class LoginFormView(SuccessMessageMixin, auth_views.LoginView):
template_name = 'login.html'
success_url = 'home/'
success_message = "You were successfully logged in."

Related

Django HTML button on-click invoke backend function

im trying to add to my html a button that appears only on certain events, that works for me but i want to add a onclick script/function that will invoke a backend view.py function that deletes the specific room on click, the room model is : owner(fk), name, slug.
and the user model is : username password1 password2.
i just need to know how to invoke an onclick event that will call the backend function in my views.
rooms.html
{% extends 'core/base.html' %}
{% block title %} Rooms | {% endblock %}
{% block content %}
<div class="main">
<h1>Rooms</h1>
</div>
<div class="rooms-container">
{% for room in rooms %}
<div class="room">
<div class="room-info">
<h1 class="room-title">{{ room.name }}</h1>
Join Room
{% if request.user == room.owner %}
<button class="room-delete" id="roomDelete">Delete Room</button>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block scripts %}
<!-- todo: add delete room button functionality. -->
{% endblock %} ```
views.py
from django.contrib.auth.decorators import login_required
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
from django.contrib import messages
from .models import Room, Message
#login_required
def rooms(request):
if request.method == 'POST':
room_owner = request.user
room_name = request.POST['room-name']
if not Room.objects.filter(slug = room_name).exists():
if room_name == '' or room_name.isspace() or room_name.startswith(' '):
messages.info(request, 'Invalid room name, spaces-only or string that starts with spaces is invalid.')
else:
new_room = Room(owner = room_owner,name = room_name,slug = room_name)
new_room.save()
else:
messages.info(request, 'That room already exists!, try a different name.')
rooms = Room.objects.all()
return render(request, 'room/rooms.html', {'rooms': rooms})
#login_required
def room(request, slug):
room = Room.objects.get(slug=slug)
messages = Message.objects.filter(room=room)[0:25]
return render(request, 'room/room.html', {'room': room, 'messages': messages})
#csrf_exempt
def delete_room(request): ## <<------ invoke this from html call.
print("hey")
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.rooms, name='rooms'),
path('<slug:slug>/', views.room, name='room'),
path('', views.delete_room, name='delete_room'),
]
now i have more 2 urls.py, the project has 3 folders, 1 main (livechatapp) with settings and all, one for core htmls (core) and one for rooms html (room)
core/urls
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views
urlpatterns = [
path('', views.frontpage, name='frontpage'),
path('signup/', views.signup, name='signup'),
path('login/', auth_views.LoginView.as_view(template_name='core/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
and finally
livechatapp/urls
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('core.urls')),
path('rooms/', include('room.urls')),
path('admin/', admin.site.urls),
]
and this is the projects overview folders and files :
this is the project
IF you want do it in standard html:
% extends 'core/base.html' %}
{% block title %} Rooms | {% endblock %}
{% block content %}
<div class="main">
<h1>Rooms</h1>
</div>
<div class="rooms-container">
{% for room in rooms %}
<div class="room">
<div class="room-info">
<h1 class="room-title">{{ room.name }}</h1>
Join Room
{% if request.user == room.owner %}
<form method="POST" action="{% url 'delete_room' room.slug %}>
<button type="submit" class="room-delete">Delete Room</button></form>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
{% block scripts %}
<!-- todo: add delete room button functionality. -->
{% endblock %} ```
urls:
urlpatterns = [
path('', views.rooms, name='rooms'),
path('<slug:slug>/', views.room, name='room'),
path('delete/<slug:slug>/', views.delete_room, name='delete_room'),
]
views:
#csrf_exempt
def delete_room(request,slug):
if request.method == 'POST':
try:
room = Room.objects.get(slug=slug, owner=request.user)
room.delete()
except ObjectDoesNotExist:
print('there is no room with this slug or you are not owner')
return redirect('rooms')
i advice to use csrf. allways try to use POST when manipulatind data in db.
If you want to work it without redirect you need to think of ajax call or maby htmx

Django Reverse for ' ' with arguments '('',)' not found

I have a problem while using Django. I was trying to create a learning_log web application from my book and came across this error: NoReverseMatch at /edit_entry/8/
Reverse for 'topic' with arguments '('',)' not found. 1 pattern(s) tried: ['topics/(?P<topic_id>[0-9]+)/\Z']. It said it was because of this line in my edit_entry.html file: p>{{ topic }}</p> but I checked my entire project and couldn't find the reason,
Here is my urls.py:
from django.urls import path
from . import views
app_name = 'learning_logs'
urlpatterns = [
path('', views.index, name='index'),
path('topics/', views.topics, name='topics'),
path('topics/<int:topic_id>/', views.topic, name='topic'),
path('new_topic/', views.new_topic, name='new_topic'),
path('new_entry/<int:topic_id>/', views.new_entry, name='new_entry'),
path('edit_entry/<int:entry_id>/', views.edit_entry, name='edit_entry'),
]
views.py:
from django.shortcuts import render, redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
def index(request):
"""The home page for Learning Log."""
return render(request, 'learning_logs/index.html')
def topics(request):
"""Show all topics."""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
def topic(request, topic_id):
"""Show a single topic and all its entries."""
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries':entries}
return render(request, 'learning_logs/topic.html', context)
def new_topic(request):
"""Add a new topic."""
if request.method !='POST':
form = TopicForm()
else:
form = TopicForm(data=request.POST)
if form.is_valid():
form.save()
return redirect('learning_logs:topics')
context = {'topic': topic, 'form': form}
return render(request, 'learning_logs/new_entry.html', context)
def edit_entry(request, entry_id):
"""Edit and existing entry."""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic
if request.method !='POST':
form = EntryForm(instance=entry)
else:
form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return redirect('learning_logs:topic', topic_id=topic.id)
context = {'entry': entry, 'topic': topic, 'form': form}
return render(request, 'learning_logs/edit_entry.html')
models.py:
from django.db import models
class Topic(models.Model):
"""A topic the user is learning about."""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""Return a string representation of the model."""
return self.text
class Entry(models.Model):
"""Something specific about a learned topic."""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
"""Return a string representation of the model."""
return f"{self.text[:50]}..."
forms.py:
from django import forms
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
base.html:
<p>
Learning Log
Topics
</p>
{% block content %}{% endblock content %}
topics.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
{{ topic }}
</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
Add a new topic
{% endblock content %}
new_topic.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Add a new topic:</p>
<form action="{% url 'learning_logs:new_topic' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Add topic</button>
</form>
{% endblock content %}
new_entry.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>{{ topic }}</p>
<p>Add a new entry:</p>
<form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name='submit'>Add entry</button>
</form>
{% endblock content %}
topic.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<p>
Add new entry
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
<p>
Edit entry
</p>
</li>
{% empty %}
<li>There are no entries for this topic yet.</li>
{% endfor %}
</ul>
{% endblock content %}
edit_entry.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>{{ topic }}</p>
<p>Edit entry</p>
<form action="{% url 'learning_logs:edit_entry' entry.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save changes</button>
</form>
{% endblock content %}
index.html:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Learning Log helps you keep track of what you've learned.</p>
{% endblock content %}
and that is literally everything I checked and I can't seem to find the error, please help me find the error and fix it.
In views.py, on the edit_entry function, pass context to the render method.
On the very last line of the edit_entry function, in the views.py file, add the context to the arguments you are passing to the returned render method.
def edit_entry(request, entry_id):
"""Edit and existing entry."""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic
if request.method !='POST':
form = EntryForm(instance=entry)
else:
form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return redirect('learning_logs:topic', topic_id=topic.id)
context = {'entry': entry, 'topic': topic, 'form': form}
return render(request, 'learning_logs/edit_entry.html')
Correct the last line as follows, by adding context. This is so can you can use the entry, topic, and form that you defined in the context in the html template.
return render(request, 'learning_logs/edit_entry.html', context)

'Profile' object is not iterable

views.py.
#login_required
def friends_profile(request):
f_profiles = Profile.objects.get(user=request.user)
return render(request, 'mains/friends_profile.html', {'f_profiles':f_profiles} )
urls.py
path('friends_profile/', views.friends_profile, name='friends_profile'),
template = friends_profile.html
{% extends "mains/base.html" %}
{% block content %}
{% for friends in f_profiles %}
{{ friends.full_name }}
{% empty %}
<li>NO DATA</li>
{% endfor %}
{% endblock content %}
models.py
class Profile(models.Model):
user = models.OneToOneField(User,
on_delete=models.CASCADE,default='',unique=True)
full_name = models.CharField(max_length=100,default='')
friends = models.ManyToManyField(User, related_name='friends',blank=True)
email = models.EmailField(max_length=60,default='')
date_added = models.DateTimeField(auto_now_add=True)
def get_friends(self):
return self.friends.all()
def get_friends_no(self):
return self.friends.all().count()
def __str__(self):
return f'{self.user.username}'
STATUS_CHOICES = (
('send', 'send'),
('accepted','accepted'),
)
class Relationship(models.Model):
sender = models.ForeignKey(Profile, on_delete=models.CASCADE,
related_name='sender')
receiver = models.ForeignKey(Profile, on_delete=models.CASCADE,
related_name='receiver')
status = models.CharField(max_length=8, choices=STATUS_CHOICES)
def __str__(self):
return f"{self.sender}-{self.receiver}-{self.status}"
'Profile' object is not iterable. This is raising when i open this template( friends_profiles.html ). Please... Help me in this ERROR. What am i missing in this ?
I will really appreciate your HELP.
You are only passing a single object f_profiles in the context to the template, but are trying to iterate over an iterable by doing {% for friends in f_profiles %}.
f_profiles = Profile.objects.get(user=request.user) this will only give you one object which is the profile of the request.user. You are not getting friends of the user with this line of code.
Also, it maybe better to use
f_profiles = get_object_or_404(Profile, user=request.user)
Try to replace this code in the templates:
{% for friends in f_profiles %}
{{ friends.full_name }}
with
{% for friend in f_profiles.friends.all %}
{{ friend.full_name}}
or
{% for friend in f_profiles.get_friends %}
{{ friend.full_name }}

Exception Type: NoReverseMatch - Django

after researching for hours I cannot get rid of this error, I hope someone can help me.
Models:
class Puja(models.Model):
seller = models.OneToOneField(Seller, on_delete=models.CASCADE)
user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True,null=True)
title = models.CharField(max_length=100)
video = models.FileField(blank=True)
photo = models.ImageField(blank=True)
published_date = models.DateTimeField("Published: ",default=timezone.now())
bidding_end = models.DateTimeField()
starting_price = models.IntegerField(default=1)
#slug = models.SlugField(null=True)
def __str__(self):
return str(self.title)
#def get_absolute_url(self):
# return reverse('bidding_list_detail', args=[str(self.id)])
#slug time
def get_absolute_url(self):
return reverse('bidding_list_detail',args={'id': self.id})
Views:
class bidding_list(ListView):
model = Puja
template_name = 'bidding_templates/bidding_list.html'
"""return render(request= request,
template_name='bidding_templates/bidding_list.html',
context = {"Pujas": Puja.objects.all})"""
class bidding_list_detail(DetailView):
model = Puja
template_name = 'bidding_templates/bidding_list_detail.html'
urls:
path('admin/', admin.site.urls),
path("bidding_list/", bidding_list.as_view(), name="bidding_list"),
path('<int:pk>', bidding_list_detail.as_view(), name='bidding_list_detail'),
admin:
class PujaAdmin(admin.ModelAdmin):
list_display = ('seller','title','video','photo','published_date','bidding_end','starting_price')
admin.site.register(Puja,PujaAdmin)
template 1:
{% extends 'header.html' %}
{% block content %}
<h1>Pujas</h1>
{% for Puja in object_list %} <!--object_list-->
<ul>
<li> {{ Puja.title }} </li>
</ul>
{% endfor %}
{% endblock %}
template 2:
{% extends 'header.html' %}
{% block content %}
<div>
<h2>{{ object.title }}</h2>
<p>{{ object.seller }}</p>
</div>
{% endblock %}
Note that, whenever I remove <a href="{{ Puja.get_absolute_url }}"> from the first template, the objects "puja" in the model get properly displayed on the template, but I cannot access them. They normally exist on the admin panel, but not displayed on the website directly.
Thank you very much on advance and stay healthy.
edit 1: Here is the urls.py directly from the app created by django. To be more specific, I created after the project a new app called "main" in which I programmed all the project, including all the code on this question except the edit.
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
#from django.config import settings
#from django.config.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('main.urls')),
#path('', include('model.urls')),
#path('', include('blog.urls')),
#path('', include('photo.urls')),
#path('', include('video.urls')),
] # +static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I guess the problem is this line - return reverse('bidding_list_detail',args={'id': self.id}), you are passing id as a string but trying to match with int in url.Try following return reverse ('bidding_list_detail',args=[self.id])

Contact Form Django Not Working

I am trying to create a contact form for my Django site but it's not working properly. There are three steps to the contact form. Step 1 has a box where you input the subject of the email. Step 2 has a box where you input the sender's email address. At this point, there are three buttons- "first step", "prev step", and "submit". If I click "submit", the site doesn't take me to step 3, which is supposed to be where you input the body of the email. Instead, it reroutes me back to the Step 1 page.
I did my research and I can't find anything online related to this particular problem.
Here is my views.py file, which is located in the django_test/django_test directory:
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.context_processors import csrf
from forms import MyRegistrationForm
from django.contrib.formtools.wizard.views import SessionWizardView
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
#import logging
#logr = logging.getLogger(__name__)
def login(request):
c = {}
c.update(csrf(request))
return render_to_response('login.html', c)
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/accounts/loggedin')
else:
return HttpResponseRedirect('/accounts/invalid')
def loggedin(request):
return render_to_response('loggedin.html',
{'full_name': request.user.username})
def invalid_login(request):
return render_to_response('invalid_login.html')
def logout(request):
auth.logout(request)
return render_to_response('logout.html')
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
return render_to_response('register.html', args)
def register_success(request):
return render_to_response('register_success.html')
class ContactWizard(SessionWizardView):
template_name = "contact_form.html"
def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)
return render_to_response('done.html', {'form_data': form_data})
def process_form_data(form_list):
form_data = [form.cleaned_data for form in form_list]
logr.debug(form_data[0]['subject'])
logr.debug(form_data[1]['sender'])
logr.debug(form_data[2]['message'])
send_mail(form_data[0]['subject'],
form_data[2]['message'], form_data[1]['sender'],
[(my email address], fail_silently=False)
return form_data
This my forms.py file, also located in the django_test/django_test directory:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
class ContactForm1(forms.Form):
subject = forms.CharField(max_length=100)
class ContactForm2(forms.Form):
sender = forms.EmailField()
class ContactForm3(forms.Form):
message = forms.CharField(widget=forms.Textarea)
And my contact_form.html file, located in the django_test/templates directory:
{% extends "base.html" %}
{% block content %}
<h2>Contact Us</h2>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
{% for field in form %}
{{field.error}}
{% endfor %}
<form action="/contact/" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"first step"</button>
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"prev step"</buttom>
{% endif %}
<input type="submit" value="submit" />
</form>
{% endblock %}
And this is my urls.py file:
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
from django_test.api import ArticleResource
from django_test.forms import ContactForm1, ContactForm2, ContactForm3
from django_test.views import ContactWizard
article_resource = ArticleResource()
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^accounts/login/$', 'django_test.views.login'),
url(r'^accounts/auth/$', 'django_test.views.auth_view'),
url(r'^accounts/loggedin/$', 'django_test.views.loggedin'),
url(r'^accounts/invalid/$', 'django_test.views.invalid_login'),
url(r'^accounts/logout/$', 'django_test.views.logout'),
url(r'^accounts/register/$', 'django_test.views.register_user'),
url(r'^accounts/register_success/$', 'django_test.views.register_success'),
url(r'^articles/all/$', 'article.views.articles'),
url(r'^articles/create/$', 'article.views.create'),
url(r'^articles/get/(?P<article_id>\d+)/$', 'article.views.article'),
url(r'^articles/like/(?P<article_id>\d+)/$', 'article.views.like_article'),
url(r'^articles/add_comment/(?P<article_id>\d+)/$', 'article.views.add_comment'),
url(r'^articles/search/', 'article.views.search_titles'),
url(r'^articles/api/', include(article_resource.urls)),
url(r'^contact/', ContactWizard.as_view([ContactForm1, ContactForm2, ContactForm3])),
)
I'm not getting any error messages either, which is frustrating, so I don't know what I'm doing wrong. Thank you.
All I had to do was view the page source on the site. It turned out
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"prev step"</buttom>
in contact_form.html had a typo: </buttom>. I fixed the error and now I get the comment page.
The line should be:
<button name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"prev step"</button>