Django redirecting after clicking Like button - django

I'm doing Like/Unlike system in my project. After clicking Like button should just redirect on the same page but updated with +1 like but it is not. Have looked on youtube videos with this system and they got it worked but I can't figure it out what is the problem with my code.
views.py
def like_view(request, pk):
cocktail = get_object_or_404(AddCocktails, id=request.POST.get('cocktail_id'))
liked = False
if cocktail.likes.filter(id=request.user.id).exists():
cocktail.likes.remove(request.user)
liked = False
else:
cocktail.likesadd(request.user)
liked = True
return HttpResponseRedirect(reverse('cocktails:cocktail-details', args=[str(pk)]))
class CocktailDetails(LoginRequiredMixin, DetailView):
model = AddCocktails
template_name = 'cocktails/cocktail-details.html'
def get_context_data(self, *args, **kwargs):
cocktail_data = AddCocktails.objects.filter(id=self.kwargs['pk'])
context = super().get_context_data(**kwargs)
stuff = get_object_or_404(AddCocktails, id=self.kwargs['pk'])
total_likes = stuff.total_likes
liked = False
if stuff.likes.filter(id=self.request.user.id).exists():
liked = True
context['cocktail_data'] = cocktail_data
context['total_likes'] = total_likes
context['liked'] = liked
return context
urls.py
path('cocktail-details/<int:pk>/', CocktailDetails.as_view(), name='cocktail-details'),
path('likes/<int:pk>/', like_view, name='likes'),
template
{% for cocktail in cocktail_data %}
<h4>Cocktail Name</h4>
{{ cocktail.cocktail_name }}
<h4>Cocktail Category</h4>
{{ cocktail.cocktails_category }}
<h4>Type of Glass</h4>
{{ cocktail.crockery_category }}
<h4>Method Category</h4>
{{ cocktail.method_category }}
<h4>Ingredients</h4>
{{ cocktail.ingredients }}
<h4>Execution</h4>
{{ cocktail.execution }}
<img src="{{ cocktail.image.url }}" width="350" height="350">
<form action="{% url 'cocktails:likes' cocktail.pk %}" method=POST>
{% csrf_token %}
{% if liked %}
<button type="submit" name="cocktail.id" value="{{ cocktail.id }}" class="btn unlike">Unlike
</button>
{% else %}
<button type="submit" name="cocktail.id" value="{{ cocktail.id }}" class="btn like">Like
</button>
{% endif %}
- {{ total_likes }} Likes
</form>
{% endfor %}
So after clicking the button the url shows "http://127.0.0.1:8000/likes/3" and page not found
Should I create template for like_view?
Is putting Like system good idea inside for loop? Because when I put it outside got error saying Reverse for 'likes' with arguments '('',)' not found. 1 pattern(s) tried: ['likes/(?P<pk>[0-9]+)$']

In your template in form you use name="cocktail.id"
Than in your view your do get_object_or_404(...id=request.POST.get('cocktail_id').
cocktail_id does not exist in your query, that's why you get HttpResponseNotFound.
You have to use your button name cocktail.id:
cocktail = get_object_or_404(AddCocktails, id=request.POST.get('cocktail.id'))
or maybe even simpler use pk parameter:
cocktail = get_object_or_404(AddCocktails, id=pk)

Related

Django display search results

I'm currently working on a blog app in Django. As all Blog apps I need a search form. Therefore I have write a small view and context processor (to make the search form available globally) that queries search results:
view.py:
class BlogSearchListView(ListView):
model = Post
paginate_by = 10
def get_queryset(self):
qs = Post.objects.published()
keywords = self.request.GET.get('q')
if keywords:
query = SearchQuery(keywords)
title_vector = SearchVector('title', weight='A')
content_vector = SearchVector('content', weight='B')
tag_vector = SearchVector('tag', weight='C')
vectors = title_vector + content_vector + tag_vector
qs = qs.annotate(search=vectors).filter(search=query)
qs = qs.annotate(rank=SearchRank(vectors, query)).order_by('-rank')
return qs
base.html:
<div class="globalsearch">
<form id="searchform" action="{% url 'search' %}" method="get" accept-charset="utf-8">
<label for="{{ categorysearch_form.category.id_for_label }}">In category: </label>
{{ categorysearch_form.category }}
<input class="searchfield" id="searchbox" name="q" type="text" placeholder="Search for ...">
<button class="searchbutton" type="submit">
<i class="fa fa-search"></i>
</button>
</form>
</div>
settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'quickblog.quickblog.context_processors.categorysearch_form',
)
context_processors.py
from .forms import PostForm
def categorysearch_form(request):
form = PostForm()
return {'categorysearch_form': form}
post_list.html:
{% extends 'quickblog/base.html' %}
{% block content %}
{% for post in posts %}
<div class="post">
<h1><u>{{ post.title }}</u></h1>
<p>{{ post.content|linebreaksbr }}</p>
<div class="date">
<a>Published by: {{ post.author }}</a><br>
<a>Published at: {{ post.published_date }}</a><br>
<a>Category: {{ post.category }}</a><br>
<a>Tag(s): {{ post.tag }}</a>
</div>
</div>
{% endfor %}
<div>
<span>
{% if posts.has_previous %}
« First <a> |</a>
Previous
{% endif %}
{% if posts.has_next %}
<span> Page {{ posts.number }} of {{ posts.paginator.num_pages }}.</span>
Next<a> |</a>
Last »
{% endif %}
</span>
</div>
{% endblock %}
The rest of the project can be checked here: https://github.com/rsmvdl/quickblog
I now want to render the results the same way as they get display in my post_list.html view with one detail more: I want that the word the user searched for gets highlighted in the search results, so that the user is able to get the context of the content ASAP ;) . I hope to get any creative ideas. Thanks.
You can create a custom template filter to add an HTML tag around the searched-for word in your post title or content. This will not be an exact solution but you should be able to adapt it:
#register.filter
#stringfilter
def highlight_search_term(text, search_term):
if search_term in text:
text.replace(search_term, '<span class="highlight">' + search_term + '</span>')
return mark_safe(text)
You can then apply this filter to your post title or content in your template with {{ post.title|highlight_search_term:search_term }}.
You will need to also pass search_term to your template context so that the filter can know what to highlight. Be careful with mark_safe() if you are applying this to user-submitted content!
You can create a context processor and pass request.GET.get('q') as context.
context_processors.py
def search(request):
search_keyword = request.GET.get('q')
context = {'search_keyword': search_keyword}
return context
And in your template access it as {{ search_keyword }}
search_results.html
<h3>Showing results for: {{ search_keyword }}</h3>

Unable to get data from django choice form

Hi, I'm trying to develop a simple django app, and I'm having trouble accessing a form's data. I've looked at django's documentation extensively and many questions on here on the same topic but nothing is working. Here's my code inside my view, that is otherwise working:
def post(self, request):
"""Return only the games from the upcoming gameweek"""
form = GWForm(request.POST)
if form.is_valid():
curr_gw = form.cleaned_data['gweek']
args = {'form': form, 'this_gw_fixtures': Game.objects.filter(gweek=curr_gw), 'curr_gw': curr_gw}
return render(request, self.template_name, args)
else:
curr_gw = 17
form = GWForm()
args = {'form': form, 'this_gw_fixtures': Game.objects.filter(gweek=curr_gw), 'curr_gw': curr_gw}
return render(request, self.template_name, args)
And here's the code of my template:
<form action="/predict/" method="post">{% csrf_token %}
<label for="Gameweek">Gameweek: </label>
<input id="gwparam" type="number" value="{{ curr_gw }}" min="17" max="40">
<input type="submit" value="Go">
</form>
{% if this_gw_fixtures %}
<ul>
{% for game in this_gw_fixtures %}
<li>{{ game }}</li>
{% endfor %}
</ul>
{% else %}
<p>No game predictions are available for this gameweek.</p>
{% endif %}
What I'm trying to do is get the input of a choice form and render a list of games that are in the gameweek selected in the form. Minumum 17, max 40. Here's my form code.
class GWForm(forms.Form):
gweek = forms.ChoiceField(required = False, choices=[(x, x) for x in range(17, 40)])
But when I try to grab the gweek from the form, is_valid() returns true, but form.cleaned_data['gweek'] doesn't return any value at all. Any help would be appreciated. Thanks in advance.
forms.py
class GWForm(forms.Form):
gweek = forms.IntegerField(required=False, min_value=17, max_value=40)
template
<form action="/predict/" method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="Go">
</form>

django form template does not update

I have created a form and I POST selection with an action to go to specific url. Although, once directed the template does not update.
I need to hit Enter again and then obviously my request is lost so I get exception value get_context_data() takes exactly 2 arguments (1 given)
any ideas why ?
Below is my code and print screen of the problem.
url
url(r'^all_rooms/$', views.AllRoomsView.as_view(), name='roomsdetails'),
template
<form action="/blocks/all_rooms/" method="post" >
{% csrf_token %}
<ul>
{% for choice in form.my_choice_field.field.choices %}
<li>
<input type="radio" name="my_choice_field" value="{{choice.0}}"
{% ifequal form.my_choice_field.data choice.0 %}
checked="checked"
{% endifequal %}/>
<label for="">{{choice.1}}</label>
</li>
{% endfor %}
</ul>
<input type="submit" value="Submit" />
</form>
EDIT:
Below is my AllRoomsView class. I suspect this is the class where the problem is.
class AllRoomsView(ListView):
template_name = 'prostats/roomsdetail.html'
queryset = Room.objects.all()
def get_context_data(self, request, **kwargs):
context = super(AllRoomsView, self).get_context_data(**kwargs)
context['rooms'] = Room.objects.all()
context['rlog'] = RoomLog.objects.all()
roomsdates = []
for r in context['rlog']:
if r not in roomsdates:
roomsdates.append(r.update_date)
roomextracted = []
for i in roomsdates:
if i not in roomextracted:
roomextracted.append(i)
context['roomextracted'] = roomextracted
choosend = '2016-02-16'
context['roomfiltersettime'] = RoomLog.objects.filter(update_date__lte = choosend)
return context

Django modelformset_factory saves nothing

(I'm quite new at django, i googled for this a lot but could not find an answer, so i hope you don't mind the low level question)
There are these Classes:
class Cl(models.Model):
user = models.ForeignKey(User,editable=False)
title = models.CharField(max_length=100)
class Member(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
cl = models.ForeignKey(Cl)
class ClForm(ModelForm):
class Meta:
model = Cl
I want to make a page where i can create an Object of Cl and some related Member Objects (I plan to use django-dynamic-formset but that is not the point here). My view looks like this:
class NewView(TemplateView):
def get(self, request):
cform = ClForm(prefix="cl", instance=Cl(user=request.user))
MemberFormSet = modelformset_factory(Member)
memberfs = MemberFormSet(queryset=Member.objects.none())
return render_to_response(self.template_name, {'cl_form': cform, 'memberformset': memberfs}, context_instance=RequestContext(request))
def post(self,request):
cform = ClForm(request.POST, prefix="cl", instance=Cl(user=request.user))
MemberFormSet = modelformset_factory(Member)
memberfs = MemberFormSet(request.POST)
if cform.is_valid() and memberfs.is_valid():
new_cl = cform.save()
new_members = memberfs.save(commit=False)
for mf in new_members:
mf.cl = new_cl
mf.save()
return HttpResponseRedirect("unimportant")
return render_to_response(self.template_name, {'cl_form': cform, 'memberformset': memberfs}, context_instance=RequestContext(request))
My template looks like this:
<form id="myForm" method="post" action="">
{% csrf_token %}
{{ memberformset.management_form }}
<table>
{{ cl_form }}
<tr><th colspan="2">Members</th></tr>
{% with memberformset.empty_form as form %}
<div id="id_empty_form" style="display:none;">
{{ form }}
</div>
{% endwith %}
</table>
<input type="submit" value="Save" />
</form>
My problem is now, that the member is not stored. Also, the memberfs.is_valid() doens't complain, if e.g. the Email field is not filled out correctly.
I also tried the inlineformset_factory, but that didn't worked either.
I think the problem is that you are using the "empty_form" in that template. The correct way of using the formset is described here. In your example, you should write:
<form id="myForm" method="post" action="">
{% csrf_token %}
{{ memberformset.management_form }}
<table>
{{ cl_form }}
<tr><th colspan="2">Members</th></tr>
<!-- THIS IS NOT NECESSARY UNLESS YOU WANT TO ADD FORMS WITH JAVASCRIPT-->
<div id="id_empty_form" style="display:none;">
{{ memberformset.empty_form }}
</div>
<!-- END NOT NECESSARY-->
{% for form in memberformset.forms %}
{{ form }}
{% endfor %}
{% endwith %}
</tbody>
</table>
<input type="submit" value="Save" />
</form>

problem handling upload file django

I'm trying to do a feature that would allow the user to upload a file. That file would have information to insert into the database, that's why in the function I'm saving data. Not sure if it's the best option.
What I've done so far:
forms.py:
class UploadFileForm(forms.Form):
file = forms.FileField()
views:
def last_step(request, word):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
msg = handle_uploaded_file(word, request.FILES['file'])
return render_to_response('final_insert.html', {'msg': msg})
else:
form = UploadFileForm()
return render_to_response('upload.html',
{
'word': word,
'form': form })
template:
<form enctype="multipart/form-data" action="{% url upload_done 'clinical' %}" method="post">
<div>
{% for field in form %}
{{ field }}
{% endfor %}
<input type="submit" value="Save" />
</div>
</form>
function:
def handle_uploaded_file(word, f):
msg = "first stop"
data = []
for chunk in f.chunks():
data.append(chunk)
msg = "after chunk"
if word == 'clinical':
pat = Patient.objects.values_list('patient', flat=True)
for i in data:
if i[0] not in pat:
b2 = Patient(patient=i[0])
b2.save()
msg = "number was inserted"
else:
msg = "something"
return msg
The problem is when I hit "save" in the template, it redirects well to another template, but I don't see any message, like I suppose to see (final_insert.html shows {{ msg }})
Can someone help me understand what I'm doing wrong?
Any help is welcome!
Thanks for your help!
I was able to understand my mistake.
sorry guys for my silly mistake
so this is the form:
<form enctype="multipart/form-data" action="{% url upload_done 'clinical' %}" method="post">
<div>
{% for field in form %}
{{ field }}
{% endfor %}
<input type="submit" value="Save" />
</div>
</form>
urls:
url(r'^insert/file/(?P<word>clinical)/upload/$', last_step, name="upload"),
url(r'^insert/file/(?P<word>clinical)/upload/result/$', final, name='upload_done'),
so the view last_step corresponds to the url "upload" and not "upload_done"
I wrote into the form action={% url upload_done 'clinical' %}, so when I hit save it will redirect me automatically to the other template. Without running the code!!
So I changed the form to:
<form enctype="multipart/form-data" action="{% url upload 'clinical' %}" method="post">
<div>
{% for field in form %}
{{ field.label_tag }}
{{ field }}
{% endfor %}
<input type="submit" value="Guardar" />
</div>
</form>
and now it works..
sorry guys, I thought I needed to redirect to the other page but when he redirects he doesn't run the code..