I'm utilizing the Django Bootstrap Toolkit for styling my website and have run into a slight issue. I am trying to have a form embedded within my base HTML that is essentially a user switch, whereby given a list of names, the user can decide whether he or she wants to switch users while utilizing the site rather than be logged in as "Guest" (the site is internal, so there's no real need for credential authentication). The views I have are such:
from django.shortcuts import render, render_to_response, redirect
from django.template import RequestContext
from django.http import HttpResponse, Http404
import datetime
myUsers = ['User A', 'User B', 'User C', 'User D', 'User E', 'Guest']
def index(request):
# make login default guest if not logged in
if not 'myUser' in request.session:
request.session['myUser'] = 'Guest'
# grab user if we've submitted login form from this page
if request.method == 'POST':
if 'myUser' in request.POST:
request.session['myUser'] = request.POST['myUser']
return render(request, 'home/index.html', {'myUsers': myUsers})
def login(request, myUser):
request.session['myUser'] = myUser
return redirect('index')
The base HTML template that contains the form is the following:
{% load bootstrap_toolkit %}
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.no-icons.min.css" rel="stylesheet">
<link href="//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
{% bootstrap_javascript_tag %}
</head>
<body>
{% block header %}
<h3 style="font-family: Source Sans Pro, Myriad Pro; font-size: 16px; margin-left: 20px">
{% if request.session.myUser %}
Current User: {{ request.session.myUser}}
<div class="navbar">
<form class="navbar-form pull-left" action="" method="post" id="myUser">
{% csrf_token %}
<select name id class="form-control" style="width: 200px;">
{% for myUser in myUsers %}
<option value="{{ myUser }}">{{ myUser }}</option>
{% endfor %}
</select>
<button id="formSubmit" type="submit" class="btn btn-default">Change User</button>
</form>
</div>
{% else %}
No User Logged In
<div class="navbar">
<form class="navbar-form pull-left" action="" method="post" id="myUser">
{% csrf_token %}
<select name id class="form-control" style="width: 200px;">
{% for myUser in myUsers %}
<option value="{{ myUser }}">{{ myUser }}</option>
{% endfor %}
</select>
<button id="formSubmit" type="submit" class="btn btn-default">Login</button>
</form>
</div>
{% endif %}
</h3>
{% endblock %}
<hr>
<h1 style="text-align:center; font-family: Myriad Pro; font-size: 60px; padding: 10px">MySite</h1>
<div style="text-align:center" name="content">
{% block content %}
{% endblock %}
</div>
{% block footer %}
{% endblock %}
</body>
</html>
I get default Guest login, which is not a problem, but I do not unfortunately get any kind of user switching when the user clicks on the dropdown menu and selects another individual. It is likely I am missing something, but I unfortunately have been unable to figure it out if so. Help is very much appreciated!
Your problem is the following, <select name id class="form-control" style="width: 200px;">
You haven't specified the name of your <select></select> form field.
Simply modify your code to include the proper form field name.
<select name="myUser" class="form-control" style="width: 200px;">
Note that its highly recommended that you use a Django Form to process the form data.
Related
So here's my code first and foremost. I'm new to Django and trying to create an ecommerce site. The way it works is that the admin creates products and users come on to the site and purchase them. The site uses Stripe to process payments.
views.py:
from django.shortcuts import render
from django.views import generic
from django.core.paginator import Paginator
from django.conf import settings
import stripe
import decimal
stripe.api_key = settings.STRIPE_SECRET_KEY
from .models import Product
# Create your views here.
class ProductListView(generic.ListView):
model = Product
paginate_by = 3
def get_context_data(self, **kwargs): # new
context = super().get_context_data(**kwargs)
context['key'] = settings.STRIPE_PUBLISHABLE_KEY
return context
def charge(request):
if request.method == 'POST':
charge = stripe.Charge.create(
amount=round(decimal.Decimal(request.POST['price'])),
currency='usd',
description='A Django charge',
source=request.POST['stripeToken']
)
return render(request, 'store/charge.html')
product_list.html:
{% extends 'home/base_generic.html' %}
{% load static %}
{% load cool_paginate %}
{% block add %}
<link rel="stylesheet" href="{% static 'store/css/products.css'%}">
{% endblock %}
{% block title %} <title> Store </title> {% endblock %}
{% block content %}
<div class="row">
{% for product in product_list %}
<div class="col-sm-4">
<div class="card" id="django-card" style="width: 300px; height: 350px;">
<img class="card-img-top" src="{{ product.image.url }}" height=150px width=150px>
<div class="card-body">
<h5 class="card-title">{{ product.name }}</h5>
<p class="card-text">
{{ product.description }} And only {{ product.price }}!
</p>
<form action="{% url 'charge' %}" method="post">
{% csrf_token %}
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ key }}"
data-description="A Django Charge"
data-amount= "{{ product.price_in_cents }}"
data-locale="auto">
</script>
<input type="hidden" name="price" value="{{ product.price_in_cents }}">
</form>
</div>
</div>
</div>
{% endfor %}
<div class="container-fluid">
<div style="margin-top: 50px;"> {% cool_paginate page_obj=product %}</div>
</div>
</div>
{% endblock %}
So, my question is, when the user selects a product to purchase, how do I tell the view to use that products price? The way I've been doing it is using a hidden html value field in the input. But this can't be secure. Thanks to all who take the time to respond.
Ok, after a few grueling hours of work I solved it. I opted to keep the hidden field form but instead of using price I used it to return the product primary key. Which I used in the view to grab the price and make charges.
I have a problem I have a site which displays users but it displays users not in a straight line but in an inverted pyramid. It could be because I am using django-filter app but it shouldnt create a problem as such. The profiles right at the end (especially in the mobile view) overlap and drag. It gets worse as profiles increase. Is it possible to align the profiles or user list in a straight line?
Please find below my code.
filters.py(for djang-filters app)
import django_filters
from userprofile.models import UserProfiles
class UserProfilesFilter(django_filters.FilterSet):
class Meta:
model = UserProfiles
fields = ['gender', 'age', 'Nationality','preference', 'Country',
'City']
views.py
#login_required
def profiles_list(request):
filter = UserProfilesFilter(request.GET, queryset =
UserProfiles.objects.all().order_by('-pub_date'))
return render(request,"userprofile/user_list.html", {'filter': filter})
user_list.html
{% extends 'base.html' %}
{% block content %}
{% load static %}
{% load bootstrap %}
<div class="container">
<form class="form-horizontal col-md-4 col-lg-4 col-sm-4" action=""
method="get">
{{ filter.form|bootstrap}} {% csrf_token %}
<input type="submit" value='search'/>
</form>
{% for profile in filter.qs %}
<div class="col-md-12 col-lg-12 col-sm-12 col-xs-12">
<hr>
<a href="{% url 'userprofile:profileview' profile.user %}"><h3>{{
profile.user }}</h3></a>
<br>
<img src="{{ profile.image.url }}" class="rounded mx-auto d-block img-
responsive float-left" style= "max-height: 100px; max-width: 100px;">
<br><br>
<br><br> <br>
<div class="font-weight-normal text-justify">
Gender: {{ profile.gender }}
<br>
Country: {{ profile.Country }}
<br>
Description: {{ profile.summary }}
<br>
Preferences: {{ profile.preference }}
<br><br>
{% endfor %}
</div>
</div>
<!--adnow ad-->
<script type="text/javascript">
(sc_adv_out = window.sc_adv_out || []).push({
id : "575193",
domain : "n.ads1-adnow.com"
});
</script>
<script type="text/javascript" src="//st-n.ads1-adnow.com/js/a.js">
</script>
<div id="SC_TBlock_575193" class="SC_TBlock">loading...</div>
<!--adnow finishes-->
{% endblock %}
You should close your div tags in each for loop, since you start them within the loop.
Change:
{% endfor %}
</div>
</div>
to:
</div>
</div>
{% endfor %}
I have a list of multiple objects from my database (named "plp's"), arranged in a table. Next to each "plp" element I have a button "Edit" to modify that particular entry.
Next, I redirect the user to a new url, where I pass the id of that "plp", and show the form to edit it, with a "save" button.
After pressing the "save", which is request.POST, I want to redirect the user back to the first url, with the list of all the "plp" objects in one list. That means to the site, where he first pressed "Edit".
Can I somehow save the url of where the "Edit" was clicked, and pass it to my views.py?
Thank you
listdns.html:
<td>
Uredi
</td>
urls.py:
rl(r'^(?P<plp_id>\d+)/uredi$', plp_list_uredi,name="plpuredi")
views.py:
def plp_list_uredi(request, plp_id=None):
moj_plp=PLPPostavka.objects.get(id=plp_id)
form=PLPPostavkaForm(request.POST or None,request=request,dns=moj_plp.dns, instance=moj_plp)
context ={
'plp':moj_plp,
'form':form,
}
if request.POST:
if form.is_valid():
plp = form.save()
return redirect(request.path)
return render(request, "plp_pos/uredi.html",context)
uredi.html
<form action="" method="POST">
{% csrf_token %}
<div class="box">
<div class="box-header">
<h4 class="box-title">
Urejanje PLP Postavke
</h4>
</div>
<div class="box-body">
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}" class="col-md-2 control-label detail">{{ field.label }}</label>
<div class="col-md-10">
{% if field|field_type == "datefield" %}
{% render_field field class+="form-control dateinput" %}
{% else %}
{% render_field field class+="form-control" %}
{% endif %}
</div>
</div>
{% endfor %}
</div>
<div class="box-footer">
<div class="box-tools pull-right">
<input type="submit" value="Shrani" class="btn btn-primary" />
</div>
</div>
Don't you only have 1 page to edit all the elements? Then you could perhaps hardcode the link e.g.
return HttpResponseRedirect(my_edit_url)
If this doesn't work and you need to go 2 pages back take a look at this post:
How to redirect to previous page in Django after POST request
Im trying to create a form where the user selects from a gallery of images and it saves it to the database. The code below currently renders some radio buttons in the html output. Is there anyway I can change these to images i have saved in a static directory so the user can click on images instead? Would be great if I could change what it saves in the database to what I needed instead of image urls as well. Theres lots of documentation on uploading images but not much I could find on selecting images. Im using django 1.9.7 and python 3.5
models.py
client_choices = (('client1', 'Client 1'),
('client2', 'Client 2'),
('client3', 'Client 3'),
('client4', 'Client 4'),
('client5', 'Client 5'))
class ClientSelect(models.Model):
client = MultiSelectField(choices=client_choices)
forms.py
from app.models import ClientSelect
class ClientSelectForm(forms.ModelForm):
class Meta:
model = ClientSelect
fields = '__all__'
views.py
class FormWizard(SessionWizardView):
template_name = "app/clientchoices.html"
#define what the wizard does when its finished collecting information
def done(self, form_list, **kwargs):
form_data = process_form_data(form_list)
return render_to_response('app/about.html', {'form_data': form_data})
urls.py
url(r'^clientchoices$', FormWizard.as_view([ClientSelectForm]) , name='clientchoices'),
clientchoices.html
{% load staticfiles %}
{% block content %}
<section class="content">
<div class="container">
<div class="fit-form-wrapper">
<h2>Client Choices</h2>
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
{% for field in form %}
{{field.error}}
{% endfor %}
<form action="{% url 'clientchoices' %}" method="post">{% csrf_token %}
<table>
{{ wizard.management_form }}
{% if wizard.form.forms %}
{{ wizard.form.management_form }}
{% for form in wizard.form.forms %}
{{ form }}
{% endfor %}
{% else %}
{{ wizard.form }}
{% endif %}
</table>
{% if wizard.steps.prev %}
<button class="btn btn-brand" name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">"First Step"</button>
<button class="btn btn-brand" name="wizard_goto_step" type="submit" value="{{ wizard.steps.prev }}">"Previous Step"</button>
{% endif %}
<input class="btn btn-brand" type="submit" value="Submit" />
</form>
</div>
</div>
</section>
{% endblock %}
Any help is appreciated thank you
I am using wtforms-recaptcha in order to get the Recaptcha to show.
pip install wtforms-recaptcha
I guided myself on this site to make the installation:
https://pypi.python.org/pypi/wtforms-recaptcha
The problem is that the recaptcha code is being echoed into the form. That is, I see the recaptcha's code on the form and not the recaptcha itself:
<script type="text/javascript" src="https://www.google.com/recaptcha/api/challenge?k=6LeCJvUSAAAAAAvqwJEueVdV0wyNLPtX6KWSTdXp"> </script> <noscript> <iframe src="https://www.google.com/recaptcha/api/noscript?k=6LeCJvUSAAAAAAvqwJEueVdV0wyNLPtX6KWSTdXp" height="300" width="500" frameborder="0"></iframe><br> <textarea name="recaptcha_challenge_field" rows="3" cols="40"> </textarea> <input type="hidden" name="recaptcha_response_field" value="manual_challenge"> </noscript>
Form code on form.py:
from wtforms import PasswordField, StringField, validators, widgets
from wtforms.form import Form
from wtfrecaptcha.fields import RecaptchaField
class ContactForm(Form):
"""Enables the user to provide feedback."""
first_name = StringField('First Name', [
validators.DataRequired()
])
last_name = StringField('Last Name', [
validators.DataRequired()
])
captcha = RecaptchaField('Captcha', [], public_key='6LeCJvUSAAAAAAvqwJEueVdV0wyNLPtX6KWSTdXp', private_key='6LeCJvUSAAAAADcUvYyLv8kt9ARiTAluDGqHBumY', secure=True)
Calling the form from within the HTML:
<form method="post">
{% for field in form %}
<div class="form-group{% if field.errors %} has-error has-feedback{% endif %}">
<div class="row">
<div class="col-xs-12 col-md-4">
{{ field.label(class="control-label") }}
</div>
<div class="col-xs-12 col-md-8">
{{ field(class="form-control") }}
</div>
</div>
{% if field.errors %}
<span class="glyphicon glyphicon-remove form-control-feedback"></span>
{% endif %}
{% for error in field.errors %}
<p class="help-block text-danger">
<span class="glyphicon glyphicon-remove"></span>
{{ error }}
</p>
{% endfor %}
</div>
{% endfor %}
<br>
<button type="submit" class="btn btn-primary">{{ title }}</button>
</form>
Route call code:
#app.route('/contact', methods=['GET', 'POST'])
def contact():
"""Display the contact page."""
form = ContactForm(request.form, captcha={'ip_address': request.remote_addr})
if request.method == 'POST' and form.validate():
return "Thank you for contacting us."
return render_template(
...
)
The issue is that WTForms-RECAPTCH does not return a safe string, but instead returns a unicode string. The underlying issue needs to be fixed here (by returning an instance of wtforms.widgets.core.HTMLString or something else that provides an __html__ method).
To work around the problem for now you should simply mark the field as safe in your template:
<div class="col-xs-12 col-md-8">
{{ field(class="form-control") | safe }}
</div>
Or, alternately, only mark the re-captcha field as safe:
<div class="col-xs-12 col-md-8">
{% if field.short_name == "captcha" %}
{{ field(class="form-control") | safe }}
{% else %}
{{ field(class="form-control") }}
{% endif %}
</div>
There is a PR for this issue and this is fixed as of version 0.3.2