There is a view in the Django project (a paginated blog) that is responsible for how likes work. It has one drawback: when a user likes a post, it is redirected to the main page of the site. How can I fix this so that the user would remain on the page where they liked.
views.py
class AddLikeView(View):
def post(self, request, *args, **kwargs):
blog_post_id = int(request.POST.get('blog_post_id'))
user_id = int(request.POST.get('user_id'))
url_from = request.POST.get('url_from')
user_inst = User.objects.get(id=user_id)
blog_post_inst = News.objects.get(id=blog_post_id)
try:
blog_like_inst = BlogLikes.objects.get(blog_post=blog_post_inst, liked_by=user_inst)
except Exception as e:
blog_like = BlogLikes(blog_post=blog_post_inst,
liked_by=user_inst,
like=True)
blog_like.save()
return redirect(url_from)
template.py
<form action="{% if not is_liked_bool %}{% url 'add' %}{% else %}{% url 'remove' %}{% endif %}" method="post">
{% csrf_token %}
<input type="hidden" name="blog_post_id" value="{{ blog_post_id }}">
<input type="hidden" name="user_id" value="{% if user.is_authenticated %}{{ request.user.id }}{% else %}None{% endif %}">
<input type="hidden" name="url_from" value="{{ request.path }}">
{% if is_liked_bool %}
<input type="hidden" name="blog_likes_id" value="{{ blog_likes_id }}">
{% endif %}
<button type="submit" class="btn btn-success">
{% if not is_liked_bool %}
<i class="fi-xnluxl-heart">♥</i>
{% else %}
<i class="fi-xnluxl-heart-solid">♥</i>
{% endif %}
<span class="likes-qty">{{ likes_counter }}</span>
</button>
I think you should check the url_from field first. Just print it and if it's wrong, you should change the {{request.path}} field in your template.
You can try this:
{{ request.get_full_path }}
And also if I remember correctly, you can access the path with request.path in your view and no need to send path via template.
Related
Sorry for my bad english
I've got "topics.html" file, that extends "base.html".
In "base" I've got search form. In "topics" I've got any checkboxes. How can I connect 2 forms in 1 request?
Base:
<form id="form_1" action="{% url 'topics' %}"><input type="search" id="search" name="search" placeholder="Search"></form>
Topics:
<form id="form_1" action="{% url 'topics' %}">
<div class="typess">
<h1 class="vk">Categories:</h1>
{% for typee, name in types.items %}
<label>
<input type="checkbox" style="display:none" value="{{ typee }}" name="category" {% if typee in categories %} checked {% endif %}>
<span class="typee" title="{{ name }}"><i class="{{ typee }}"></i>{{ name }}</span>
</label>
{% endfor %}
</div>
</form>
It should connect in "topics" function:
def topics(request):
info = []
categoriess = request.GET.getlist('category')
typess = request.GET.getlist('type')
search = request.GET.get('search')
if categoriess:
...
But when I run code, it's not see the checkboxes
So, i want to get the checked checkboxes items ids as a list and show them on another page. But when i get to that specific page i get the value 'None' instead of the list of ids. What could go wrong? I tried some different versions from another questions already posted on the site, but the result was the same.
Here is the code:
models.py:
from django.db import models
class afirmatii(models.Model):
text = models.CharField(max_length = 250)
def __str__(self):
return self.text
views.py:
def exam(request):
if request.method == 'POST':
checks = request.POST.get('selected[]')
request.session['checks2'] = checks
context = {
'title' : 'Title1',
'aff': afirmatii.objects.order_by('id')
}
return render(request, 'pages/exam.html', context)
def result(request):
checks = request.session.get('checks2')
context = {
'title' : 'Title2',
'checks': checks
}
return render(request, 'pages/result.html', context)
exam.html:
{% extends "./base.html" %}
{% block content %}
<div class="text-break">
<form action="{% url 'result' %}" method="POST">
{% csrf_token %}
{% for q in aff %}
<div class="border mb-3 rounded-sm bg-light p-2">
<div class="custom-control custom-checkbox checkbox-info">
<input type="checkbox" class="custom-control-input" id="{{ q.id }}" name = "selected[]">
<label class="custom-control-label" for="{{ q.id }}" name = 'selected[]'> {{ q.text }} </label>
</div>
</div>
{% endfor %}
<button type="submit" class="btn btn-md btn-outline-info">Next</button>
</form>
</div>
{% endblock content %}
result.html:
{% extends "./base.html" %}
{% block content %}
<body>
<div class="text-center">
<p class="pb-5"> {{ checks }} </p><br>
<div class="row">
<div class="col">
Home
</div>
<div class="col">
Learn more
</div>
</div>
</div>
</body>
{% endblock content %}
You can try use FORMSETS A formsets is a layer of abstraction to work with multiple forms on the same page.
You can paint the list of questions according to records in the table and get ids (or other fields) of the marked answers
forms.py
class ExamForm(forms.Form):
checkbox = forms.BooleanField(required=False)
id = forms.CharField(widget=forms.HiddenInput)
text = forms.CharField(widget=forms.HiddenInput)
views.py
from django.shortcuts import render
from django.forms import formset_factory
from .forms import *
def exam(request):
aff = afirmatii.objects.order_by('id')
exam_formset = formset_factory(ExamForm, extra=0)
formset = exam_formset(initial=[{'id': x.id, 'text': x.text} for x in aff])
checks = []
if request.method == 'POST':
formset = exam_formset(request.POST)
if formset.is_valid():
for form in formset.forms:
if form.cleaned_data.get('checkbox', None):
checks.append(form.cleaned_data)
context = {
'formset': formset,
'checks': checks,
}
return render(request, 'pages/exam.html', context)
exam.html
{% if not checks %}
<h1>Exam:</h1>
<form action="{% url 'exam' %}" method="POST">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset.forms %}
<div class="form-group">
{{ form.checkbox }}
{{ form.text.value }}
{{ form.id }}
{{ form.text }}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% else %}
<h1>Results:</h1>
{% for check in checks %}
<p>{{ check.id }} {{ check.text }}</p>
{% endfor %}
{% endif %}
I'm trying allauth for the first time and having difficulty signing up for the first time. I am using the Facebook support and I connect to Facebook successfully, logging in and get to /accounts/social/signup:
where my Facebook name and email address are pre-filled, but the button doesn't work, quite possibly because the form action is empty. I checked the allauth package template, and it seems designed this way. I'm not sure what's going on, but it's not working for me. Please help!
Excerpt from rendered page http://localhost:8000/accounts/social/signup/
<p>{% blocktrans with provider_name=account.get_provider.name site_name=site.name %}You are
about to use your {{provider_name}} account to login to
{{site_name}}. As a final step, please complete the following form:{% endblocktrans %}</p>
<form class="signup" id="signup_form" method="post" action="">
{% csrf_token %}
{{ form.as_p }}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button type="submit">{% trans "Sign Up" %} »</button>
</form>
excerpt from /virtualenvs/myproject/lib/python2.7/site-packages/allauth/templates/socialaccount/signup.html
<form class="signup" id="signup_form" method="post" action="">
{% csrf_token %}
{{ form.as_p }}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button type="submit">{% trans "Sign Up" %} »</button>
</form>
Action was left out in code and has now been changed on github, although apparently not in the pip package directory, thus I installed the error.
I have a database with users information and IP's. What I would like to do is to dynamically create, and then open, a *.vnc file with their IP.
In my views.py file I have this:
def view_list(request):
template_name = 'reader/list.html'
cust_list = xport.objects.all()
#if request.method == 'POST':
#<a href=link to created *.vnc file>Connect to client</a>
return render(request, template_name, {'xport': cust_list})
The commented out portion is just what I've been playing with and what I currently think I need to do.
My template file is list.html and looks like this:
{% extends "base.html" %}
{% load url from future %}
{% block content %}
<h1> Customer List </h1>
<ul>
{% for c in xport %}
{% if c.ip %}
<li>{{ c.firstName }} {{ c.lastName }}</li>
<form method="POST" action=".">{% csrf_token %}
<input type="submit" name="submit" value="Create VNC to {{ c.ip }}" />
</form>
{% endif %}
{% endfor %}
</ul>
{% endblock %}
What I would like to do is to click on the "Create VNC" button and then that create and open the *.vnc file.
This should give you an idea:
url(r'^file/vnc/$', 'myapp.views.vnc', name='vnc-view'),
views.py
from django.views.decorators.http import require_POST
#require_POST
def vnc(request):
ip = request.POST.get('ip', None)
response = HttpResponse(ip, content_type='application/octet-stream')
# If you don't want the file to be downloaded immediately, then remove next line
response['Content-Disposition'] = 'attachment; filename="ip.vnc"'
return response
template
<form method="POST" action="{% url 'vnc-view' %}">{% csrf_token %}
<input type="hidden" name="ip" value="127.0.0.1" />
<input type="submit" name="submit" value="Create VNC to 127.0.0.1" />
</form>
how can I get rid of users being directed to the “Thanks you
for your comment” page after commenting in Django site? I want users to be
redirected to the same page they commented. I’m using Django
comments.
I’ve tried adding:
<input type=”hidden” name=”next” value=”"{% url
django.contrib.comments.views.comments.comment_done %}" />
But it’s not working. Below is codes in my comment/form.html
{% load comments %}
{% get_comment_count for sol as comment_count %}
{% get_comment_list for sol as comment_list %}
{% get_comment_form for sol as form %}
{% if user.is_authenticated %}
<form action="{% comment_form_target %}" method="post">
{% csrf_token %}
{% if next %}<input type="hidden" name="next" value="{% url
django.contrib.comments.views.comments.comment_done %}" />{% endif %}
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
{% if field.name != "name" and field.name != "email"
and field.name != "url" %}
{% if field.errors %}{{ field.errors }}{% endif %}
{{ field }}
{% endif %}
{% endif %}
{% endfor %}
<input class="submit-post" name="post" type="submit" value="Comment" />
</form>
{% else %}
I'm sorry, but you must be <a href="javascript:alert('send to
login page')">logged in</a> to submit comments.
{% endif %}
First let's review your code:
<input type=”hidden” name=”next” value=”"{% url
django.contrib.comments.views.comments.comment_done %}" />
Two double quotes: value=”"{% url
The url is comment_done: so this will redirect to the "Thank you for your comment page", which you want to avoid
Use url names instead of module name: {% url comments-comment-done %} rather than {% url django.contrib.comments.views.comments.comment_done %}
Instead, you can redirect the comment poster to the absolute url of the object he commented:
<input type="hidden" name="next" value="{{ form.instance.content_object.get_absolute_url }}" />
This assume that your model has the standard get_absolute_url() method defined.
Or even, you can redirect the user to the very same page he's on:
<input type="hidden" name="next" value="{{ request.path }}" />
Or the previous page he visited:
<input type="hidden" name="next" value="{{ request.META.HTTP_REFERER }}" />