where `form.as_p`in django templates come from? - python

I have a generic view and a form template.
my view is:
class BlogCreateView(CreateView):
model = Post
template_name = "post_new.html"
fields = "__all__"
and my form template is:
{% extends "base.html" %}
{% block content %}
<h1>New Post</h1>
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
{% endblock content %}
now my question is about form.as_p or specifically form.
Where did that come from?
help me please. thanks a lot

.as_p() [Django-doc] is a method on a Form. It produces a SafeText object [Django-doc] that contains HTML code to be included in the template.
The fact that it is SafeText is important, since the Django render engine will otherwise "escape" it: without using SafeText, it would replace < with <; > with >, etc. Unless of course you wrap it in a SafeText object yourself, for example through the |safe template filter [Django-doc].
We can for example define a form like in the documentation:
class OptionalPersonForm(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
nick_name = forms.CharField(required=False)
If we then construct a form object, we can call the .as_p() method:
>>> OptionalPersonForm().as_p()
'<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" required id="id_first_name"></p>\n<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" required id="id_last_name"></p>\n<p><label for="id_nick_name">Nick name:</label> <input type="text" name="nick_name" id="id_nick_name"></p>'
>>> type(OptionalPersonForm().as_p())
<class 'django.utils.safestring.SafeText'>
Django forms have three popular rendering methods: .as_p, .as_table() [Django-doc] and .as_ul() [Django-doc]. The difference is that these render the HTML slightly differently: as paragraphs, a table or unordered HTML list.

Related

how to pass data from multiple checkboxes created in django template using for loop to views.py without using forms

This is my html form in which i have a text field for a word and i am running a for loop which created checkbox for the list of document a user has and displays it as form.
<body>
<form id="form" method = "POST">
{% csrf_token %}
<fieldset id="User">
<legend>Your details:</legend>
<p><label for="word">Enter your word</label>
<input type="text" id="word" name="word">
</p>
{% for doc in docs %}
<p>
<input type="checkbox" id="{{ doc.document_id }}" name="docid" value="{{ doc.path }}">
<label for="{{ doc.document_id }}"> {{ doc.document_name }} </label><br>
</p>
{% endfor%}
<input type="submit" value="Submit" >
</fieldset>
</form>
</body>
In views.py I have below method which loads this html page
def client_home(request):
client_pr = Client_Profile.objects.get(user_id=request.user)
events = Event.objects.filter(client_id=client_pr.pk)
name = request.POST.get('word')
id = request.POST.get('docid')
print(name)
print(id)
docs = []
for eve in events:
docs = Document.objects.filter(event_id=eve)
context = {'events': events, 'docs': docs}
return render(request, 'Elasticsearch/form.html', context)
My question is as i am using a for loop create checkbox field based on number of documents a user has and when I try to print them in my Views.py file it is only priniting last document id whose checkbox is created and not all the documents.
From seeing your view, I assume you want to pass a list of documents specific to a user to your template. Currently you are overwriting docs in every iteration of your for loop.
Change
docs = Document.objects.filter(event_id=eve)
to
docs += Document.objects.filter(event_id=eve)
You need to use getlist to get all the selected values from your checkbox, so:
id_list = request.POST.getlist('docid')
Otherwise using get will only return the last one.

Pre-Populate an edit form with WTForms and Flask

I am able to add a new entry to my database using WTForms and Flask and I can edit too, the problem is that I need to display the already existing information in the database in an edit form.
I have the following code:
A Class For the Edit Post Form
class editPostForm(Form):
postTitle = TextField('postTitle', validators.Required()])
postSubtitle = TextField('postSubtitle', validators.Required()])
A Route for the Edit Post Template
#app.route('/editpost/<postId>', methods = ['GET','POST'])
def editpost_page(postId):
try:
form = editPostForm(form)
if request.method == "POST" and form.validate():
postTitle = form.postTitle.data
postSubtitle = form.postSubtitle.data
c, conn = connection()
query = c.execute("SELECT * FROM posts WHERE post_id = (%s)",
[noinjection(postId)])
c.execute("UPDATE posts SET post_title=%s, post_subtitle=%s WHERE post_id = %s",
[
noinjection(postTitle),
noinjection(postSubtitle),
noinjection(postId)
])
conn.commit()
flash("Post Edited", 'success')
c.close()
conn.close()
gc.collect()
return redirect(url_for('posts'))
return render_template("editpost.html", form = form, POST_ID = postId)
except Exception as e:
return(str(e))
The Edit Post Template {jinja}
{% extends "header.html" %}
{% block body %}
<body>
<div class="container-fluid">
<br />
<h4>Edit Post</h4>
<br />
{% from "_formhelpers.html" import render_field %}
<form action="/editpost/{{ POST_ID }}" class="form-horizontal" method="post">
{% from "_formhelpers.html" import render_field %}
<form action="/editpost/" method="post">
<div class="form-group">
<label for="postTitle">Post Title</label>
<input type="text" class="form-control" id="postTitle" name="postTitle" placeholder="Post Title" value="{{request.form.postTitle}}">
</div>
<div class="form-group">
<label for="postSubtitle">Post Subtitle</label>
<input type="text" class="form-control" id="postSubtitle" name="postSubtitle" placeholder="Post Subtitle" value="{{request.form.postSubtitle}}">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
{% if error %}
<p class="error"><strong>Error: </strong>{{error}}</p>
{% endif %}
</form>
{% if error %}
<p class="error"><strong>Error: </strong>{{error}}</p>
{% endif %}
</div>
</body>
{% endblock %}
With the following code, I am getting a selected post to update in the database, but the editpost template is not showing the values which are already in the database and all the fields are blank.
How can I pre-populate the form before editing?
You can populate each field separately like this:
form = editPostForm(form)
form.postTitle.data = postTitle_from_database
form.postSubtitle.data = postSubtitle_from_database
or you can populate your form fields from a given object using process method:
process(formdata=None, obj=None, **kwargs)
Take form, object data, and keyword arg input and have the fields
process them.
Parameters:
formdata – Used to pass data coming from the enduser, usually request.POST or equivalent.
obj – If formdata has no data for a field, the form will try to get it from the passed object.
**kwargs – If neither formdata or obj contains a value for a field, the form will assign the value of a matching keyword argument
to the field, if provided.
Since BaseForm does not take its data at instantiation, you must call
this to provide form data to the enclosed fields. Accessing the
field’s data before calling process is not recommended.
I was able to pre-populate HTML input and textarea fields from a SQL database with Python and Jinja as follows:
1. Store relevant data from database in a variable:
name = db.execute("""SELECT name FROM users WHERE id = :id""", id=session["user_id"])
about = db.execute("""SELECT about FROM users WHERE id = :id""", id=session["user_id"])
2. Render template (with render_template function) and pass in the relevant variables:
return render_template("edit.html", name = name, about = about)
3. Pass variables via jinja to html input and textarea elements. Index into the object that has been passed as follows:
For an input tag use the value attribute as below:
<input type="text" class="form-control" name="name" value="{{ name[0]["name"] }}">
For a textarea element:
<textarea class="form-control" name="about">{{ about[0]["about"] }}</textarea>

Django how to retrieve post data from Modelform and static formfields mixed together

I'm using a Django Modelform mixed with static form fields to generate a HTML form like so:
Models.py:
class example(models.Model):
value_1 = models.PositiveIntegerField()
value_2 = models.PositiveIntegerField(unique=True)
value_3 = models.PositiveIntegerField()
value_4 = models.CharField(max_length=600)
value_5 = models.CharField(max_length=600)
label_1 = models.CharField(max_length=3)
label_2 = models.CharField(max_length=3)
label_3 = models.CharField(max_length=3)
def __str__(self):
return self.name
class ExampleForm(ModelForm):
class Meta:
model = example
fields = '__all__'
exclude = ['label_1','label_2','label_3']
Template (HTML):
<form method="post" action="" enctype="multipart/form-data">
<!-- Start static form fields -->
<input type="checkbox" checked="checked" name ="label_1" value="blabla">
<input type="checkbox" checked="checked" name ="label_2" value="blabla">
<input type="checkbox" checked="checked" name ="label_3" value="blabla">
<!-- End static form fields -->
<!-- Start Modelform fields -->
{% for field in form %}
<div class="form-group form-group-default required">
{{ field.label_tag }}
{{ field|addcss:'form-control' }}
<span class="text-danger">{{ field.errors }}</span>
</div>
{% empty %}
<h3 class="text-warning">Database lookup failed.</h3>
{% endfor %}
<!-- End Modelform fields -->
<button class="btn btn-complete btn-lg" type="submit"><i class="fa fa-save"></i></button>
</form>
The HTML form shows perfectly with the static and the dynamic form fields. I can request the form values and see them like so:
form = ExampleForm(request.POST)
return HttpResponse(form)
Problem:
When I use the above technique to request POST data I only receive the post data from Modelform (dynamic fields) and not the data from the static fields!
I found out I can request the posted values from the static fields this way:
label_1 = request.POST.get("label_1")
return HttpResponse(label_1)
Above code will give me the value of the posted static checkbox. However, now I have to collect all the static fields and I want to catch all posted data at once and than handle it further.
Now my question, how is it possible that I don't get all the post values when I request them in Django? How do I make 1 variable with all the post data in it including modelform values and static form fields?
Hope my question is clear, thanks guys! :)
I believe you might want to take a close look at this line:
exclude = ['label_1','label_2','label_3']

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')

django poplulate html form

How to set the html form fields without using django-forms.
If you do not wish to use django.forms, but get data from a model and display it into a html form, you could do something like this:
views.py
from django.shortcuts import render_to_response, redirect
from myApp.models import MyModel
def editForm(request, model_pk):
model = MyModel.objects.get(pk=model_pk)
return render_to_response('formUpdate.html',{ 'model' : model })
def updateForm(request, model_pk):
model = MyModel.objects.get(pk=model_pk)
model.firstname = request.POST['firstname']
model.lastname = request.POST['lastname']
model.save()
return redirect('home', message='your name has been updated')
template - formUpdate.html
{% extends "base.html" %}
{% block content %}
<form action="/updateForm/{{ model.id }}/" method="post">
First name: <input type="text" name="firstname" value="{{ model.firstname }}" /><br />
Last name: <input type="text" name="lastname" value="{{ model.lastname }}" /><br />
<input type="submit" value="submit" />
</form>
{% end block %}
models.py
from django.db import models
class MyModel(models.Model):
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
urls.py
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^$', 'views.home', name="home"),
(r'^editForm/(?P<model_pk>\d+)/$', 'views.editForm'),
(r'^updateForm/(?P<model_pk>\d+)/$', 'views.updateForm'),
)
This is very similar to how forms are processed in PHP or similar, the model is passed into the template where the existing values are rendered. The id or pk (primary key) of the model is passed to the view via the URL and then updated values then returned to the storing view in the POST data where they can be retrieved and the updated values stored in the database.
One of the beauties of Django is how it balances speed of development with plugability - pretty much any of it's parts can be replaced or altered.
Having said this, is there a reason why you don't want to use django.forms? To my understanding a form simply performs most of the hard work in the example above for you, this is what django.forms are for. They also have other features, to help prevent malicious access of your web app, for example, OOTB. It is fairly easy to create ajax helper methods to retrieve and update them also.
You can do that as you would create a normal form in html. Just be careful to place the {% csrf_token %}. And the name of the input in the form, as they will be used in the view.
Eg:
<form method="post" action="#the url for the view">
{% csrf_token %}
...
...
<!-- fields that you want Eg: -->
<label for="username">User name:</label>
<input type="text" name="username" id="username" />
...
...
<input type="submit" value="Submit" />
</form>
Hope this helped.

Categories

Resources