Change a view varible file with the html file - python

I'm making an online store and I add to it the Stripe Checkout for payments, everything works correct, the problem is that the view function only manages one price. It looks like this:
def charge(request): # new
if request.method == 'POST':
charge = stripe.Charge.create(
amount=179900,
currency='mxn',
description='Bota Caballero',
source=request.POST['stripeToken']
)
return render(request, 'charge.html')
the amount says the price, In my html homepage I have a select tag, it defines the cost of the product
<select id="modelo" onchange="modelo()" class="select__option" required>
<option>Selecciona Modelo...</option>
<option>$1799</option>
<option>$1299</option>
<option>$1199</option>
</select>
I would like to change the amount variable of the view file depending on what is selected in the select tag. Any idea?

You would typically pass the value via your form and retrieve it with request.POST.get('amount', None) however..
You should never pass pricing from a client editable form.
As an example, if you POST a form with your selection to your view and then dynamically set that value to your amount, you set yourself up to some serious pricing issues.
The end user could simply modify the POST data and set whatever value they like.
I think the best solution here would be to:
Store the pricing you have set in your database
Pass the product identification or similar via POST
Retrieve pricing from database
Set dynamic pricing based on database response

I assume that your select tag is within a form. You can simply retrieve the value/option selected by your user and use it in your view function to set the Stripe charge.
<select id="modelo" name="modelo_price" onchange="modelo()" class="select__option" required>
<option>Selecciona Modelo...</option>
<option>$1799</option>
<option>$1299</option>
<option>$1199</option>
</select>
def charge(request): # new
if request.method == 'POST':
# Here you retrieve the value submitted by your user
charge_amount = int(request.form.get('modelo_price')) * 100
charge = stripe.Charge.create(
amount=charge_amount,
currency='mxn',
description='Bota Caballero',
source=request.POST['stripeToken']
)
return render(request, 'charge.html')

Related

Django - Pass Object ID after redirect

Apologies if the question title is wrong but I am unsure of exactly what I need to do. I am building a scrum app where users can create user stories and add them to sprints. I want to have two separate ways of creating stories. If the user is creating a story from the backlog, the story that has been created will not be assigned to a sprint, but the user can also add a story from a sprint's detail screen. I want to make it so that if they add a story from a specific sprint's page, that story's sprint field is populated with that sprint.
The way I have tried to go about this is by creating two different functions in my views.py file and two separate templates. I am able to create the story without relating to a sprint as intended, but I cannot think of a way to get the id of the sprint where I navigated from to get to the new template.
For reference I have included my function for creating stories without relating to a sprint:
def create_story(response, id=None):
user = response.user
if response.method == "POST":
form = CreateNewUserStory(response.POST)
if form.is_valid():
name = form.cleaned_data["name"]
description = form.cleaned_data["description"]
status = form.cleaned_data["status"]
assignee = form.cleaned_data["assignee"]
estimate = form.cleaned_data["estimate"]
userstory = UserStory(name=name, description=description, status=status, assignee=assignee, estimate=estimate)
userstory.save()
response.user.userstories.add(userstory)
return HttpResponseRedirect("/backlog")
else:
form = CreateNewUserStory()
return render(response, "main/create_story.html", {"form": form})
If any more information or code is required please let me know, thank you!
You can define 2 URLs, one with an optional sprint ID:
urls.py:
path('story/<int:sprint_id>/add/', views.create_story, name='create_story_for_sprint'),
path('story/add/', views.create_story, name='create_story_for_backlog'),
views.py:
def create_story(request, sprint_id=None):
...
form = CreateNewUserStory(response.POST, initial={"sprint_id": sprint_id})
if form.is_valid():
...
sprint_id = form.cleaned_data["sprint_id"]
create_story.html:
<form action="..." method="POST">
<input type="hidden" name="sprint_id" value="{{ sprint_id|default_if_none:'' }}">
...
Then, in your sprint page, use
Add Story
and in your backlog page:
Add Story

WTForm used in two different views validate only using one view

I'm having a problem using a WTForm in two different views. One view creates a new item, using the form data. The other view display information for items already in the database and the user should be able to update the form data from there.
I can create and view the items in the database. The problem is updating the information when in in the display view. The steps I take are something like:
Create a item in /create. Before saving to database check that the same ID is not already in database. If exists show a flash and do not permit saving the item. Reloading /create
To display information about a existing item the route /display/<item> call the database, populate the form and show the information using the same form.
Desired behavior
To update information when in /display/<item>. After updating any field data and pressing the submit button, the form should save to the database and reload /display/<item>.
Actual behavior
After pressing the submit button the form takes me back to the /create route, and performs the ID validation.
I don't understand why, being in a different view /display/<item>, the form's submit button takes me to the /create view.
The code goes something like this:
This is a simple form
class ItemForm(FlaskForm):
id = IntegerField("id", validators=[DataRequired()])
name = StringField("Email", validators=[DataRequired()])
submit = SubmitField("Submit")
With this I create a new item in the database, checking that the same Id is not already in the database:
#app.route("/create", methods=["GET", "POST"])
def create():
form = ItemForm()
if form.validate_on_submit():
item = item = Item.query.filter(Item.id == form.id).first()
# Check the same id is not already created
if item is not None:
flash('item already in database')
return redirect(url_for("create"))
item = Item()
form.populate_obj(item)
db.session.add(item)
db.session.commit()
return redirect(url_for("display", item = form.id))
else:
return render_template("create.html", form=form)
And then after there is created items in the database i can call a display route. In this route I should be able to update the fields in the form and save it to the database. Whit out validating as the the same ID is already present in the database (I'm updating, no creating a new one).
#app.route("/display/<item>", methods=["GET", "POST"])
def display(item):
item = Item.query.filter(Item.id == item).first()
form = ItemForm(obj=item)
if form.validate_on_submit():
form.populate_obj(item)
db.session.add(item)
db.session.commit()
return redirect(url_for("display", item=form.id))
else:
return render_template("display.html", form=form)
The problem is that when in the /display/<item> route, the submit button takes me back to the /create route. Performing the validations in there. Of course the item is already created in the database so I get the flash and I'm redirected to /create, when it should reload /display/<item>.
Could someone point me in the right direction, please. Thank you all!
My mistake, but #the_gañañufla asked the right question. The problems of coding alone.
I had added an action to the HTML and i forgot to remove it.
I had
<form id="form_item" action="{{ url_for('create') }}" class="form" method=post>
After correct it I have:
<form id="form_product" action="" class="form" method=post>

Displaying the content on a different html based on the primary key

I am using Django to create a site. I have Table called notice as below
Models.py
class Notice(models.Model):
Notice_No=models.AutoField(primary_key=True)
Content=models.TextField(max_length=5000, help_text="Enter Owner Name")
I am using a for loop to display the all these fields on my template page as
Notice No, Content, Date of issue, Date of expiry. I have provided a hyperlink to the all the content values which take it to another HTML play with a proper notice formal of a CHS. Now what I wanna do is if I click on let's say notice of notice no-1. I only want to display the content of that notice on the next page. If I click on notice _no 2, it should only display the contents of that notice. I'm new to python so not sure how to do this. How do I go about this?
Notice.html is the page that displays the table. Noticesoc.html display is where the content should be displayed.
views.py
def notices(request):
Notice_all=Notice.objects.all()[:50]
return render(
request,
'notices.html',
context={'Notice_all':Notice_all}
)
def noticesoc(request):
Notice_all=Notice.objects.all()
return render(
request,
'noticesoc.html',
context={'Notice_all':Notice_all}
)
Send the primary key of the data you want to see in detail.
<td style="color:white; font-family:helvetica; font-size:15px;">
<a class="nav-link" href="{% url 'noticesoc' Notice.pk %}">
Click here to view the contents</a>
</td>
url( r'^noticesoc/(?P<pk>\d+)/$', 'noticesoc')
Then in the view. Use .get to get the information Notice and then render it.
Ex:
def noticesoc(request, pk):
Notice=Notice.objects.get(id=pk)
return render(
request,
'noticesoc.html',
context={'Notice_all':Notice}
)
in reference to this ....
Still doesn't work. Error=local variable 'Notice' referenced before assignment. Can you see my url.py(previous comment) and see if it's correct
you will notice that the model name and the function name are similar hence instead of django differentiating the two it assumes them as similar with the first code to run as the model then the view function
try to use another name for your view function and call the name different and unique from the model name for instance
def noticesoc(request, pk):
Notice=Notice.objects.get(id=pk)
return render(
request,
'noticesoc.html',
context={'Notice_all':Notice}
)
use this instead
def noticesoc(request, pk):
note=Notice.objects.get(id=pk)**
return render(request,'noticesoc.html',context={'note':note}
emphasized text

Grab and manipulate user data without models

I'm not sure if this is even possible, but I would like to grab a user's input, pull it into my views.py, manipulate it, and then use that data in other views.
I do not need this data stored in a database, as I won't be referencing it again, and I want to keep this as lightweight as possible.
Currently, I'm trying to pull data from espn's fantasy football site using the python library espnff. My homepage consists of a textfield box and a submit button (Think of google.com).
I have functions set up that will comb through an espn url such as http://games.espn.com/ffl/clubhouse?leagueId=123456 to grab the leagueID, from there I make use of espnff to grab more info on that league.
My ideal use case is someone comes to my site, copies and pastes their league url like the one above, clicks submit and then brings them to https://example.com/{{ leagueID}/ which will display different info that I gather.
I have not found a way to do this without submitting the user input to a model. Is possible to avoid using the database? If so how?
Not sure I understood it right, but what you are trying to do can easily be done without using any models/database or any other kind of persistent storage.
The user submits that information using the form, you grab the URL from the request object in your view, parse the URL to get the league_id and then redirect the user to /{league_id}.
Then on that view, you gather the league_id parameter (from the url), use the library (espnff) to fetch the data with that id and then render the template with that data.
For example, the implementation would be something in these lines:
Make a form in your html template:
<form method="post" action="/">
{% csrf_token %}
<input type="text" name="league_url"/>
<input type="submit" value="Submit" />
</form>
in urls.py:
url(r'^$', index_view, name="index"),
url(r'^(?P<league_id>[0-9]+)$', league_view, name="league_view")
in views.py:
def index_view(request):
if request.method == 'POST':
league_url = request.POST.get('league_url', None)
# Your code to parse the URL and extract the ID
return HttpResponseRedirect('/{}'.format(league_id))
else:
# render form template
def league_view(request, league_id):
# your code here using the league_id
# and render the page with data
(I didn't tested that code, I just wrote it quickly as an example of the flow)
The django documentation describes quite extensively how to do caching with django. You can find the documentation on how to set that up here
Once it's been set up you simply use the cache in the following way
from django.core.cache import cache
cache.set('my_key', 'my_value', 60) # number is in seconds
value = cache.get('my_key')
You can provide dictionaries and such as values. The caching framework will serialize that for you using pickle.

Django add single fields to Model form using AJAX call

I have a Model form. The form contains a button "Add more Field". Clicking this button sends an AJAX call which should add a textfield to the form. Any number of "textfields" can be added.
I am not sure if Django-Formsets is the correct way to do it as I need to store the data of "extra added fields" in the same Model Form's Table in the database.
How can I achieve this ?
I did something similar to this recently, and my solution was to subclass the form dynamically, providing only the field needed, and rendering just that field:
from forms import SomeModelForm
from models import SomeModel
def view_name(request,pk,field):
SomeModelFieldForm(SomeModelForm):
class Meta(SomeModelForm.Meta):
fields = (field,)
inst = SomeModel.objects.get(pk=pk)
form = SomeModelFieldForm(instance=inst)
#the rest of your view goes here...
#...send only the form's field:
ctx = {'field': form[field]}
return render_to_response("template",ctx)
This takes advantage of your original form's specifics - i.e., if you have specially defined widgets, or other restrictions, or something. It then restricts the entire form to a single field. This is to allow the validation of a single field on an existing model.
However, you don't want to send the entire form, you only want to send the single field. form[field] is a django.forms.forms.BoundField that represents the specific field you pass in.
For example, if you were working with the User model from django.contrib.auth.models, and you created a form for a specifi user, in idle calling form["username"] would return:
<django.forms.forms.BoundField object at 0x01354750>
and calling print form["username"] would print:
<input id="id_username" type="text" name="username" value="name_of_user" maxlength="30" />

Categories