I have a simple form with a single text input field which is not getting displayed in the template.Only the form's submit button is displayed.
The template:
<form method='POST' action="example">
{{ form.as_p }}
<input type="submit" value="submit"/>
</form>
The form:
class sampleform(forms.Form):
data = forms.CharField(label = u'Add a text:')
The view:
def example(request):
if request.method == 'POST':
form = sampleform(request.POST)
if form.is_valid:
return HttpResponseRedirect('/register/success/')
else:
form = sampleform()
variables = RequestContext(request,{'form':form})
return render_to_response('stream.html',variables)
I also get such a bug, tried to change forms, at first I had a form.ModelForms, Then tried in new forms.Form, but it was still not out in template.
I win my bug when in View change Context {'form':form} to {'formZZZ':form} and template to {{ formZZZ }}, and 2 forms still work (Forms and ModelForms).
Question was 4 years ago, but hope it help for other, who take this result. Python 3.5, virtualenv on Win10, Django 1.11.1 Sorry for bad English.
Related
Most of the info I find online is for multiple checkboxes. I just want 1.
I have:
class CategoryForm(FlaskForm):
category = StringField('category',validators=[DataRequired()])
checkbox = BooleanField('Private?')
#app.route('/category/<categoryid>',methods=('GET','POST'))
def category(categoryid):
category = Category.query.get(categoryid)
if request.method == 'POST':
if request.form.get('category'):
category.name = request.form['category']
category.private = request.form['private']
db.session.add(category)
db.session.commit()
return redirect(url_for('index'))
c_form = CategoryForm()
c_form.category.data = category.name
return render_template('category.html',form =c_form,category=category)
And my 'category' template:
<form method="post">
{{ form.hidden_tag() }}
{{ form.checkbox }}
<button type="submit">Go!</button>
</form>
right now my browser renders this:
<peewee.BooleanField object at 0x105122ad0> Go!
Obviously I would like it to render the checkbox instead. How can I do this? Do I need a widget ?
I'm having the impression that you're using the fields from peewee as the fields in your form, that isn't going to work. The most likely case is that you're importing both and one import is overwriting the other.
If you need to have both the model and the form in the same file, use aliases.
from peewee import BooleanField as PeeBool
from wtforms import BooleanField as WTBool
I want to use more than one forms in the same page from the same model.
Ok, lets take it easy.
I have Social modules that have 3 attributes (network, url and image) charfield.
I've added 4 values in Social database (Facebbok, Twitter, Youtube, Pinterest)
In the settings view (settings.html) i want to have all 4 forms (for Facebook, Twitter etc.) to edit them.
Something like that:
Facebook: text input (that contains the current facebook url)
Youtube: text input (that contains the current youtube url)
etc.
So when i go to settings.html i can change, update social url for all networks.
I have something like this for General Settings module (that have 3 fields, Title, Slug, Description and 1 attribute cuz the website have 1 title, 1 slug and 1 description). For this one is pretty simple i can use get_object_or_404 because Settings module have just 1 value and i can select it.. but the problem is Social Module have more values and i want to have on my page all forms from them so i can edit how ever i want.
views.py
def settings(request):
sidebar_items = Sidebar.objects.order_by('position')
social_items = Social.objects.order_by('network')
settings = get_object_or_404(Settings, pk = 1)
if request.method == "POST":
form_settings = SettingsForm(request.POST, instance = settings)
if form_settings.is_valid():
settings = form_settings.save(commit = False)
settings.save()
return HttpResponseRedirect('/dashboard/settings')
else:
form_settings = SettingsForm(instance = settings)
context = {'sidebar_items' : sidebar_items, 'form_settings' : form_settings, 'social_items' : social_items}
return render(request, 'dashboard/settings.html', context)
Django doesn't care how many forms you want to initialize in your view. If they're for the same model, you can use a formset. Otherwise, you can initialize and create objects however you want.
Example:
def your_view(request):
social_items = Social.objects.order_by('network')
forms = []
for index, social_item in enumerate(social_items):
forms.append(SocialForm(request.POST or None, instance=social_item,
prefix="form_{}".format(index)))
if request.method == 'POST':
for form in forms:
if form.is_valid():
form.save()
# do whatever next
return render(request, 'some-template.html', {'forms': forms})
You don't need three separate form tags in your template. You can submit all of the data in one post. Django will try to hydrate an instance of each model from the POST data, and return any errors if that fails.
In your template, you'll need to iterate over the form instances:
# some-template.html
<form action="." method="post" enctype="x-www-form-urlencoded">
{% for form in forms %}
<ol>
<li>
{{ form.network }}
{{ form.network.errors }}
</li>
<li>
{{ form.url }}
{{ form.url.errors }}
</li>
<li>
{{ form.image }}
{{ form.image.errors }}
</li>
</ol>
{% endfor %}
<button type="submit">Save</button>
</form>
I am new to django forms and Crispy Forms. I have some simple forms in a little forum Im developing. I think I don't need to use the %crispy% tag. I only need the form|crispy filter. However, I don't know why they don't render the error messages.
Also, if I want to customize the error messages (they must be in spanish), do I need to use the %crispy% tag or is it possible to do this with the |crispy filter?
Anyway, here is one of my forms:
from django import forms
from django.forms import Textarea
class FormNuevoVideo(forms.Form):
url = forms.URLField(initial='http://', max_length=250)
titulo = forms.CharField(max_length=150)
descripcion = forms.CharField(
help_text="...",
widget=Textarea(attrs={'rows': 3, 'data-maxlength': 500}))
Here is the view:
#login_required
def nuevo_video(request, slug):
template = 'videos/nuevo.html'
tema = Temas.objects.get(slug=slug)
if request.method == 'POST':
form = FormNuevoVideo(request.POST)
if form.is_valid():
...
nuevo_video.save()
return redirect('videos:videos_tema', slug=tema.slug, queryset='recientes')
else:
return redirect('videos:nuevo_video', slug=tema.slug) #this same view.
else:
form_nuevo_video = FormNuevoVideo()
context = {'form_nuevo_video': form_nuevo_video, 'tema': tema}
return render(request, template, context)
And in the HTML:
{% block form %}
<form action = "{% url 'videos:nuevo_video' tema.slug %}" method = "post">
{% csrf_token %}
{{form_nuevo_video|crispy}}
<input class = "btn pull-right" type = "submit" value ="enviar"/>
</form>
{% endblock form %}
So, lets say, when someone tries to submit a video with a title of more than 150 characters, it doesn't display the error. I am sure I am missing something simple. Also, I'd like to customize the error messages so that they are in spanish. Thanks in advance.
I'm using the code found here (SO.com) to use the same template to both add and edit a record, but when I add a new record and click Submit, I get a 404 on the URL http://192.168.1.3:5678/app/student/edit/None/, and I'm not exactly sure why.
Here is the relevant portion of my urls.py:
url(r'^app/lesson/new/$', 'edit_lesson', {}, 'lesson_new'),
url(r'^app/lesson/edit/(?P<id>\d+)/$', 'edit_lesson', {}, 'lesson_edit'),
Here is the relevant portion of my views.py:
def edit_lesson(request, id=None, template_name='lesson_edit_template.html'):
if id:
t = "Edit"
lesson = get_object_or_404(Lesson, pk=id)
stu = get_object_or_404(Student, pk=sid)
if stu.teacher != request.user:
raise HttpResponseForbidden()
else:
t = "Add"
lesson = Lesson()
if request.POST:
form = LessonForm(request.POST, instance=lesson)
if form.is_valid():
form.save()
# If the save was successful, redirect to another page
return view_lessons(request)
else:
form = LessonForm(instance=lesson)
return render_to_response(template_name, {
'form': form,
't': t,
'lesson': lesson,
}, context_instance=RequestContext(request))
And finally, here is my template:
<h1>{{ t }} Lesson</h1>
<form action="/app/lesson/edit/{{ lesson.id }}/" method="post"> {% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
I'm certain that I'm missing something really easy, but I can't seem to put my finger on it. I'm using Django 1.3.1 if that makes any difference.
Thanks,
MC
There's no need to specify any URL in the form's action attribute. Just do
<form action="" method="post">
and it will POST back to the URL that you originally used to access it, which is what you want.
In add case {{ lesson.id }} is None, because lesson is unsaved Lesson() instance, without pk, so your form is being fired to nonexistent URL.
I recommend separating create and edit views and processing them in different ways (or even inherit generic views - with new class-based generic views it's easy and pleasant).
Also, use {% url %} template tag everywhere instead of hard-coded urls.
I have a model in Django that allows blanks for two date fields:
class ReleaseStream(models.Model):
name = models.CharField(max_length=200,db_column='name')
version = models.CharField(max_length=20,blank=True,db_column='version')
target_date = models.DateTimeField(null=True,blank=True,db_column='target_date')
actual_date = models.DateTimeField(null=True,blank=True,db_column='actual_date')
description = models.TextField(db_column='description')
...and a form definition:
class ReleaseStreamForm(ModelForm):
class Meta:
model = ReleaseStream
When the form comes up, I can fill in a value for the "target_date", and not for the "actual_date" fields, and when the form.save() fires it appears to write the value supplied for "target_date" into both fields. I have looked at the post data going into the code that does the form.save() and it definitely has a value for "target_date" and a '' for "actual_date", so I don't think that there is something weird with the form itself, variable names in the POST, etc.
Now, if I supply a non-blank value for "actual_date", the form.save() does the right thing - both the "target_date" and "actual_date" have the correct values written in. Am I doing something wrong, or is this potentially a bug in django?
Here is the template (sorry for the blank comment below:)
{% extends "base.html" %}
{% block title %}{{ form_title }}{% endblock %}
{% block subtitle %}{% endblock %}
{% block content %}
<form action={{ action_url }} method="post">
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit" />
</form>
{% endblock %}
And the code that handles the form:
def edit_release_stream(request,req_release_stream_id=None):
form_title = 'Edit release stream'
if request.method == 'POST':
if req_release_stream_id!=None:
release_stream_entry=ReleaseStream.objects.get(pk=req_release_stream_id)
form = ReleaseStreamForm(request.POST,instance=release_stream_entry)
else:
form = ReleaseStreamForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/releases/')
elif req_release_stream_id!=None:
release_stream_entry=ReleaseStream.objects.get(pk=req_release_stream_id)
form = ReleaseStreamForm(instance=release_stream_entry)
else:
form_title = 'Add new release stream'
form = ReleaseStreamForm()
return render_to_response('dashboard/tableform.html', {
'action_url': request.get_full_path(),
'form_title': form_title,
'form': form,
})
... And the post data coming in:
<QueryDict: {u'name': [u'NewRelease'], u'target_date': [u'2011-06-15 00:00'], u'version': [u'4.5.1'], u'actual_date': [u''], u'description': [u'']}>
You can see that it has a valid POST var of "actual_date", with an empty string. This post yields a form.save() that stores the string provided above for "target_date" for both "target_date" and "actual_date".
If I then run a post with differing values for the two dates - here is the post:
<QueryDict: {u'name': [u'NewRelease'], u'target_date': [u'2011-06-15 00:00'], u'version': [u'4.5.1'], u'actual_date': [u'2011-07-15 00:00'], u'description': [u'']}>
In this case, with two distinct, non-empty strings, it writes the correct value shown in the POST above into each of the fields in the db.
I don't believe it to be a bug in Django, or somebody would have seen this problem a long time ago. Can you show us the template that renders the form? Also, if you can show the contents of the request.POST, that'd also be useful.
I'm guessing that your template code is incorrect somehow. The only other problem I can think of would be custom validation in your form (if there is any). Is that the whole ModelForm definition that you've supplied?