Django2 forms nothing happend when submit post article - forms

I have forms to Post Article in my blog Django2. When I run django server there is no error, but when I Post and submit Article in my frontEnd apps nothing happens and doesn't save any data.
Any help on this would be highly appreciated!
Template HTML
<div class="create-article">
<h2>Create an Awesome New Articles</h2>
<form class="site-form" action="{% url 'articles:create' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<input type="submit" value="Create">
</form>
</div>
forms.py
from django import forms
from . import models
class CreateArticle(forms.ModelForm):
class Meta:
model = models.Article
fields = ['title', 'body', 'slug', 'thumb']
views.py
def article_create(request):
if request.method == 'POST':
form = forms.CreateArticle(request.POST, request.FILES)
if form.is_valid():
# save article to db
instance = form.save(commit=False)
instance.author = request.user
instance.save
return redirect('articles:list')
else:
form = forms.CreateArticle()
return render(request, 'articles/article_create.html', {'form': form})
urls.py
from django.urls import path
from . import views
app_name = 'articles'
urlpatterns = [
path('', views.article_list, name="list"),
path('create/', views.article_create, name="create"),
path('<slug>/', views.article_detail, name="detail"),
]
Thanks.

It starts here: instance = form.save(commit=False), where you are not commiting the save.
Further down you have instance.save as if you were setting a model field, but with not value given to it.
Make that line instance.save() instead.

Related

Flask-WTF not validating with FieldList subforms

I am trying to get a test form that includes subforms to work but the form does not validate on submission. The form itself is submitting a recipe with ingredients as its subforms using FieldList(). I have also made sure to include hidden_tag() in the HTML.
Forms:
class IngredientsForm(FlaskForm):
ingredient_name = StringField("Ingredient", validators=[DataRequired()])
class RecipeForm(FlaskForm):
recipe_name = StringField("Recipe name", validators=[DataRequired()])
ingredients = FieldList(FormField(IngredientsForm), min_entries=2, max_entries=5)
submit = SubmitField("Submit")
Views:
#app.route("/", methods=["GET", "POST"])
def index():
form = RecipeForm()
return render_template("index.html", form=form)
#app.route("/submit", methods=["POST"])
def submit():
form = RecipeForm()
print(f"ERRORS: {form.errors}")
print(f"DATA: {form.data}")
if form.validate_on_submit():
print("Validated!")
print(form.recipe_name)
for ingredient in form.ingredients.data:
print(ingredient)
return redirect("/")
else:
print("Form not validated")
return render_template("index.html", form=form)
HTML:
<h1>Enter recipe:</h1>
<form action="/submit" method="POST">
{{ form.hidden_tag() }}
<p>
{{ form.recipe_name.label }} <br>
{{ form.recipe_name() }}
</p>
<p>
{{ form.ingredients.label }} <br>
{% for ing in form.ingredients %}
{{ ing.ingredient_name.label }}
{{ ing.ingredient_name() }}
<br>
{% endfor %}
</p>
<p>
{{ form.submit() }}
</p>
</form>
Output:
ERRORS: {}
DATA: {'recipe_name': 'butterbread', 'ingredients': [{'ingredient_name': 'butter', 'csrf_token': None}, {'ingredient_name': 'bread', 'csrf_token': None}], 'submit': True, 'csrf_token': 'Ijg1NmVjZjIwODY3MTJkNDNkMTFiNDQ2YzdiNzYyYzYyNmUzNGUzMWMi.YtaF7g.WRn25PWYMFplr_KV7RoZq1uLgrI'}
Form not validated
127.0.0.1 - - [19/Jul/2022 03:22:44] "POST /submit HTTP/1.1" 200 -
So far, no errors show up but it looks like in the data that since each subform has None as its csrf_token, maybe that's messing up the validation? I've tried getting this to validate for a while but to no avail.
You can disable csrf protection for the FlaskForm by setting the flag to false within the class Meta. CSRF protection is not necessary for nested forms as long as the parent form takes over this task.
class IngredientsForm(FlaskForm):
class Meta:
csrf = False
ingredient_name = StringField("Ingredient", validators=[DataRequired()])
class RecipeForm(FlaskForm):
recipe_name = StringField("Recipe name", validators=[DataRequired()])
ingredients = FieldList(FormField(IngredientsForm), min_entries=2, max_entries=5)
submit = SubmitField("Submit")
An alternative is to inherit from Form.
Figured it out. The problem is that the subform IngredientsForm inherits from FlaskForm which is a subclass that's csrf secure, and was the reason preventing validation. You don't need this as you have already the token in the main form.
Instead, have it inherit from wtforms.Form which doesn't have that. Another way is to disable csrf during init, but the previous method is preferred.

django form to upload file returns error as form not valid

I am developing an app in Django.
My users are allowed to save data by compiling a form like this
Tool:
acronym:
definition:
defined by the following function, in forms.py:
class tool_form(forms.ModelForm):
class Meta:
model=tool
fields=["Tool", "Acronym", "Definition"]
That saves the data into a model like this:
class tool(models.Model):
Tool = models.CharField(max_length=256, blank=True, null=True)
Acronym = models.CharField(max_length=25, blank=True, null=True)
Definition = models.TextField(blank=True, null=True)
The view function allowing this, is:
def add_tool(request):
if request.method=='POST':
form = tool_form(request.POST or None)
if form.is_valid():
form.save()
messages.success(request, ("Submit succeed!"))
return redirect('adding_tools')
else:
messages.error(request, ('ERROR: submit failed'))
return render(request, 'adding_tools.html', {})
else:
return render(request, 'adding_tools.html', {})
Now I want my users to be able to copile many times of the same form, all at once.
In order to achieve this, I am allowing my users to upload a file copiled with the data to insert.
So I am allowing my users to download a template xlsx file with colums with given name
Column 1 name (cell A1): Tool
Column 2 name (cell B1): acronym
Column 3 name (cell C1): definition
To compile it, inserting many records, and then to upload it back.
So I want my code to save this data into the same model declared before (tool)
I am trying to achieve this by:
in template add_tool_sheet.html:
<form class="container" method="POST" enctype="multipart/form-data" >
{% csrf_token %}
<div class="file-upload-wrapper" id="input-file-now">
<small id="inputHelp" class="form-text text-muted">Select file to upload.</small>
<input type="file" name="uploaded_file" id="input-file-now" data-max-file-size="5M" class="file-upload">
<br><br>
<div class="form-group">
<input name="Date" type="hidden" class="form-control" id="date_to_turn_into_toda">
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</div>
</form>
in forms.py:
class tool_file_form(forms.ModelForm):
class Meta:
model=tool_file
fields=["Tool_file", "Date"]
In models.py
class tool_file(models.Model):
Tool_file = models.FileField(upload_to='uploaded_sheets/', blank=False, null=False)
Date = models.DateField(blank=False, null=False, default=timezone.now().date() )
class Meta:
ordering = ['Date', 'Tool_file']
def clean(self):
if not (self.Tool_file or self.Date):
raise ValidationError("something went wrong")
def __str__(self):
return "%s ----- [%s]" % (self.Tool_file, self.Date)
in views.py:
def add_tool_sheet(request):
if request.method=='POST':
form = tool_file_form(request.POST, request.FILES)
if form.is_valid():
form.save()
messages.success(request, ("upload succeeded"))
return redirect('add_tool_sheet')
else:
messages.error(request, ('ERROR n1'))
return render(request, 'add_tool_sheet.html', {})
else:
return render(request, 'add_tool_sheet.html', {})
When I try to add new objects in the model tool_file from admin section, it works.
But when I try to add new objects from the user interface (template add_tool_sheet.html), it returns
ERROR n1
as message, and my console returns
GET /admin/ HTTP/1.1" 200 7381
Why?
Please note:
The upload from admin section works, the upload from user interface does not.
SOLVED
In template I put
name="uploaded_file"
but in order to match with the information in forms.py and model.py, it has to be:
name="Tool_file"
Now it works!

web.py markdown global name 'markdown' is not defined

Im trying to use markdown together with Templetor in web.py but I can't figure out what Im missing
Documentation is here http://webpy.org/docs/0.3/templetor#builtins
import markdown
t_globals = {
'datestr': web.datestr,
'markdown': markdown.markdown
}
render = web.template.render(globals=t_globals)
class Blog:
def GET(self, post_slug):
""" Render single post """
post = BlogPost.get(BlogPost.slug == post_slug)
render = web.template.render(base="layout")
return render.post({
"blogpost_title": post.title,
"blogpost_content": post.content,
"blogpost_teaser": post.teaser
})
here is how I try to use markdown inside the post.html template
$def with (values)
$var title: $values['blogpost_title']
<article class="post">
<div class="post-meta">
<h1 class="post-title">$values['blogpost_title']</h1>
</div>
<section class="post-content">
<a name="topofpage"></a>
$:markdown(values['blogpost_content'])
</section>
But Im getting this exception
type 'exceptions.NameError' at
/blog/he-ll-want-to-use-your-yacht-and-i-don-t-want-this-thing-smelling-like-fish/
global name 'markdown' is not defined
You're re-initializing render, once in global scope setting globals and once within Blog.GET setting base. Do it only once!

How can I keep field data after validating false in flask wtform?

I am new to flask and don't know how to keep field data after a failing post.
Thanks for your helps ^_^.
Example:
views.py:
#app.route('/', methods=['GET', 'POST', ])
def index():
form = MyForm()
if request.method == 'GET':
return render_template('index.html', form=form)
elif request.method == 'POST':
if form.validate_on_submit():
# blabla...
return redirect('/')
else: # validate false
# how to keep field data in new page?
return render_template('index.html', form=form) # it failed
It didn't work because I implement my own html form fields, in order to solve the problem, I should write template like this:
index.html:
<form ...>
{{ form.fieldname(class_='form-control', placeholder='hint') }}
</form>
Instead of inheriting your Form class from wtforms.Form, inherit it from flask_wtf.FlaskForm
For example, Replace this
from wtforms import Form
class RegistrationForm(Form):
#fields...
With this
from flask_wtf import FlaskForm
class RegistrationForm(FlaskForm):
#fields...

Symfony2 Forms: is it possible to bind a form in an "unconventional way"?

Imagine this scenario: in our company there is an employee that "play" around graphic,css,html and so on.
Our new project will born under symfony2 so we're trying some silly - but "real" - stuff (like authentication from db, submit data from a form and persist it to db and so on..)
The problem
As far i know, learnt from symfony2 "book" that i found on the site (you can find it here), there is an "automated" way for creating and rendering forms:
1) Build the form up into a controller in this way
$form = $this->createFormBuilder($task)
->add('task','text'),
->add('dueDate','date'),
->getForm();
return $this->render('pathToBundle:Controller:templateTwig',
array('form'=>$form->createview());
2) Into templateTwig render the template
{{ form_widget(form) }} // or single rows method
3) Into a controller (the same that have a route where you can submit data), take back submitted information
if($rquest->getMethod()=='POST'){
$form->bindRequest($request);
/* and so on */
}
Return to scenario
Our graphic employee don't want to access controllers, write php and other stuff like those. So he'll write a twig template with a "unconventional" (from symfony2 point of view, but conventional from HTML point of view) method:
/* into twig template */
<form action="{{ path('SestanteUserBundle_homepage') }}" method="post" name="userForm">
<div>
USERNAME: <input type="text" name="user_name" value="{{ user.username}}"/>
</div>
<div>
EMAIL: <input type="text" name="user_mail" value="{{ user.email }}"/>
</div>
<input type="hidden" name="user_id" value="{{ id }}" />
<input type="submit" value="modifica i dati">
</form>
Now, if into the controller that handle the submission of data we do something like that
public function indexAction(Request $request)
{
if($request->getMethod() == 'POST'){ // sono arrivato per via di un submit, quindi devo modificare i dati prima di farli vedere a video
$defaultData = array('message'=>'ho visto questa cosa in esempio, ma non capisco se posso farne a meno');
$form = $this->createFormBuilder($defaultData)
->add('user_name','text')
->add('user_mail','email')
->add('user_id','integer')
->getForm();
$form->bindRequest($request); //bindo la form ad una request
$data = $form->getData(); //mi aspetto un'array chiave=>valore
/* .... */
We expected that $data will contain an array with key,value from the submitted form.
We found that it isn't true. After googling for a while and try with other "bad" ideas, we're frozen into that.
So, if you have a "graphic office" that can't handle directly php code, how can we interface from form(s) to controller(s) ?
UPDATE
It seems that Symfony2 use a different convention for form's field name and lookup once you've submitted that.
In particular, if my form's name is addUser and a field is named userName, the field's name will be AddUser[username] so maybe it have a "dynamic" lookup method that will extract form's name, field's name, concat them and lookup for values.
Is it possible?
You can force Symfony2 to set the name of a form field, though I don't suggest it: $formBuilder->add('dummyfield', 'text', array( 'attr' => array('name' => 'yournamehere') ) );
Alternatively (also a bad idea), you can do this, which won't even let you use the form API: $this->getRequest()->get('whatever_the_field_name_is');
OR you can hackily add elements to the request based on the Sf2 generated names before binding it (copying the values that exist).
OR you can make use of the bind method of the form component (instead of bindRequest) as documented here.
But seriously...just use the formbuilder api. Your life will be easier, and isn't that what a framework is for? :)
Symfony 2 is based on twig as templating language. Let him use it :
{{ form_label(form.field) }}
will generate something like this :
<label for="field">field</label>
You can use all the available functions in order to render the form :
{{ form_label() }}
{{ form_widget() }}
{{ form_errors() }}
If you want to customize what is rendered by those functions, you can override twig templates as defined in the Symfony2 documentation.
Otherwise if you really want to something ugly, you can go for this kind of syntax :
{{ myform.vars.value.myField }}