Password Reset functionality inheriting from Django clases - reverse url issues ('uidb64') - django

I want to create a Password Reset functionality but changing the templates.
So I'm inheriting from Django classes.
After I insert the email to reset password, I ge the following error:
NoReverseMatch at /accounts/password-reset/
Reverse for 'confirm_reset_password' with keyword arguments
'{'uidb64': '', 'token': '4y5-9ae986836e35f95b842c'}' not found. 1
pattern(s) tried:
['accounts\/password-reset-confirm/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$']
I think the issue is that 'uidb64', but I don't know why is empty.
Views:
class CustomPasswordResetView(PasswordResetView):
form_class = CustomPasswordResetForm
email_template_name = 'account/password_reset_email.html'
template_name = 'account/password_reset.html'
class UserPasswordResetConfirmView(PasswordResetConfirmView):
pass
Form:
class CustomPasswordResetForm(PasswordResetForm):
email = forms.EmailField(widget=TextInputWidget)
Urls:
path('password-reset/', UserPasswordResetView.as_view(), name='reset_password'),
re_path(r'^password-reset-confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
UserPasswordResetConfirmView.as_view(), name='confirm_reset_password')
in reset template:
<form action="" method="post">
{% csrf_token %}
<div class="row ">
{{ form.email }}
</div>
<div class="l-action">
<input type="submit" class="button" value="Reset my password">
</div>
</form>
In email template:
a href="http://{{ domain }}{% url 'users:confirm_reset_password' uidb64=uidb token=token %}"

I think your email template contains an error. You write:
a href="http://{{ domain }}{% url 'users:confirm_reset_password' uidb64=uidb token=token %}"
But the uidb64 parameter should, according to the documentation [Django-doc] have as parameter the uid variable, so:
a href="http://{{ domain }}{% url 'users:confirm_reset_password' uidb64=uid token=token %}"

Related

Why is Django product editing not working. Reverse for 'edit' not found?

I'm trying to edit a product (without using forms.py) but I get an error Reverse for 'edit' not found. 'edit' is not a valid view function or pattern name.
vievs.py
def edit(request, id):
if (request.method == 'POST'):
obj, update = Posts.objects.update_or_create(title=request.POST.get("title"))
obj.text=request.POST.get("text")
obj.date=request.POST.get("date")
obj.image=request.POST.get("image")
obj.save()
return render(request, 'edit.html')
html
<form action="{% url "blog:edit" %}" method="post">
{% for el in posts %}
{% csrf_token %}
<input type="text" placeholder="Название" name="title" value="{{ el.title }}"><br>
<textarea placeholder="Текст статьи" rows="8" cols="80" name="text"></textarea><br>
<input type="file" name="image"><br>
<button type="submit">Добавить статью</button>
{% endfor %}
</form>
You need to define the view in your blog app's urls.py file. Something like this:
urlpatterns = [
# ... other patterns
path('<int:id>/edit/',views.edit,name='edit'),
]

Can't get the DeleteView of a post in a social network project

I am building a simple social network in django.
In the "home" of my social, I have the list of all posts published by all users, with author and publishing date. Under each post of the logged user, a "delete" button appears. If the user clicks on it, it should return a specific view of that post, with a message like "do you really wish to delete this post?"
However, as I click on it, the code returns this error:
NoReverseMatch at /posts/delete/7/
Reverse for 'single' with no arguments not found. 1 pattern(s) tried: ['posts/by/(?P[-\w]+)/(?P\d+)/$']
Why does it says that it cannot get the reverse for 'single' with no arguments, while in the template the delete button has a link to 'delete' view function?
Here is my urls.py, inside urlpatterns:
url(r'^$',
views.PostList.as_view(),
name='all'),
url(r'new/$',
views.CreatePost.as_view(),
name='create'),
url(r'by/(?P<username>[-\w]+)/$',
views.UserPosts.as_view(),
name='for_user'),
url(r'by/(?P<username>[-\w]+)/(?P<pk>\d+)/$',
views.PostDetail.as_view(),
name='single'),
url(r'delete/(?P<pk>\d+)/$',
views.DeletePost.as_view(),
name='delete'),
Here is my views.py:
class DeletePost(LoginRequiredMixin, SelectRelatedMixin, generic.DeleteView):
model = models.Post
select_related = ('user', 'group')
success_url = reverse_lazy('posts:all')
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user_id = self.request.user.id)
def delete(self,*args,**kwargs):
messages.success(self.request,'Post Deleted')
return super().delete(*args,**kwargs)
Here is my piece of template making the delee button appear:
{% if user.is_authenticated and post.user.username == user.username %}
<a href="{% url 'posts:delete' pk=post.pk %}" title="delete" class="btn btn-simple">
<span class="glyphicon glyphicon-remove text-danger" aria-hidden="true"></span>
<span class="text-danger icon-label">Delete</span>
</a>
{% endif %}
EDIT:
Here is my piece of template showing the post and asking the user if he/she really wants to delete it:
<h3>Do you want to delete this post?</h3>
<div class="posts">
{% include "posts/_post.html" with post=object hide_delete=True %}
</div>
<form class="POST">
{% csrf_token %}
<input type="submit" value="Confirm Delete" class="btn btn-danger btn-large">
<a href="{% url 'posts:single' username=user.username pk=object.pk %}"
class="btn btn-simple btn-large btn-default">Cancel</a>
</form>
The model User is django's default models.User
Note: I previously encountered a similar error related to the use of regex expressions. More details can be found in this other question.
I was looking for the error in the part of template showing the delete button, while it lied in the template asking the user if he/she wants the post to be deleted.
In code piece:
<h3>Do you want to delete this post?</h3>
<div class="posts">
{% include "posts/_post.html" with post=object hide_delete=True %}
</div>
<form class="POST">
{% csrf_token %}
<input type="submit" value="Confirm Delete" class="btn btn-danger btn-large">
<a href="{% url 'posts:single' %} username=user.username pk=object.pk %}"
class="btn btn-simple btn-large btn-default">Cancel</a>
</form>
I replaced
<a href="{% url 'posts:single' %} username=user.username pk=object.pk %}"
with:
<a href="{% url 'posts:delete' pk=post.pk %}"
and now it finally takes me to the post deletion confirm view

How to render template after failed form validation?

urls.py:
urlpatterns = [
path('employee/add_employee/', views.add_employee, name='add-employee'),
path('employee/add_employee/add/', views.add_employee_action, name='add-employee-action'),
]
I have add-employee page and some forms to fill there.
views.py:
def add_employee(request):
personal_form = PersonalEmployeeForm()
history_form = EmployeeHistoryForm()
return render(
request,
'sections/add_employee.html',
context={
'personal_form': personal_form,
'history_form': history_form,
}
)
def add_employee_action(request):
if request.method == "POST":
personal_form = PersonalEmployeeForm(request.POST)
history_form = EmployeeHistoryForm(request.POST)
if personal_form.is_valid() and history_form.is_valid():
# here is some logic with models
return redirect('add-employee')
else:
personal_form = PersonalEmployeeForm()
history_form = EmployeeHistoryForm()
return render(
request,
'sections/add_employee.html',
context={
'personal_form': personal_form,
'history_form': history_form,
}
)
template:
<form id="a-submit-form" action="add/" method="POST">
{% csrf_token %}
<div class="column-wrapper">
<div class="column">
<div class="form-wrapper">
{% for field in personal_form.visible_fields %}
{% include "elements/forms/form_line.html" %}
<br>
{% endfor %}
</div>
</div>
<div class="column">
<div class="form-wrapper">
{% for field in history_form.visible_fields %}
{% include "elements/forms/form_line.html" %}
<br>
{% endfor %}
</div>
</div>
</div>
<div class="button-bar-wrapper">
<div class="button_bar">
<a class="a-button positive" id="submit">Добавить</a>
<a class="a-button" href="{% url 'employee' %}">Сотрудники</a>
<a class="a-button" href="{% url 'index' %}">На главуную</a>
</div>
</div>
</form>
Submitting by <a> element is tested and worked well with jQuery script.
The problem is after submitting invalid forms I have a page with blah-blah/employee/add_employee/add/ URL. And if I try to submit forms again I have a page with blah-blah/employee/add_employee/add/add/ URL, which is incorrect. How can I render the page with blah-blah/employee/add_employee/ URL and show all error messages?
This is likely because you have written a relative URL in the <form> tag of the sections/add_employee.html template. The template thus contains something like:
<form method="post" action="add/">
...
</form>
You can use a URL with the {% url … %} template tag [Django-doc]:
<form method="post" action="{% url 'add-employee-action' %}">
...
</form>
Furthermore one usually uses the same path to handle both the GET and the POST request. So in fact you might simply remove the 'add-employee' path.

django 2.0 work with forms without jquery

from django import forms
class Find(forms.Form):
object_name = forms.CharField()
views.py
def get_obj(request, object_name='000'):
print(object_name)
form = FindSSK()
print(request.GET)
urlpatterns = [
# path(r'ssk/<str:object_name>/', get_obj),
re_path(r'^(?P<object_name>)#$', get_obj),
path(r'', get_obj),
]
{% block find %}
<form class="form-inline ml-5" action="#" method="GET">
{% comment %} {{form}} {% endcomment %}
{% comment %} <input type="number" class="form-control" placeholder="Enter obj" aria-label="Search"> {% endcomment %}
{% comment %} <input type="text" > {% endcomment %}
<input type="text" name="object_name" />
<input class="btn btn-outline-success ml-1 fas fa-search" type="submit" >
</input>
</form>
{% endblock %}
When i push to submit on forms, he will redirect http://127.0.0.1:8000/?object_name=001
But var object_name steal 000
result print in get_obj()
000
<QueryDict: {'object_name': ['001']}>
Sorry for bad English.
You're not able to get the argument needed because you're actually sending the value as a GET argument. However object_name is passed in your view as an argument and as URL parameter for your URL pattern, means that this should be included in the URL like url/object_name/ == http://127.0.0.1:8000/001/. Not sure this is what fits better your need.
To send data to the view, you could use a POST request or a GET request as you did with http://127.0.0.1:8000/?object_name=001.
For both options above, you don't need to have object_name as a parameter neither this ^(?P<object_name>) in url pattern.
VIEW: def get_obj(request object_name='000'):
______________________
URL: re_path(r'^$', get_obj),
method="GET": If you use GET request in form <form class="form-inline ml-5" action="#" method="GET"> you could retrieve the value like the following
def get_obj(request):
object_name = request.GET.get('object_name') # object_name is the field name in form
print(object_name)
method="POST": If you use POST request in form <form class="form-inline ml-5" action="#" method="POST"> you could retrieve the value like the following
def get_obj(request):
object_name = None
if request.method == 'POST':
object_name = request.POST.get('object_name')
print(object_name)
If you use POST request, don't forget to add {% csrf_token %} in your form

Django NoReverseMatch url issue

I'm getting the error
"Reverse for 'recall' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'associate/recall/']"
When I try to submit a form. Here is my html:
<form action="{% url 'associate:recall' ordered_group %}" method="post">
{% csrf_token %}
<div>
<label for="recall">enter as many members of {{ ordered_group }} as you can recall </label>
<input type="text" id="recall" name="recall">
</div>
<div id="enter_button">
<input type="submit" value="enter" name="enter" />
</div>
<div id="done_button">
<input type="submit" value="done" name="done" />
</div>
</form>
"ordered_group" is a model object that is carried over from the 'learn' view:
urls.py:
urlpatterns = patterns('',
url(r'^learn/', "associate.views.learn", name='learn'),
url(r'^recall/', 'associate.views.recall', name='recall'),
url(r'^$', "associate.views.index", name='index'),
)
I am trying to use the ordered_group model object that is submitted in the learn view context to the html, back to the recall view as an argument. Can one do this? It makes sense to me, but what is the correct way of doing this?
views.py
def recall(request, ordered_group):
...
def learn(request):
...
ordered_group = ordered_groups[index]
return render(request, 'associate/learn.html', {'dataset':model, 'ordered_group':ordered_group})
I want to submit the form with
In you HTML, you are doing:
{% url 'associate:recall' ordered_group %}
Django expects that "recall" url is in "associate" namespace, because of the ":". But, you need to declare the namespace in urls.py, like:
url(r'^recall/', 'associate.views.recall', namespace='associate', name='recall')
If you don't want the namespace, just do:
{% url 'recall' ordered_group %}
And, about "ordered_group", you need to declare it in your url, like:
url(r'^recall/(?P<ordered_group>\w+)', 'associate.views.recall', namespace='associate', name='recall')
You are passing ordered_group in HTML, youare expecting this in views.py, but you are not expecting this on you URL.