how to pass a primary key to a view in django? - django

I am trying to implement a class based view that should create a update form to update my model form but I don not know how to pass the pk from my base.html to my view:
viewvs.py:
from artdb.models import *
class UpdateForm(UpdateView):
print('updateform')
model=Date
fields=['activity']
template_name='updateForm.html'
updateForm.html:
{% extends "artdb/base.html" %}
{% block upd %}
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Update">
</form>
{% endblock upd %}
base.html:
<p><a class="btn btn-secondary" href="{% url 'artdb:updateform' %}" role="button">update form »</a></p
{% block upd %}
{% endblock upd %}
urls.py:
urlpatterns = [
path('<pk>/updateform/',views.UpdateForm.as_view(),name='updateform'),
]
I think that pk should be passed in the base.html but I am not shure how. Any suggestions?

I think you've probably got it by now, but if you didn't, try it like this in the app url.py file:
urlpatterns = [
path('updateform/<int:pk>',views.UpdateForm.as_view(),name='updateform'),
]

Related

PasswordChangeView not redirecting to PasswordChangeDoneView (or changing the password)

I am trying to use the Django authentication views. My login/logout views are working without a problem.
urls.py:
from django.urls import path
from django.contrib.auth import views as auth_views
from account import views
urlpatterns = [
path('', views.dashboard, name = 'dashboard'),
path('login/', auth_views.LoginView.as_view(), name = 'login'),
path('logout/', auth_views.LogoutView.as_view(), name = 'logout'),
path('password_change', auth_views.PasswordChangeView.as_view(), name = 'password_change'),
path('password_change/done', auth_views.PasswordChangeDoneView.as_view(), name = 'password_change_done'),
]
password_change_form.html:
{% block body %}
<h1>Change your password</h1>
<p>Please use the following form to change your password:</p>
<div class = 'password-change-form'>
<form class="" action="{% url 'login' %}" method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="submit" name="" value="Change">
</form>
</div>
{% endblock %}
password_change_done.html:
{% block body %}
<h1>Password Changed Successfully</h1>
{% endblock %}
I can navigate to /password_change and see the form, but when I fill it in and submit it in I am redirected to /login (I have made sure I was already logged in) and the password does not change. Does anyone know what the issue is?
This is because you specified {% url 'login' %} for the action="…" parameter, you need to change it with:
{% block body %}
<h1>Change your password</h1>
<p>Please use the following form to change your password:</p>
<div class = 'password-change-form'>
<form class="" action="{% url 'password_change' %}" method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="submit" name="" value="Change">
</form>
</div>
{% endblock %}

Why is my Update URL link kicking me to the CreateNew html view

so this is a tag on from my previous stackoverflow post:
Django updateView saving another instance instead of updating
and i think i've narrowed it down. Whats happening is that when i click on the link to update my view, it sends me to the "create new" page. my problem is that I cant figure out why its doing that.
Any and all help is appreciated.
here is the code:
question_form.html
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Create New Question</h4>
<form method="POST" action="{% url 'questions:create' %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Post" class="btn btn-primary btn-large">
</form>
{% endblock %}
question_update.html
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Update Question</h4>
<form method="POST" action="{% url 'questions:update' pk=question.pk %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Update" class="btn btn-primary btn-large">
</form>
{% endblock %}
question_detail.html
{% block content %}
this is the question detail view
<h3>{{ question.question_html|safe }}</h3>
<h3>{{ question.answer_html|safe }}</h3>
Update Question
{% endblock %}
urls.py
url(r'new/$', views.CreateQuestion.as_view(), name='create'),
url(r'questionupdate/(?P<pk>\d+)/$', views.QuestionUpdate.as_view(), name='update'),
url(r'questiondetail/(?P<pk>\d+)/$', views.QuestionDetail.as_view(), name='single'),
views.py
class CreateQuestion(generic.CreateView):
model = models.Question
form = QuestionForm
fields = ('question', 'answer')
success_url = reverse_lazy('questions:all')
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
class QuestionDetail(generic.DetailView):
model = models.Question
class QuestionUpdate(generic.UpdateView):
model = models.Question
form_class = QuestionForm
context_object_name = 'question'
From your urls.py the name of update view is only update. You can try only update tag in html file Like
{% extends "base.html" %}
{% load bootstrap3 %}
{% block content %}
<h4>Update Question</h4>
<form method="POST" action="{% url 'update' pk=question.pk %}" id="questionForm">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" value="Update" class="btn btn-primary btn-large">
</form>
{% endblock %}
I've figured it out. it turns out I was missing the template name part under my Create and update views which directs them to their own html templates:
class CreateQuestion(generic.CreateView):
model = models.Question
form_class = QuestionForm
fields = ('question', 'answer')
template_name = "questions/question_form_create.html"
success_url = reverse_lazy('questions:all')
class QuestionUpdate(generic.UpdateView):
model = models.Question
form_class = QuestionForm
template_name = "questions/question_form_update.html"

How to GET data by search word Django

I have problem getting the data to the home page.
I would like to filter out all the books based on Genre. I'm following the
MDN site for this.
index.html
{% extends "base_generic.html" %}
{% block content %}
<h1>Local Library Home</h1>
<p>Welcome to <em>Local Library</em>, a very basic Django website.</p>
<h2>Dynamic content</h2>
<form action="" method="get">
<input type="text" name="genre" placeholder="Search">
<input type="submit" value="Search">
</form>
{% endblock %}
urls.py
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^books/$', views.BookListView.as_view(), name='books'),
url(r'^(?P<string>[-\w]+)$', views.GenreListView.as_view(), name='index'),
]
GenreListView class
class GenreListView(generic.ListView):
model = Book
def get(request, string):
try:
book = Book.objects.all().filter(genre=string)
except Book.DoesNotExist:
raise Http404("Book does not exist")
return render(
request,
'index.html',
context={'book': book,}
)
I can't figure out what I'm missing or what else I have to do to get all the date based on genre?
EDIT:
whole index.html
{% extends "base_generic.html" %}
{% block content %}
<h1> Book List </h1>
<form action="" method="get">
<input type="text" name="genre" placeholder="Search">
<input type="submit" value="Search">
</form>
{% if book_list %}
<ul>
{% for book in book_list %}
<li>
{{ book.title }} ({{ book.author }})
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no books in the library</p>
{% endif %}
{% endblock %}
You should override get_queryset, No need to rewrite get
class GenreListView(generic.ListView):
model = Book
template_name = 'index.html'
def get_queryset(self):
books = Book.objects.all()
query = self.request.GET.get('genre', None)
if query:
return books.filter(genre=query)
return books
The exception Book.DoesNotExist will never
occur if you filter() queryset. it will always return a empty queryset in case of no object found

django-registration-redux and django-crispy-forms: submit button not responding

my registration_form.html is
{% extends '../base.html' %}
{% load crispy_forms_tags %}
{% block content %}
{% crispy form %}
<input type='submit' value="submit">
{% endblock %}
the view is in a module in an existing app. its below:
from registration.views import RegistrationView
from . import forms
class MyRegistrationView(RegistrationView):
def get_form_class(self):
return forms.LoginForm
the url in the urls.py file is
url(r'^accounts/register/$',MyRegistrationView.as_view()),
when the page load, on filling it, when i click submit, it does not submit.
pls what am i missing?
It looks as if your form is not enclosed in a <form> tag. You should have something like:
<form method="post" action="">
{% crispy form %}
<input type='submit' value="submit">
</form>

Resetting Password in Django

I have problem in resetting password in Django . After looking at this:Resetting Password, this error still exist....
My error is:
Reverse for 'django.contrib.auth.views.password_reset_confirm' with arguments '()' and keyword arguments '{'uidb36': '1', 'token': '392-804fab6dcec790f0ec6b'}' not found.
Here is my urls.py:
urlpatterns = patterns('lex.views',
url(r'^home/forgotpassword', 'lexrequestpassword', name='lexrequestpassword'),
url(r'^home/resetpassword', 'lexresetpassworddone', name='lexresetpassworddone'),
url(r'^home/reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$', 'lexresetpasswordconfirmed', name='lexresetpasswordconfirmed'),
url(r'^home/resetpasswordcompleted', 'lexresetpasswordcompleted', name='lexresetpasswordcompleted'),)
My views.py:
#login_required
def lexrequestpassword(request):
"""
Reset Password
"""
path = reverse('lexresetpassworddone')
return password_reset(request,post_reset_redirect=path)
#login_required
def lexresetpassworddone(request):
"""
Reset Password Done
"""
path = reverse('lexresetpasswordconfirmed')
return password_reset_done(request,template_name=path)
#login_required
def lexresetpasswordconfirmed(request):
"""
Reset Password Confirmed
"""
path = reverse('lexresetpasswordcompleted')
return password_reset_confirm(request,post_reset_redirect=path)
#login_required
def lexresetpasswordcompleted(request):
"""
Reset Password Completed
"""
path = reverse('lexmain')
return password_reset_complete(request,post_reset_redirect=path)
Not sure how to solve this. Need some guidance...
Password Reset
Django has a built-in password reset functions which we are going to use. In this tutorial we will name our app as accounts.
urls.py
from django.conf.urls import patterns, include, url
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
admin.autodiscover()
urlpatterns = patterns('',
url(
r'^admin/',
include(admin.site.urls)
),
#this is the url for password reset authentication
#Don't remove, this is important!
url(
r'^account/',
include('django.contrib.auth.urls')
),
#this is the accounts app main url
url(
r'^accounts/',
include('accounts.urls', namespace="accounts")
),
)+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += staticfiles_urlpatterns()
urls.py
from django.conf.urls import *
urlpatterns = patterns('accounts.views',
url(
r'^forgot-password/$',
'forgot_password',
name="forgot-password"
),
)
views.py
from django.contrib.auth.views import password_reset
from django.shortcuts import render
def forgot_password(request):
if request.method == 'POST':
return password_reset(request,
from_email=request.POST.get('email'))
else:
return render(request, 'forgot_password.html')
Put your base.html in your main templates folder
base.html
<html>
<head>
<title>{% block title %}{% endblock title %}</title>
</head>
<body>
{% block content %}{% endblock content %}
</body>
</html>
put this template in the app templates folder.
forgot_password.html
{% extends "base.html" %}
{% block title %}Forgot Password{% endblock title %}
{% block content %}
<form method="post" action="{% url django.contrib.auth.views.password_reset %}">
{% csrf_token %}
<p>Please enter your email address.
You will receive a link to create a new password via email.</p>
<input type="email" name="email"
placeholder="Your e-mail"><br/>
<button type="submit">Send new password</button>
</form>
{% endblock content %}
settings.py
#add email settings
EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'user'
EMAIL_HOST_PASSWORD = 'password'
DEFAULT_FROM_EMAIL = 'your email'
Now we will override the password reset templates of the admin. In your main templates folder create registration folder. Inside the registration folder, create these files:
If you want to change the contents of the files. Make sure it is correct or else you will got an errors.
password_reset_complete.html
{% extends "base.html" %}
{% block title %}Password reset complete{% endblock title %}
{% block content %}
<h4>Reset Complete</h4>
<p>Your password has been set.
You may go ahead and log in now.</p>
Log in
{% endblock content %}
password_reset_confirm.html
{% extends "base.html" %}
{% block title %}Setting New password{% endblock title %}
{% block content %}
<h4>Set New Password</h4>
<form action="" method="post">
{% csrf_token %}
{% if validlink %}
<p>Please enter your new password twice.
So we can verify you typed it in correctly.</p>
<p>
{{ form.new_password1.errors }}<br/>
{{ form.new_password1 }}
</p>
<p class="button-height">
{{ form.new_password2.errors }}<br/>
{{ form.new_password2 }}
</p>
{% else %}
<h4>Password reset unsuccessful</h4>
<p>The password reset link was invalid,
possibly because it has already been used.
Please request a new password reset.</p><br/>
{% endif %}
<button type="submit">Change my password</button>
</form>
{% endblock content %}
password_reset_done.html
{% extends "base.html" %}
{% block title %}Password reset successful{% endblock title %}
{% block content %}
<h4>Reset Password</h4>
<p>We've e-mailed you instructions for setting
your password to the e-mail address you submitted.</p>
<p>You should be receiving it shortly.</p>
<p>Login</p>
{% endblock content %}
#password_reset_ email.html
{% load i18n %}
{% load url from future %}
{% autoescape off %}
{% blocktrans %}
You're receiving this e-mail because you requested
a password reset for your user account at {{ site_name }}.
{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.username }}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}
password_reset_form.html
{% extends "base.html" %}
{% block title %}Password reset form{% endblock title %}
{% block content %}
<h4>Reset Password</h4>
<p>Forgotten your password?
Enter your e-mail address below,
and we'll e-mail instructions for setting a new one.</p>
<form action="" method="post">
{% csrf_token %}
{% if form.email.errors %}`enter code here`
<div class="message red-gradient">{{ form.email.errors }}</div><br/>
{% endif %}
<p>E-mail address: {{ form.email }} <br/><br/>
<input type="submit" value="Reset my password"></p>
</form>
{% endblock content %}
Than your def lexresetpasswordconfirmed(request): should accept also uidb36 and token args.
Reverse for 'django.contrib.auth.views.password_reset_confirm' with arguments '()' and keyword arguments '{'uidb36': '1', 'token': '392-804fab6dcec790f0ec6b'}' not found.
This means that at some point in the execution, you are not calling reverse on lexresetpasswordconfirmed, you are calling it on django.contrib.auth.views.password_reset_confirm.
Where is this error occurring? In the template? If so, make sure that the template you are using has
{% url lexresetpasswordconfirmed uid token %}
and not
{% url django.contrib.auth.views.password_reset_confirm uid token %}
Is the error occurring in a view? If so, somewhere you are calling reverse on django.contrib.auth.views.password_reset_confirm.
Once that error is resolved, then yes you will have to resolve the other error that Alexander pointed out, namely including the uuid and token in the view function:
#login_required
def lexresetpasswordconfirmed(request, uuid36, token):
"""
Reset Password Confirmed
"""
# you need to do SOMETHING with the uuid and token here, RIGHT?!?!
path = reverse('lexresetpasswordcompleted')
return password_reset_confirm(request,post_reset_redirect=path)
So I'm guessing on each of these returns you're using the views from django.contrib.auth, correct? Problem is that one of these views -- probably password_reset_done -- doesn't care that you've provided it with a redirect, it's using its own.
My settings.py:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ.get('EMAIL_USER')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_PASS')
My urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('register/', user_views.register,name='register'),
path('profile/', user_views.profile,name='profile'),
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'),name='login'),
path('logout/',auth_views.LogoutView.as_view(template_name='users/logout.html'),name='logout'),
path('password-reset/',auth_views.PasswordResetView.as_view(template_name='users/password_reset.html'),name='password_reset'),
path('password-reset/done/',auth_views.PasswordResetDoneView.as_view(template_name='users/password_reset_done.html'),name='password_reset_done'),
path('password-reset-confirm/<uidb64>/<token>/',auth_views.PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html'),name='password_reset_confirm'),
path('password-reset-complete/',
auth_views.PasswordResetCompleteView.as_view(
template_name='users/password_reset_complete.html'
),
name='password_reset_complete'),
path('', include('blog.urls')),
]
password_reset.html:
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Reset Password</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Request Password Reset</button>
</div>
</form>
</div>
{% endblock content %}
password_reset_done:
{% extends "blog/base.html" %}
{% block content %}
<div class="alert alert-info">
An email has been sent with instructions to reset your password
</div>
{% endblock content %}
password_reset_confirm.html:
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Reset Password</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Reset Password</button>
</div>
</form>
</div>
{% endblock content %}
password_reset_complete.html:
{% extends "blog/base.html" %}
{% block content %}
<div class="alert alert-info">
Your password has been set.
</div>
Sign In Here
{% endblock content %}