Django Prevent page from refreshing - python

So guys I have 2 problems.
I am pretty new in Django and Python. I build a page with a form and I can input data in those fields, I receive the data do some operation with it and pass back other variables which are shown in a div under the form field after a button was clicked. It is actually working but the page refreshes so I can see the result for only one second. Second Problem is that I have to click twice on the button so it shows me the right result. Example: First button click Result shows x, then I use other input and click button, result shows x again. After I click the button again it shows the right result, how do I fix this problem aswell.
And do you have suggestions how to make this system better?
I am already really thankful for your help.
My view file:
from django.shortcuts import render,redirect
from django.http import HttpResponse
from pages.forms import NameForm
import requests
# Create your views here.
def home_view(request,*args,**kwargs):
api_key = "RGAPI-9b573263-7b5a-433e-9e82-a973f5db4749"
name = ""
tier = ""
rank = ""
lp = 0
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
summoner = form.cleaned_data["summoner"]
region = form.cleaned_data["region"]
url = "https://" + region + ".api.riotgames.com/lol/summoner/v4/summoners/" \
"by-name/" + summoner + "?api_key=" + api_key
response = requests.get(url).json()
id = response["id"]
name,tier,rank,lp = ranklookup(id,region,api_key)
return render(request,"home.html",{'form' : form,'rank':rank, 'tier' : tier, 'lp' : lp, 'name' : name})
def ranklookup(id,region,api_key):
rankurl = "https://" + region + ".api.riotgames.com/lol/league/v4/entries/by-summoner/" + id + "" \
"?api_key=" + api_key
rankResponse = requests.get(rankurl).json()
if rankResponse[0]["queueType"] == "RANKED_SOLO_5x5":
name = rankResponse[0]["summonerName"]
tier = rankResponse[0]["tier"]
rank = rankResponse[0]["rank"]
lp = str(rankResponse[0]["leaguePoints"])
else:
name = rankResponse[0]["summonerName"]
tier = rankResponse[1]["tier"]
rank = rankResponse[1]["rank"]
lp = str(rankResponse[1]["leaguePoints"])
return name,tier,rank,lp
And my HTML file:
{% extends 'base.html' %}
{% block content %}
<h2> League of Legends Rank lookup</h2> <br>
<div id ="ranklookup">
<form id="myform" method="post"> {% csrf_token %}
{{ form }}
</form>
<button onclick="showDiv()" type="submit" id="but" form="myform" value="button">Submit</button><br><br>
<div id="showRank">
This will get replaced
</div>
<script type="text/javascript">
function showDiv(){
var tier = ' {{ tier }}';
var rank = ' {{ rank }} ';
var name = ' {{ name }} ';
var lp = {{ lp}};
document.getElementById("showRank").innerHTML = "Name: " + name + "</br> Rank: " + tier + rank + "</br> LP: " + lp;
}
</script>
{% endblock %}"

If you are not trying to actually reload the page entirely, you should look for how to handle AJAX form in django (i.e. in this previous answer).
Otherwise, you can just change your views.py code as follows:
def home_view(request,*args,**kwargs):
api_key = "RGAPI-9b573263-7b5a-433e-9e82-a973f5db4749"
name = ""
tier = ""
rank = ""
lp = 0
if request.method == 'GET':
form = NameForm(auto_id='myform')
return render(request,"home.html",{'form' : form, 'showdiv': False})
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
summoner = form.cleaned_data["summoner"]
region = form.cleaned_data["region"]
url = "https://{}.api.riotgames.com/lol/summoner/v4/summoners/by-name/{}?api_key={}".format(region, summoner, api_key)
response = requests.get(url).json()
id = response["id"]
name, tier, rank, lp = ranklookup(id, region, api_key)
return render(request, "home.html", {
'form': form,
'rank': rank,
'tier': tier,
'lp': lp,
'name' : name,
'showdiv': True })
and the template (which now does not use javascript at all):
{% extends 'base.html' %}
{% block content %}
<h2> League of Legends Rank lookup</h2> <br>
<div id ="ranklookup">
<form id="{{ form.auto_id }}" method="post">
{% csrf_token %}
{{ form }}
</form>
<button type="submit" id="but" form="{{ form.auto_id }}" value="button">
Submit</button><br><br>
{% if showdiv %}
<div id="showRank">
Name: {{ name }}<br>
Rank: {{ tier }}{{ rank }}<br>
LP: {{ lp }};
</div>
{% endif %}
{% endblock %}

Related

How do I get the current item in the model from the request?

When a submit button is clicked, I want to be able to know what item the user was on. The button would be on an item's page that the user gets taken to when they click on an item. This button is is part of a django form (PlaceBid) that allows the user to bid for the item. So I want to be able to update what the item's highest bid is if the bid is higher than the current highest. This means that I need to know what item the user was viewing.
I also want to save the bid in a model called Bid and in that model I also need to know what listing the bid is for.
So how do I get the correct item from the model?
The models:
Listing() is the model for the item
Bid() is the model for the bid
views.py:
def bid(request):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
current = Listing.objects.get(pk=request.id) # my attempt to get the current item
highest = current.highest_bid
if form.cleaned_data['bid'] < highest:
obj = Bid()
obj.price = form.cleaned_data['bid']
obj.item = current
obj.user = User.objects.get(pk=request.user.id)
obj.save()
current.highest_bid = form.cleaned_data['bid']
current.save()
return HttpResponseRedirect(request.path_info)
forms.py:
class PlaceBid(forms.Form):
bid = forms.FloatField(required=False, widget=forms.NumberInput(attrs={
'class': 'bid',
}))
html:
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
With the limited code shown, I can only assume at this point that you have a bidding form for each item in a forloop. Example:
{% for item in items %}
...
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
...
{% endfor %}
But here are two methods that can be done...
Use a hidden input field to hold the item object id then retrieve that field name on the server to get the item's id value.
# html
<form action=" {% url 'bid' %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="hidden" value="{{ item.id }}" name="item_id">
<input type="submit" value="Place Bid" class="place-bid">
</form>
# views.py
def bid(request):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
item_id = request.POST.get('item_id', None)
current = Listing.objects.get(id=item_id)
# rest of code follows...
Pass the item's id via the url. (My recommendation)
# html
<form action=" {% url 'bid' item.id %} " method="post">
{% csrf_token %}
{{ bidForm }}
<input type="submit" value="Place Bid" class="place-bid">
</form>
# urls.py
# update the necessary url to accept an id
path('bid/<int:id>/', views.bid, name='bid')
# views.py
def bid(request, id):
if request.method == 'POST':
form = PlaceBid(request.POST)
if form.is_valid():
current = Listing.objects.get(id=id) # id passed to this method used here...
# rest of code follows...
Also, instead of using Listing.objects.get(id=id), I'd suggest using get_object_or_404(Listing, id=id) as this will handle any potential error that Listing.objects.get(id=id) will throw.
You won't get it from the request. Hide it in the form.
class PlaceBid(forms.Form):
bid = forms.FloatField(required=False, widget=forms.NumberInput(attrs={
'class': 'bid',
}))
listing_id = forms.IntegerField(widget=forms.HiddenInput())
Then in your method that displays the form (I'm using function-based views)
def view_listing(request, listing_id)
listing = Listing.objects.get(id=listing_id)
myForm = PlaceBid(initial={"listing_id" : listing_id})
return render("whatever.html", {"listing" : listing, "form" : form })
I suppose another option would be to stash the listing_id in the session, but I try to avoid that.

How to subtract from a Django model?

I am trying to add and subtract 1 from the value of a Django model's IntegerField and display it on the webpage, depending on when a button is clicked.
models.py
class User(AbstractUser):
following = models.ManyToManyField("self", related_name="followers", symmetrical=False)
following_num = models.IntegerField(default=0)
In views.py:
To add: following_num = page_visitor.following_num +1
To subtract: following_num = page_visitor.following_num -1
This is displaying in the html where the number should be displaying:
<django.db.models.query_utils.DeferredAttribute object at 0x0000022868D735E0>
entire view:
def username(request, user):
#get user
user = get_object_or_404(User.objects, username=user)
posts = Post.objects.filter(user=user).order_by('-date_and_time')
page_visitor = get_object_or_404(User.objects, username=request.user)
if user == request.user:
followButton = False
else:
followButton = True
if request.method == "POST":
if "follow" in request.POST:
request.user.following.add(user)
following_num = page_visitor.following_num +1
#following_num = F('User.following_num') + 1
elif "unfollow" in request.POST:
request.user.following.remove(user)
following_num = page_visitor.following_num -1
#following_num = F('User.following_num') - 1
followers_num = page_visitor.following_num
following_num = User.following_num
return render(request, "network/username.html",{
"user": user,
"posts": posts,
"followButton": followButton,
"followers": followers_num,
"following": following_num
})
html
{% block body %}
<h1>{{ user }}</h1>
<h4>Followers:{{ followers }}</h4>
<h4>Following:{{ following }}</h4>
<!--follow/unfollow button-->
{% if followButton == True %}
<form action = "{% url 'username' user %}" method = "POST">
{% csrf_token %}
{% if user not in request.user.following.all %}
<input type="submit" value="Follow" name="follow">
{% else %}
<input type="submit" value="Unfollow" name="unfollow">
{% endif %}
</form>
{% endif %}
<!--displays all the posts-->
{% for post in posts %}
<div class = "individual_posts">
<h5 class = "post_user">{{ post.user }}</h5>
<h6 id = "post_itself">{{ post.post }}</h6>
<h6 class = "post_elements">{{ post.date_and_time }}</h6>
<h6 class = "post_elements">{{ post.likes }} Likes</h6>
</div>
{% endfor %}
{% endblock %}
you reference the class (model) and not the object (instance)
following_num = User.following_num
as you alredy passed your user object to the template you can also access the attributes directly
{{user.following_num }} {{request.user.following_num }}
but you better rename the passed user variable to avoid confusion / errors
Get user information in django templates
Without the html that is supposed to display the number I cant tell why it is displaying that, but if you intend to change the following count then you need to call page_visitor.save() after changing a property of page_visitor in order for it to save the new property's value in the database

Django form field not displaying correct queryset values

The following code is from an multi-vendor ecommerce portal. We need to display different shipping methods according to the store(or vendor) on the checkout summary page.
However even though I get correct queryset while print i.e Store 1 has Test Rest of World Shipping method and Store 2 has UPC and DHL, the rendered form shows incorrect values -
#########################################################
class ShippingCountryChoiceField(forms.ModelChoiceField):
widget = forms.RadioSelect()
def label_from_instance(self, obj):
price_html = format_price(obj.price.gross, obj.price.currency)
label = mark_safe('%s %s' % (obj.shipping_method, price_html))
return label
class ShippingMethodForm(forms.Form):
def __init__(self, country_code, *args, **kwargs):
stores = kwargs.pop('stores')
super(ShippingMethodForm, self).__init__(*args, **kwargs)
for count, store in enumerate(stores, start=1):
method_field = ShippingCountryChoiceField(
queryset=ShippingMethodCountry.objects.select_related(
'shipping_method').order_by('price').filter(shipping_method__store=store),
label=pgettext_lazy('Shipping method form field label', 'Shipping method for %s' % store),
required=True)
if country_code:
queryset = method_field.queryset
method_field.queryset = queryset.unique_for_country_code(country_code)
if self.initial.get('method') is None:
method_field.initial = method_field.queryset.first()
method_field.empty_label = None
self.fields['method_%d' % count] = method_field
print [q.queryset for q in self.fields.values()]
###################################################
#load_checkout
#validate_voucher
#validate_cart
#validate_is_shipping_required
#validate_shipping_address
#add_voucher_form
def shipping_method_view(request, checkout):
country_code = checkout.shipping_address.country.code
stores = checkout.cart.lines.values_list('variant__product__store', flat=True)
stores = Store.objects.filter(id__in=stores)
print checkout.shipping_method
shipping_method_form = ShippingMethodForm(
country_code, request.POST or None, initial={'method': checkout.shipping_method},
stores=stores)
if shipping_method_form.is_valid():
for count, store in enumerate(stores):
checkout.shipping_method[store] = shipping_method_form.cleaned_data['method_%s' % count]
return redirect('checkout:summary')
print [q.queryset for q in shipping_method_form.fields.values()]
return TemplateResponse(request, 'checkout/shipping_method.html', context={
'shipping_method_form': shipping_method_form, 'checkout': checkout})
##############################################################
{% extends "checkout/details.html" %}
{% load i18n %}
{% load gross from prices_i18n %}
{% load bootstrap_form from bootstrap3 %}
{% block forms %}
<h3>{% trans "Shipping address" context "Checkout shipping address title" %}</h3>
{% include "userprofile/snippets/address-short.html" with address=checkout.shipping_address only %}
<p>{% trans "Select other address" %}</p>
<hr>
<form method="post" novalidate>
{% csrf_token %}
{% bootstrap_form shipping_method_form show_label=True %}
<p class="text-md-right">
<button type="submit" class="btn primary">
{% trans "Continue" context "Checkout shipping method primary action" %}
</button>
</p>
</form>
{% endblock %}
I believe the problem is that you are instantiating the widget in the field definition. This could cause state to be shared between different fields. Try changing it to:
class ShippingCountryChoiceField(forms.ModelChoiceField):
widget = forms.RadioSelect
...

django 1.5: not being able to get the values of variable in view

I am new to django. I have django 1.5. I want to take two variables from one template to some other template. but i am not receiving the value instead just nothing received.
Code of the Template from which i want to send variable as a part of url is:
<div class="tags">
{% for tags1 in document.tags.all %}
{% if tags1.name|length > 0 %}
{% with tags1.name as tagts %}{% endwith %}
{{ tags1.name }}
{% endif %}
{% endfor %}
</div>
Code of the URL where i am calling Second View is:
url(r'^tag_related/(?P<username>[-\w\.#]+)/(?P<tagts>)/$',
tag_related_document,
{'template_name': 'document/tag_related_document.html'},
name = 'tag_related_document'
),
Code of the View tag_related_document is:
def tag_related_document(request, username, tagts, template_name , page_template="userprofile/entry_index_page.html"):
"""
documents Related to tag """
try:
notifications = request.user.notifications.all()[:100]
except AttributeError:
notifications = ""
user = get_object_or_404(User, username = username)
try:
user_profile = user.get_profile()
except UserProfile.DoesNotExist:
messages.error(request, "Profile does not exist.")
return HttpResponseRedirect(reverse('homepage'))
documents = Document.objects.filter( Q(tags__in = user_profile.tags.all()) , date_deleted = None).order_by("-date_added")
if not documents:
documents = Document.objects.filter( date_deleted = None).order_by("?")
related_doc_widget = Document.objects.filter( Q(tags__in = user_profile.tags.all()) , date_deleted = None).order_by('?')
if not related_doc_widget:
related_doc_widget = Document.objects.filter( date_deleted = None).order_by("?")
followers_widget = Felloz.objects.get_followers(user = user_profile.user)
followings_widget = Felloz.objects.get_followings(user = user_profile.user)
# recommendations_widget = UserProfile.objects.filter(Q(~Q(user__in = followings_widget) or ~Q(user = request.user) ) ).order_by('?')
recommendations_widget = UserProfile.objects.filter( tags__in = user_profile.tags.all() ).distinct().exclude(user__in = followings_widget).exclude( user = user )
if not recommendations_widget:
recommendations_widget = UserProfile.objects.filter(~Q( user__in = followings_widget ) ).exclude( user = user ).order_by('?')
ideas_widget = Idea.objects.filter(user = user).order_by('?')
for idea in ideas_widget:
is_substring = "<a" in idea.idea_html
if(is_substring is False):
idea.idea_html = truncate_chars(idea.idea_html,50)
else:
idea.idea_html = htmltruncate.truncate(idea.idea_html,50,ellipsis='')
no_of_documents = len( Document.objects.filter(author = user) )
no_of_ideas = len(Idea.objects.filter(user=user))
try:
slug_status = SlugStatus.objects.get(user=user)
except SlugStatus.DoesNotExist:
slug_status = ''
context = {
'slug_status':slug_status,
'documents': documents,
'page_template': page_template,
'followers_widget': followers_widget,
'followings_widget': followings_widget,
'related_doc_widget': related_doc_widget,
'user': user,
'site': Site.objects.get_current(),
'profile':user_profile,
'recommendations_widget': recommendations_widget,
'no_of_documents':no_of_documents,
'no_of_ideas': no_of_ideas,
'notifications': notifications,
'notifications_unread': request.user.notifications.unread(),
'idea_widget': ideas_widget,
'tagts':tagts,
}
print '=============i m here==================='
print tagts
print '=============i m here==================='
#related_doc_widget = Document.objects.filter(~Q(author = user) and ~Q(tags__in = UserProfile.tags.all())).order_by('?')
#recommendations_widget = UserProfile.objects.filter(~Q(user__in = followings_widget) and ~Q(user = user)).order_by('?')
#documents_newsfeed = Document.objects.filter(Q(author = user) | Q(author__in = followings_widget), date_deleted = None).order_by("-date_added")
if request.is_ajax():
template_name = page_template
return render_to_response(template_name, context, context_instance=RequestContext(request))
return render_to_response(template_name, context, context_instance=RequestContext(request))
The code of the Second Template where i want to show that variable is:
{% if profile.user == request.user %}
<h2 class="mainHeading"> Documents Related To: {{tagts}} </h2>
{% else %}
<h2 class="mainHeading"> Documents Related To: {{tagts}}</h2>
{% endif %}
But i am getting here nothing.... Please help thanks in advance....
You are closing {% with %} before {% url %} so url is being based on empty value, i think it's the reason.
And please, in future avoid posting large pieces of irrelevant code. Shrink it down to minimal amount which is needed to reproduce error.
Should be like this unless the code doesn't resemble the one you posted.
{% for tags1 in document.tags.all %}
{% if tags1.name|length > 0 %}
{% with tags1.name as tagts %}
{{ tags1.name }}
{% endwith %}
{% endif %}
{% endfor %}

Trouble accessing dictionary values inside a Django template

Here's my view function:
def detail(request, movie_id):
movie = Movie.objects.get(id = movie_id)
movieReleases = Release.objects.filter(movie = movie)
reviews = Review.objects.filter(movie = movie)
initRating = 0
if request.user.is_authenticated():
user = Account.objects.get(user = request.user.id)
try:
myreview = Review.objects.get(movie = movie, user = user)
initRating = myreview.rating
except:
pass
releaseContext = dict()
for release in movieReleases:
if release.isReleased():
releaseContext[release.id] = {'buttonURL' : reverse('movies.views.add', args=(release.id,)), 'buttonText' : 'Add to cart'}
elif MovieReleaseReminder.objects.filter(account=user, movie=release).exists():
releaseContext[release.id] = {'buttonURL' : reverse('movies.views.unsubscribeFromReleaseReminder', args=(release.id,)), 'buttonText' : 'Unsubscribe from release reminder'}
else:
releaseContext[release.id] = {'buttonURL' : reverse('movies.views.subscribeForReleaseReminder', args=(release.id,)), 'buttonText' : 'Subscribe to release reminder'}
if MovieUpdateSubscription.objects.filter(account=user, movie=movie).exists():
movieSubscribeURL = reverse('movies.views.unsubscribeFromUpdates', args=(movie.id,))
movieSubscribeButtonText = 'Unsubscribe from updates'
else:
movieSubscribeURL = reverse('movies.views.subscribeForUpdates', args=(movie.id,))
movieSubscribeButtonText = 'Subscribe for updates'
else:
releaseContext = None
movieSubscribeURL = None
movieSubscribeButtonText = None
averageRating = calculateAverageRating(movie)
t = loader.get_template('movies/detail.html')
c = RequestContext(request, {'movie' : movie,
'movieReleases' : movieReleases,
'releaseContext' : releaseContext,
'reviews': reviews,
'averageRating': averageRating,
'initRating': initRating,
'movieSubscribeURL' : movieSubscribeURL,
'movieSubscribeButtonText' : movieSubscribeButtonText})
return HttpResponse(t.render(c))
Here's the template code in question:
{% if movieReleases%}
<table border="1px">
{% for release in movieReleases %}
<tr>
<td>{{release.format}}</td>
<td>{{release.region}}</td>
<td>{{release.price}}</td>
{% if user.is_authenticated %}
{% with release_id=release.id %}
<td><form action="{{ releaseContext.release_id.buttonURL }}" method="post">{% csrf_token %}<input type="submit" value="{{ releaseContext.release_id.buttonText }}" /></form></td>
{% endwith %}
{% endif %}
</tr>
{% endfor %}
</table>
{% endif %}
The problem is that both {{ releaseContext.release_id.buttonURL }} and {{ releaseContext.release_id.buttonText }} are evaluating to the empty string when the template is rendered, even though I've checked in the debugger that releaseContext has the appropriate data. What am I missing?
Since releaseContext is a dictionary, attribute lookup (x.y) is not what you require, but element lookup (x[y]).
So instead of:
{{ releaseContext.release_id.buttonURL }}
use
{{ releaseContext['release_id']['buttonURL'] }}
Try getting the value out of the dictionary before handing it to the template:
{% display = releaseContext['release_id']['buttonURL'] %}
{{ display }}

Categories

Resources