Get the details of selected item - python

I have a part table and delivery instruction table (dins). To create a dins, I have to choose a part name. So what I want to do is, after choosing the part name from the dropdown that part's price will be visible in the form.
In the Part table, I have the price value for the specific part name. So during the creation of dins, after choosing such an example part name is X, then the form should show what is the price of that chosen part (X part) price.
Any idea how to make that happen?
views.py
def create_deliveryins(request):
from django import forms
form = DeliveryInsForm()
if request.method == 'POST':
forms = DeliveryInsForm(request.POST)
if forms.is_valid():
product = forms.cleaned_data['product']
usage = forms.cleaned_data['usage']
part= forms.cleaned_data['part']
deliveryins = DeliveryIns.objects.create(
usage=usage,
product=product,
part=part,
)
return redirect('dins-list')
context = {
'form': form
}
return render(request, 'store/addDins.html', context)
HTML
<form action="#" method="post" novalidate="novalidate">
{% csrf_token %}
<div class="form-group">
<label for="product" class="control-label mb-1">Product</label>
{{ form.product }}
</div>
<div class="form-group">
<label for="part" class="control-label mb-1">Part</label>
{{ form.part}}
</div>
<div class="form-group">
<label for="usage" class="control-label mb-1">Usage</label>
{{ form.usage }}
</div>
</form>

Create a hidden form field that has the part prices for each part.
Use Javascript or Jquery to update the form field for price and show it whenever the form part field is changed.
This would prevent the need for ajax, or additional views or requests.
You would only need to slightly modify your view and template.

Related

Store dynamic choice field form from api call to be able to pass the verification in post request

I'm working on an app that can display the events coming from a google calendar.
To be able to do this, the user need to fill a form with the start date, end date, timezone and select a calendar.
I'm new to Django and it's ok to make a form with date, text, checkbox but regarding the choice field, it fail because the values are not present in the choice list.
Select a valid choice. johndoe#gmail.com is not one of the available choices.
This is normal because the values will change according to the user.
For that I'm calling the google calendar api before showing the page at GET request.
I tried to add it to the form but of course, it doesn't stay while the post method is called.
Is there a way to store the value without using the session or database?
How do you manage dynamic choice field that isn't coming from database?
Here is my code:
form.py
from django import forms
class events_filters(forms.Form):
start = forms.DateField(label='Start date')
end = forms.DateField(label='End date')
calendar = forms.ChoiceField(label='Select calendar')
timezone = forms.BooleanField(label="Show timezone")
view.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
from allauth.socialaccount.models import SocialApp, SocialAccount
import csv
from django.http import HttpResponse
from .forms import events_filters
# Create your views here.
# Main page
#login_required(login_url='/accounts/google/login/')
def index(request):
if request.method == "GET":
creds = create_credentials(request)
calendars = getCalendars(creds) #function to get the calendars
form = events_filters()
form.fields["calendar"].choices = calendars #tried to add the calendars to the form, it work but of course doesn't stay for the post request
return render(request, "ts_index.html", context={"calendars":calendars, 'form': form})
if request.method == "POST":
form = events_filters(request.POST)
if form.is_valid(): # Failed here because the form doesn't know the values to be validated. I would like to be able to validate the data without passing by the client to be sure that the user use an email in the list. I would also like to avoid to call the calendar api again.
parameters = {
"start_date" : form["start"] + "T00:00:00.000Z",
"end_date" : form["end"] + "T00:00:00.000Z",
"calendar_id" : form["calendar"],
}
# Use the access token to authenticate with the Google Calendar API
creds = create_credentials(request)
events = getEvents(creds, parameters["start_date"], parameters["end_date"], parameters["calendar_id"])
return render(request, "ts_input_data.html", context={'events':events, "parameters": parameters})
else :
print("Data not valid")
Html page
{% extends 'head.html' %}
{% load socialaccount %}
<!--Block content goes below-->
{% block content %}
<h1>Input data</h1>
<!-- Select the dates -->
<form method="POST" class="d-flex flex-column justify-content-center align-items-center" >
<!-- Key for CSRF -->
{% csrf_token %}
<!-- Select the agenda -->
<div class="mb-3 w-100">
<label for="calendar" class="form-label">Select calendar</label>
<select name="calendar" id="calendar_id" class="form-control">
{% for c in calendars %}
<option value=" {{ c.0 }} ">{{ c.1 }}</option>
{% endfor%}
</select>
</div>
<!-- Start date -->
<div class="mb-3 w-100">
<label for="start_id" class="form-label">Start date</label>
<input type="date" class="form-control" id="start_id" name="start">
</div>
<!-- End date -->
<div class="mb-3 w-100">
<label for="end" class="form-label">End date</label>
<input type="date" class="form-control" id="end_id" name="end">
</div>
<!-- End date -->
<div class="mb-3 w-100">
<label for="timezone" class="form-label">Show time-zone</label>
<input type="checkbox" class="form-check-input" id="timezone_id" name="timezone" checked>
</div>
<!-- Submit -->
<button type="submit" class="btn btn-primary w-100">Submit</button>
</form>
{% endblock %}

Populate textarea field using WTForms

As I understand it, if you want to populate a textarea you place the text between the textarea tags. However I am using WTForms. How can I pre-populate the form from views or in my template?
FORM
class ModuleSectionForm(FlaskForm):
title = StringField('Section Title', validators=[DataRequired()])
description = TextAreaField('Description', validators=[DataRequired()])
submit = SubmitField('Add Section')
VIEW
#modules.route('/update_section/<name>/<title>', methods=['GET', 'POST'])
def update_section(name, title):
form = ModuleSectionForm()
module = Module.objects(title=name).first()
section = None
for sect in module.sections:
if sect.title == title:
section = sect
#if form.validate_on_submit():
#save data
return render_template('modules/update_section.html', section=section, form=form)
TEMPLATE
<form method="post" action="{{ url_for('modules.update_section', name=name) }}">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.title.label(class="form-control-label") }}
{{ form.title(class="form-control", value=section.title) }}
</div>
<div class="form-group">
{{ form.description.label(class="form-control-label") }}
{{ form.description(class="form-control", default=section.description) }}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-secondary shadow") }}
</div>
</form>
This can be done by just assigning the text to display beforehand (in the view, for instance).
Try edit your view (update_section) this way:
+ form.description.data = 'text you want to display'
And your template as follows:
- {{ form.description(class="form-control", default=section.description) }}
+ {{ form.description(class="form-control") }}
Mind you, there's an alternative way, which is to specify the placeholder attribute (but I guess is not what you want to do here).
Typically with WTForms (let's assume you're using Flask and Bootstrap here), you'll use the value attribute of the input to pre-populate a form field. Note that pre-populating a field is distinct from providing a 'placeholder', which is just an ephemeral hint. So usually we pre-populate like this:
<div class="form-group row">
<label for="form_subject" class="col-sm-2 col-form-label">Subject</label>
<div class="col-sm-7">
<input class="form-control" id="form_framework" name="form_framework"
value="{{ instruct.Subject }}">
</div>
</div>
With Flask and Bootstrap, the name attribute is required to pass the value back to the Controller upon submission, the value attribute is used to pre-populate the field from the object - in this case, our controller has passed in an object called instruct, which has an attribute Subject.
But you have to be aware that different kinds of inputs in WTForms have different attributes, and this is left as a fun challenge for the developer to figure out.
TextArea doesn't have a value attribute, so in order to pre-populate the field, you have to provide the value between the tags, like so (again, using Bootstrap here in case any of these tags are unfamiliar):
<div class="form-group row">
<label for="form_longish_text"
class="col-sm-2 col-form-label">Longish Text</label>
<div class="col-sm-7">
<textarea class="form-control" rows="3"
id="form_longish_text"
name="form_longish_text">{{ instruct.LongishText }}
</textarea>
</div>
</div>

Updating user profile - Django

I've created a template for updating account profiles using a Bootstrap snippet (from https://www.bootdey.com). With the django default format (like {{ form.as_p }}), updating accounts works (for example, when I modify the first name, it changes in the database). When I use the bootstrapp snippet, it doesn't update: it goes straight to 'homepage' without updating (as explained in views.py).
In forms.py
class EditAccountForm(UserChangeForm):
class Meta:
model = Account
fields = ('email','first_name','last_name')
In views.py
def EditProfile(request):
context= {}
if request.POST:
form = EditAccountForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
email = form.cleaned_data.get("email")
raw_password = form.cleaned_data.get("password1")
account = authenticate(email=email,password=raw_password)
return redirect('profile_page')
else:
context['edit_form'] = form
return redirect('homepage')
else:
form = EditAccountForm(instance=request.user)
context['edit_form'] = form
return render(request,'Account/edit_page.html',context)
the template: edit_profile.html (I only show the first_name part as example)
<form method = "POST" class="form" novalidate="">
{% csrf_token %}
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<div class="form-group">
<label>First name</label>
<input class="form-control" type="text" name="firstna" value={{ edit_form.first_name.value }}>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col d-flex justify-content-end">
<button class="btn btn-primary" type="submit">Save Changes</button>
PS: I've preferred to use those snippets instead of the Django style since I find them more attractive and offer more freedom.
Please check you are taking same value if you are changing the data in views like if you are using (name="firstna") in template so for First Name you have to take same in views.
Same question is asked here you can go and follow below link
[How to update user profile in Django

Using Django FormPreview the right way

My Goal
I have a django project with a form, and I want to display a preview page before the user submits.
The problem
I can display a preview page using a Django FormPreview, but not all form data is displayed properly. Specifically, if I have a field with choices, the string values of these choices aren't displayed. I'm also having problems applying template filters to date fields. The end result is that some data on the preview page is visible but other data is blank:
However, if I display the same data for posts that have actually been submitted, then everything displays properly:
My Code
models.py:
class Game(models.Model):
# Game Choices
FOOTBALL = 0
BASKETBALL = 1
TENNIS = 2
OTHER = 3
GAME_CHOICES = (
(FOOTBALL, 'Football'),
(BASKETBALL, 'Basketball'),
(TENNIS, 'Tennis'),
(OTHER, 'Other')
)
game_id = models.AutoField(primary_key=True)
location = models.CharField(max_length=200, verbose_name="Location")
game = models.IntegerField(choices=GAME_CHOICES, default=FOOTBALL)
game_date = models.DateField(verbose_name='Game Date')
forms.py
class GameForm(ModelForm):
class Meta:
model = Game
fields = (
'location',
'game',
'game_date'
)
I'm pretty sure that the problem is in my views.py: I'm not sure that I'm processing the POST request the right way to feed all data to the preview page.
views.py
def form_upload(request):
if request.method == 'GET':
form = GameForm()
else:
# A POST request: Handle Form Upload
form = GameForm(request.POST) # Bind data from request.POST into a GameForm
# If data is valid, proceeds to create a new game and redirect the user
if form.is_valid():
game = form.save()
return render(request, 'games/success.html', {})
return render(request, 'games/form_upload.html', {
'form': form,
})
preview.py
class GameFormPreview(FormPreview):
form_template = 'games/form_upload.html'
preview_template = 'games/preview.html'
def done(self, request, cleaned_data):
# Do something with the cleaned_data, then redirect
# to a "success" page.
return HttpResponseRedirect('/games/success')
form_upload.html
...
<form method="post">
{% csrf_token %}
<ul><li>{{ form.as_p }}</li></ul>
<button type="submit">Preview your post</button>
</form>
...
preview.html
{% load humanize %}
...
<h1>Preview your submission</h1>
<div>
<p>Location: {{ form.data.location }}</p>
<p>Game Date: {{ form.data.game_date|date:"l, F d, Y" }}</p>
<p>Game Type: {{ form.data.get_game_display }}</p>
</div>
<div>
<form action="{% url 'form_upload' %}" method="post">
{% csrf_token %}
{% for field in form %}
{{ field.as_hidden }}
{% endfor %}
<input type="hidden" name="{{ stage_field }}" value="2" />
<input type="hidden" name="{{ hash_field }}" value="{{ hash_value }}" />
<!-- Submit button -->
<button type="submit">Submit your post</button>
<!-- Go back button -->
<button type="submit">
<a href="{% url 'form_upload' %}"
onClick="history.go(-1);return false;" >
Go back and edit your post
</a>
</button>
</div>
</form>
</div>
...
Two issues
Essentially, I'm having these two issues:
String values for choices are not displayed. If I use the get_FOO_display() method in my preview.html template, it returns blank. However, if I use this in a page after the post has been submitted, it displays properly.
The humanize date filter doesn't work. If I apply a humanize filter ({{ form.data.game_date|date:"l, F d, Y" }}) in preview.html, it also displays blank. Again, this works for submitted posts.
My question essentially is: what's the right way to use the FormPreview here?
form.data does not have get_FOO_display attributes. When you access {{ form.data.get_game_display }} in the template, it fails silently and doesn't display anything.
The get_FOO_display are methods of the instance, so try this instead.
{{ form.instance.get_game_display }}
Wherever possible you should access data from form.cleaned_data (which is validated and 'cleaned') instead of form.data, which is the raw data submitted to the form.
The filters don't work with form.data.game_date because it's a raw string. They should work with form.cleaned_data.game_date, which has been converted to a python date object.
Finally, you haven't implemented anything in your done method, you've just copied the comment from the docs. You could create a new game using cleaned_data as follows:
def done(self, request, cleaned_data):
game = Game.objects.create(**cleaned_data)
return HttpResponseRedirect('/games/success')

Error passing argument to form in Django

I am new with django and I try update some data passing the id_provider from form1 to form2
The form2 have to display the data of the provider
I have an html page with a little form(form1):
Is a a simple input text where the user write a number.
the number is passed to other form as an argument.
My forms.py:
class ConfigForm(forms.ModelForm):
def __init__(self,idprov,*args,**kwargs):
super(ConfigForm,self).__init__(*args,**kwargs)
self.id_provider = idprov
class Meta:
model = Config
And my views.py:
#csrf_exempt
def configView(request):
prov = get_object_or_404(Config, id_proveedor=id)
if request.method == 'POST':
form = ConfigForm(request.post, instance=prov)
if form.is_valid():
form.save()
return HttpResponseRedirect('/monitor/')
else:
form = ConfigForm(Config.id_proveedor,instance=prov)
return render_to_response('config.html',{'form':form},RequestContext(request))
This is the form(form2) where I try to display the data:
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-4">
<form method='POST' action='' class='form'>
<div class="form-group">
{% csrf_token %}
{{ form.as_p }}
</div>
<button type='submit' class="btn btn-primary">Grabar</button>
</form>
</div>
</div>
</div>
{% endblock %}
I receive the error:
TypeError at /config/
id() takes exactly one argument (0 given)
I don't know if my error are in the method of the form where I try to update the data (form2) or I have some error in the view of the form.
I think I am not getting the value of the input text int the right way.
Any advice, link or snippet will be very helpful
Thanks in advance
id is a Python function and you didn't create it
>>> id('test')
35092128
Try
#csrf_exempt
def configView(request):
# Get your ID in another way for example this one
pk = request.POST.get('id', None)
if pk is None:
# Handle error
prov = get_object_or_404(Config, id_proveedor=pk)
# ^^
should works
BTW using csrf_exempt is generally not a good idea.

Categories

Resources