Creating a model from a form in django - python

I have a django project with a front end created using bootstrap which has about 20 fields :
<form id="form" class="form-vertical" action="/contact/" method="post">
{% csrf_token %}
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-sm-6 col-xs-12">
<form method="post">
<div class="form-group ">
<label class="control-label requiredField" for="subject">
Your Name (Primary Contact)
<span class="asteriskField">
*
</span>
</label>
<input class="form-control" id="subject" name="contact_name" type="text"/>
</div>
<div class="form-group ">
<label class="control-label requiredField" for="name">
Your Address (Primary Contact)
<span class="asteriskField">
*
</span>
In my app/views.py I have:
def contact(request):
django_query_dict = request.POST
message = django_query_dict.dict()
In retrospect, I probably should have used a model form (https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#django.forms.ModelForm) . But given that I have not, what would be the simplest approach to sanitize the data and load in into a db table?

The simplest approach is probably to switch it to a ModelForm - and it's definitely the best approach to take.
Using a ModelForm with bootstrap can be a little tricky at first, but take a look at django crispy forms, it makes it a lot easier. Once you do this once you'll never do it another way, it's great and will change your perspective on django forms.

Related

Adding a UserCreationForm to html in Django

I am creating a registration page for my website. I have a bootstrap/html template with a form (Down Bellow), and I want to replace the html form with a UserCreationForm that I have already made in my forms.py file. The tutorial says to replace the html input fields with my user creation fields, but then bootstrap cannot style them.
Forms.py:
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'first_name', 'last_name', 'password1', 'password2',]
Form parameters: (These are the fields from the UserCreationForm that I want to replace the HTML form fields with).
<form method = "POST" action="">
{% csrf_token %}
{{form.username.label}}
{{form.username}}
{{form.email.label}}
{{form.email}}
{{form.first_name.label}}
{{form.first_name}}
{{form.last_name.label}}
{{form.last_name}}
{{form.password1.label}}
{{form.password1}}
{{form.password2.label}}
{{form.password2}}
<input type="submit" name="Register">
</form>
I would advise you to look toward the following approach, if you can and willing to modify your UserCreationForm a bit:
class UserCreationForm(forms.Form):
# other fields as needed...
username = forms.CharField(
max_legth=100,
widget=forms.TextInput(attrs={'class': 'FOO_CLASS'}))
# Added a class to our input fields
So, now you can hook onto the specified class .form-control. In your CSS file and in HTML file in the question, this class supposedly introduces the styles.
Then (after your forms.py is modified) the template should look like this:
<div class="signup-form">
<form action="" method="post">
{% csrf_token %}
<h2>Sign Up</h2>
<p>Please fill in this form to create an account!</p>
<hr>
<form method = "POST" action="">
{% csrf_token %}
<div class="form-group">
{{form.username.label}}
{{form.username}}
</div>
<div class="form-group">
{{form.email.label}}
{{form.email}}
</div>
<div class="form-group">
{{form.first_name.label}}
{{form.first_name}}
</div>
<div class="form-group">
{{form.last_name.label}}
{{form.last_name}}
</div>
<div class="form-group">
{{form.password1.label}}
{{form.password1}}
</div>
<div class="form-group">
{{form.password2.label}}
{{form.password2}}
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-lg">Sign Up</button>
</div>
</div>
</form>
<div class="hint-text">Already have an account? Login here</div>
</div>
There are some other ideas based on using the ~ CSS selector and targeting the labels or inputs themselves. But this one is based on the Django's framework facilities.

Contained submit button validating other forms

I have two forms on my page, each with its own fields and submit button, but whenever I use any of them, they always check the overall page fields instead of just the form they're contained in...
The simulator.html has two forms, the first one is this:
<div class="forms">
<div class="form-1">
<form method="post" action="{{ url_for('core.simulator') }}">
<div class="container">
<div class="row g-3">
<div class="col-sm-3">
<label class="form-label"><b>Capital:</b></label>
<input type="text" class="form-control" name="capital_html" required>
</div>
<div class="col-sm-3">
<label class="form-label"><b>Price:</b></label>
<input type="text" class="form-control" name="price_html" required>
</div>
</div>
</div>
<br>
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
<button id="btn" type="submit" class="btn btn-info">Launch simulation!</button>
</div>
</form>
<br>
<p>Units to purchase: <b>{{simulation_units}}</b>
</div>
</div>
And the second one is this:
<h3> Screener</h3>
<div class="forms">
<div class="form-2">
<form method="post" action="{{ url_for('core.simulator') }}">
<div class="container">
<div class="row g-3">
<div class="col-sm-3">
<label class="form-label"><b>Ticker:</b></label>
<input type="text" class="form-control" name="ticker_symbol_html" placeholder="Enter Ticker Symbol" required>
</div>
</div>
</div>
<br>
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
<button id="btn" type="submit" class="btn btn-info">Launch!</button>
</div>
<p>Symbol <b>{{simulation_symbol}}.
</form>
</div>
</div>
The views.py file has the back-end code for each, the first one is this:
def capital_simulator():
if request.method == 'POST':
simulation_capital = request.form.get('capital_html', '')
simulation_price = request.form.get('price_html', '')
try:
simulation_units = math.floor(float(simulation_capital) / float(simulation_price))
except KeyError:
simulation_units == 0
return render_template('simulator.html',form1=form,capital_html=simulation_capital,price_html=simulation_price,simulation_units=simulation_units)
And the second form back-end script is this:
def screener():
if request.method == 'POST':
ticker_symbol = request.form.get('ticker_symbol_html', '')
return render_template('simulator.html',ticker_symbol=ticker_symbol_html,ticker_symbol=simulation_symbol)
I thought by specifically calling the mentioned fields and containing them into forms classes, I would avoid an overall validation, but right now I'm failing to make the submit button focus on their own forms. How can I fix this, please?
You have two forms. One is within the 'form-1' div. One is within the 'form-2' div. Each one has its own <form> and </form> tags, which means they are separate forms. The first form contains two <input> fields: one called capital_html, one called price_html, and a button called btn. The second form has one <input> field called ticker_symbol_html and a button called btn.
Let's say the user fills in the first two fields and clicks the first button. That's going to send a request to whatever the URL is in the <form> tag. In the data, it will send three things:
capital_html=xxx
price_html=yyy
btn=submit
That's it. That's all you get. You don't get any fields from the other form. If the user clicks the other form, all you will get is
ticker_symbol_html=xxx
btn=submit
The problem, as you can see, is there's no easy way for you to tell which form was submitted. If you have to use the same URL for both, the usual way to solve this is to add a hidden field that gets sent with the data, like:
<input type=hidden name="ident" text="form1">
and in the second one:
<input type=hidden name="ident" text="form2">
Now, your handler can say
if request.form.get("ident") == "form1":
# Go handle first form.
else:
# Go handle second form.

Custom Bootstrap Checkbox in Jinga2/Flask

I have the following WTF form
class config_reports(FlaskForm):
test2use = SelectMultipleField('Choose Test(s):', [DataRequired()], choices=[('', '')])
display_cuts = BooleanField('Display Proficiency Cuts?', default = True)
submit = SubmitField('Run Report')
and now I'm trying to fancy up my checkbox to use the example found here, https://getbootstrap.com/docs/4.0/components/forms/, which uses this code
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<label class="custom-control-label" for="customCheck1">Check this custom checkbox</label>
</div>
Within my jinga2 template file, I'm trying the following. Some of the style is applied, but my checkbox isn't clickable. Any advice on how to properly apply the styling here?
<div class = 'col'>
<div class="formwrapper">
<form method="POST" action="{{url_for('config_tools.config_reader')}}">
<div class="form-field">
{{form2.test2use.label}}
{{form2.test2use (class="form-control", required=False)}} <br>
<div class="custom-control custom-checkbox">
{{form2.display_cuts.label(class="custom-control-label")}}
{{form2.display_cuts (class="custom-control-input") }}<br>
</div>
{{form2.submit(class = "btn btn-primary")}} <br><br>
</div>
</form>
</div>
</div>

django create template with multiple input field

I am trying to create a template which would take input items like item, quantity and unit price and render a pdf report of it with total price. Also i want the input to be on tabular form and add the lines dynamically by clicking + icon or something.
My folder structure is:
Project
|__ app
|__ template
|__ app.html
I am extending app.html from base.html which inherits bootstrap. Tried the below code but can't figure out how to do it.
{% extends 'base.html' %}
{% block head %}
{% endblock %}
{% block body %}
<div class="panel panel-default">
<div class="panel-body">
<div id="all_fields">
</div>
<div class="col-sm-3 nopadding">
<div class="form-group">
<input type="text" class="form-control" id="Itemquantity" name="Itemquantity[]" value="" placeholder="Item Quantity">
</div>
</div>
<div class="col-sm-3 nopadding">
<div class="form-group">
<input type="number" class="form-control" id="Quantity" name="Quantity[]" value="" placeholder="Quantity">
</div>
</div>
<div class="col-sm-3 nopadding">
<div class="form-group">
<input type="number" class="form-control" id="Unitprice" name="Unitprice[]" value="" placeholder="Unit Price">
</div>
</div>
<div class="col-sm-3 nopadding">
<div class="form-group">
<div class="input-group">
<div class="input-group-btn">
<button class="btn btn-success" type="button" onclick="all_fields();"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> </button>
</div>
</div>
</div>
</div>
<div class="clear"></div>
</div>
<div class="panel-footer"><small>Press <span class="glyphicon glyphicon-plus gs"></span> to add another form field :)</small>, <small>Press <span class="glyphicon glyphicon-minus gs"></span> to remove form field :)</small></div>
</div>
{% endblock %}
If you want dinamic you should go to Javascript instead of Django, because Django is server side, django only will process your data after new request... so you can do it from scratch setting up one ajax to connect to your django while User is interacting with your page and create this new inputs based in something from server... or your inputs will be just generated in your HTML and only after sended to your backend will be hanlded by django (you will have to create your own logic)
Probabily there is any lib that already do that for your.
I do recommend to setup your javascript to dinamic create ids and new inputs, setup all inside one form tag, send this form to your backend, capture it in your post request and handle if... if you receive 5 inputs so it means there i 5 new itens...

HTML form is not taking in a date value on desktop, but is on mobile

I'm creating a form. I've created a mobile block that renders on mobile and a desktop block that renders on desktop. There are several fields in this form, and it's working fine with the exception of the date field where I want someone to put in a date. On the mobile block, the date field is taking in a value perfectly. On the desktop block, it is not taking in any value. I end up getting this error when rendering the desktop version:
ValueError: time data '' does not match format '%Y-%m-%d'
The HTML looks like this (I've eliminated a big chunk of the fields in the form for simplicity, let me know if you need to see more of the HTML):
<form method="POST">
<div class="mobile-only">
<div class="form-group row">
<div class="col-12 col-md-2 col-lg-4">
<label for="start-date" class="col-form-label">
<h4>Start Date: <sup class="required">(required)</sup></h4>
</label>
</div>
<div class="col-12 col-md-10 col-lg-4">
<input type ="date" maxlength="10" class="form-control" id="start-date" name="start-date" placeholder="MM/DD/YYYY">
</div>
</div>
<div class="row">
<div class="col-3 col-md-1">
<button class="green-button link-text" type="submit" id="submit" type="submit">Save</button>
</div>
<div class="col-3 col-md-1">
<button class="green-button">Cancel</button>
</div>
</div>
</div>
The above code works fine on mobile, below is what is rendered on desktop, and gives me the above referenced error:
<div class="desktop-only">
<div class="form-group row">
<div class="col-lg-1">
<label for="start-date" class="col-form-label">
<h4>Start Date: <sup class="required">(required)</sup></h4>
</label>
</div>
<div class="col-lg-3">
<input type ="date" maxlength="10" class="form-control" id="start-date" name="start-date" placeholder="MM/DD/YYYY">
</div>
</div>
<div class="row">
<div class="col-3 col-md-1">
<button class="green-button link-text" type="submit" id="submit" type="submit">Save</button>
</div>
<div class="col-3 col-md-1">
<button class="green-button">Cancel</button>
</div>
</div>
</div>
</form>
Also, in case it's relevant, I'm using Bootstrap 4 and the backend is a Flask App with Python. Any idea what the issue is?
your placeholder indicates to user this format:
placeholder="MM/DD/YYYY"
but then elsewhere in the code you are expecting:
format '%Y-%m-%d'
which is your error, if you trying to upload to database you should use YYYY-MM-DD as this is international standard, then in your front end convert to MM/DD/YYYY.
If you asking for input of MM/DD/YYYY, you need to convert it to YYYY-DD-MM

Categories