I'm doing django-contrib-comment's custom comment app to my django app. At long last i achieved my comment app that has image field, and it shows in template of course. But here is the thing, When i'm trying to post comment with image, it does not saving image file, and says empty(This field is required). Can anyone help me to figure it out. Here is some code snippets.
models.py
class CommentWithPic(Comment):
image = models.ImageField(upload_to="comments/%Y/%m/%d/", null=True, blank=True)
forms.py
class CommentFormWithPic(CommentForm):
image = forms.ImageField()
def get_comment_model(self):
return CommentWithPic
def get_comment_create_data(self):
data = super(CommentFormWithPic, self).get_comment_create_data()
data['image'] = self.cleaned_data['image']
return data
post_with_comment.html
{% render_comment_list for adi %}
{% get_comment_form for adi as form %}
<form action="{% comment_form_target %}" method="post">
{% csrf_token %}
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
{% if field.errors %}{{ field.errors }}{% endif %}
{{ field.label }}
{{ field }}
{% endif %}
{% endfor %}
<input type="hidden" value="{% url 'ad' adi.id %}"/>
<input type="submit" value="comment"/>
</form>
You need to declare your form like the following (notice the enctype attribute) when dealing with `ImageField
<form enctype="multipart/form-data" action="{% comment_form_target %}" method="post">\
to bind uploads to a form:
Dealing with forms that have FileField and ImageField fields is a little more complicated than a normal form.
Firstly, in order to upload files, you’ll need to make sure that your element correctly defines the enctype as "multipart/form-data"
You also need to make the image optional in the form:
class CommentFormWithPic(CommentForm):
image = forms.ImageField(required=False)
...
Related
I want to replace the add object button in the listview of an admin page. The underlying idea is that an administrator can download data on all models in the db, use a tool to edit the data, and then reupload as a CSV file.
In the list view I am struggling to override the form, as setting
class SomeModelForm(forms.Form):
csv_file = forms.FileField(required=False, label="please select a file")
class Meta:
model = MyModel
fields = '__all__'
class SomeModel(admin.ModelAdmin):
change_list_template = 'admin/my_app/somemodel/change_list.html'
form = SomeModelForm
other stuff
The admin change_list.html is overridden as follows:
{% extends "admin/change_list.html" %}
{% load i18n admin_urls admin_static admin_list %}
{% block object-tools-items %}
<form action="{% url 'admin:custom_submit_row' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>
{{ form.as_p }}
</p>
<p><input type="submit" value="Upload" /><input type="reset" value="Reset"></p>
</form>
{% endblock %}
Previously SomeModel was missing the class Meta, as per sebbs response this is updated. The original error has been resolved but now currently the admin page is displaying the upload and reset buttons but no field for file uploads.
cheers
Edited with sebb's input below. Thanks sebb.
The error fixed was
< class ‘my_model.admin.SomeModelAdmin'>: (admin.E016) The value of 'form' must inherit from 'BaseModelForm'
OP here, solution is as follows:
class SomeModelForm(forms.Form):
csv_file = forms.FileField(required=False, label="please select a file")
class SomeModel(admin.ModelAdmin):
change_list_template = 'admin/my_app/somemodel/change_list.html'
def get_urls(self):
urls = super().get_urls()
my_urls = patterns("",
url(r"^upload_csv/$", self.upload_csv, name='upload_csv')
)
return my_urls + urls
urls = property(get_urls)
def changelist_view(self, *args, **kwargs):
view = super().changelist_view(*args, **kwargs)
view.context_data['submit_csv_form'] = SomeModelForm
return view
def upload_csv(self, request):
if request.method == 'POST':
form = MineDifficultyResourceForm(request.POST, request.FILES)
if form.is_valid():
# process form
with the template overridden as so:
{% extends "admin/change_list.html" %}
{% load i18n admin_urls admin_static admin_list %}
{% block object-tools %}
{% if has_add_permission %}
<div>
<ul class="object-tools">
{% block object-tools-items %}
<form id="upload-csv-form" action="{% url 'admin:upload_csv' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ submit_csv_form.as_p }}</p>
<p>{{ submit_csv_form.csv_file.errors }}</p>
<p><input type="submit" value="Upload" />
<input type="reset" value="Reset"></p>
</form>
{% endblock %}
</ul>
</div>
{% endif %}
{% endblock %}
The form needs some custom validation but otherwise this solves the difficult part of customizing the admin page.
To elaborate what is going on here:
get_urls is overridden so that an additional endpoint can be added to the admin page, this can point to any view, in this case it points upload_csv
changelist_view is overridden to append the form info to the view
the change_list.html template block "object-tools" is overridden with the form fields
Hopefully someone else finds this helpful as well.
to your class SomeModelForm add something like this:
class Meta:
model = YourModel
fields = '__all__'
and change from forms.Form to forms.ModelForm
I have a the following code for a Form that I have in my Flask application using Wtforms. I use FieldList to use two fields for one part.
class A(Form)
additional = FieldList(FormField(Additional), 'Additional', min_entries=1)
submit = SubmitField('Submit')
class Additional(Form):
choices = [('Funding Mechanism', 'Funding Mechanism'), ('Study Section Name', 'Study Section Name')]
critera = SelectField('Additional Criteria', choices=choices)
input = StringField()
The template uses wtf.quick_form:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Grants - Find Grant{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Specify</h1>
</div>
<div class="col-md-4">
{{ wtf.quick_form(form) }}
</div>
{% endblock %}
Currently the forms render in a squished and overlapping way like so:
How can I change the code so that it is formated in one line like below? It is a screenshot of #Niklas in Stockholm 's form from his question.
Thank you!
Since your form class A is calling class Additional as a FormField and only adding submit to the field, i added the submit button the Additional form itself and then called it in the view.
In the template, use
{{ wtf.quick_form(form, form_type="inline") }}
It outputs the page like this:
The form_type argument adds the .form-inline to the class attribute.
This is just a hack, surely your form will have more inputs than this, for that, you'll be writing the whole form template yourself.
The issue is that {{ wtf.quick_form(form) }} is calling wtf.form_field() on your FieldList additional in A instead of calling it on additional's subfields. Because of this, I don't think you will be able to use wtf.quick_form() on your particular form.
Instead, try templating your form like this:
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Grants - Find Grant{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Specify</h1>
</div>
<div class="col-md-4">
<form class="form form-horizontal" method="post" role="form">
{{ form.hidden_tag() }}
{{ wtf.form_errors(form, hiddens="only") }}
{% for subfield in form.additional %}
{{ wtf.form_field(subfield) }}
{% endfor %}
{{ wtf.form_field(form.submit) }}
</form>
</div>
{% endblock %}
You can read more about wtf.form_field() on the Flask-Bootstrap documentation site.
I am using Django Form View to split a large, single-page form into a multi-page form with separate templates for each one. I followed the documentation and other online examples, and most everything is going well.
However, the problem is that I have required fields in the form and they are failing validation because, as it turns out, the data is not being passed back to Django (as was verified by overriding 'is_valid()' and printing the form data, as well as printing {{ wizard.form.errors }} in my templates). It may be worth noting that the form worked fine before I split it up.
Below is a shortened version of the relevant code. If anyone has some pointers that would be great. I am no expert at this and the original code was not written by me, so I'll answer any questions as best I can. Thanks!:
VIEWS.PY
FORMS = [("venue", RegisterBusinessFormVenue),
("manager", RegisterBusinessFormManager),
("extras", RegisterBusinessFormExtras)]
TEMPLATES = {"venue": "registrationVenue.html",
"manager": "registrationManager.html",
"extras": "registrationExtras.html"}
class RegisterBusinessView(SessionWizardView):
file_storage = FileSystemStorage(location=os.path.join('/var/www/', 'logos'))
def get_template_names(self):
return TEMPLATES[self.steps.current]
def done(self, form_list, **kwargs):
return HttpResponseRedirect(reverse_lazy('submission_page_view'))
MODELS.PY
class RegisterBusinessFormVenue(forms.Form):
venue_name = forms.CharField(label='Venue Name', max_length=128)
class RegisterBusinessFormManager(forms.Form):
manager_first_name = forms.CharField(label='First Name', max_length=255)
class RegisterBusinessFormExtras(forms.Form):
website = forms.URLField(label="Website", required=False)
URLS.PY
url(r'^register/', RegisterBusinessView.as_view(FORMS), name='register_business_view')
TEMPLATE
{% extends "base.html" %}
{% load staticfiles %}
{% block stylesheet %}
<link rel="stylesheet" href="{% static 'css/registration.css' %}">
{% endblock stylesheet %}
{% block content %}
<div class="page-header">
<h1>Register your business</h1>
</div>
<form class="form-horizontal" role="form" action="" method="POST">{% csrf_token %}
{{ wizard.management_form }}
{{ wizard.form.errors}}
{{ wizard.form.non_field_errors}}
<legend>Event Venue Information</legend>
<div class="form-group required {% if wizard.form.venue_name.errors %}has-error{% endif %}">
<label for="inputVenueName" class="col-sm-3 control-label">{{ wizard.form.venue_name.label }}</label>
<div class="col-sm-9">
<input type="text" class="form-control"
name="{{ wizard.form.venue_name.name }}"
id="inputVenueName"
{% if wizard.form.venue_name.value %}value="{{ wizard.form.venue_name.value }}"{% endif %}
placeholder="Venue name where events are held"
spellcheck="true">
</div>
</div>
<div class="register-btn-block">
<button type="submit">Register</button>
</div>
</form>
{% endblock content %}
I answered my own question. It was a dumb mistake on my part: I wasn't using the wizard provided id's and name's for my html markup. In my template above where I have the 'label for' and 'id' attributes, they should be populated with the value '{{ wizard.form.venue_name.id_for_label }}'. For the 'name' attribute, it should be populated with '{{ wizard.form.venue_name.html_name }}'.
The pre-defined values that can be used are found here. After making these changes, then the form data was properly submitted to the server.
Below is my form code :
class FMessage(forms.Form):
From = forms.CharField()
To = forms.CharField()
Subject = forms.CharField()
Message = forms.CharField()
and this is my html code:
<form method='POST' action='.'>
{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='submit'>
</form>
The code works fine by displaying forms and has not any issue in functionality, but now I need to wrap my form fields in html by a div like this:
<div id='mydiv'>
<input ... />
<div>
How can I fix it?
Seems like you do not really want to use the inbuilt <p> or <table> wrapped forms and rather want to display the fields wrapped within a <div>'s. You can simply iterate over fields in the form as follows.
{% if form %}
<!-- Form Errors -->
{% if form.errors %}
<ul class="errors">
{% for error in form.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<!-- Display Form -->
<form>
{% csrf_token %}
{% for field in form %}
<div class="mydiv">
<label class="mylabel">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
</form>
{% endif %}
Dont render the form by using form.as_p. You need to show each field of the form, for example, by using form.to. By using this way, you can wrap the field 'to' into a div
<div>{{ form.To}} </div>
For more detail, view this link
I have a model:
class Setting(models.Model):
class Meta:
abstract = True
name = models.CharField(max_length=120, primary_key=True)
description = models.CharField(max_length=300, blank=True)
class IntegerSetting(Setting):
value = models.IntegerField()
I would like to create a form that looks something like:
<form method="POST" action="">
{% for model in models %}
<label>{{model.name}}</label> <input value='{{model.value}}' />
<p>{{model.description}}</p>
{% endfor %}
</form>
I'm not quite sure how to go about doing this. Perhaps I need to use a formset?
from django.forms.models import modelformset_factory
from apps.about.models import Setting, IntegerSetting
def site_settings(request):
formset = modelformset_factory(IntegerSetting)()
return render_to_response("about/admin/site-settings.html", {'formset': formset}, RequestContext(request, {}))
Then in the template, I'd want to render the form differently than default. I'm not quite sure how to go about accessing the model properties, however. Is this the right approach, or is there another way I should be going about doing this?
Update: This is what I'm currently doing. It renders exactly as I'd like it to, aside from the styling. However, I feel that it's deeply hacky:
class SettingsForm(ModelForm):
class Meta:
model = IntegerSetting
def as_table(self):
bound_field = BoundField(self, self.fields['value'], 'value')
return mark_safe("<tr><td><label>%s</label></td><td>%s\n<p class='help'>%s</p></td></tr>" % (self.instance.name,
self.instance.description,
bound_field.__unicode__()))
def edit_settings(request):
forms = [SettingsForm(instance=intSetting) for intSetting in IntegerSetting.objects.all()]
return render_to_response("admin/edit-settings.html", {'forms': forms}, RequestContext(request, {}))
edit-settings.html:
{% extends "admin/base_site.html" %}
{% block title %}System Settings{% endblock %}
{% block content %}
<form method="post" action="">
<table>
{% for form in forms %}
{{form}}
{% endfor %}
</table>
</form>
{% endblock %}
Is there a better approach to this?
Also, I'm not sure if I'll encounter problems when the form is submitted or not.
<form action="/contact/" method="post">
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Send message" /></p>
</form>
You can find the complete documentation here:
http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template
I don't think you need a formset here. Take a look here if you want a custom template for one view. If you want to create your own {{ form.as_foobar }}, just subclass forms.Form, something like this:
class MyForm(forms.Form):
def as_foobar(self):
return self._html_output(
normal_row = u'%(label)s %(field)s%(help_text)s',
error_row = u'%s',
row_ender = '',
help_text_html = u' %s',
errors_on_separate_row = False)
and just use it in your forms.py:
class ContactForm(MyForm):
# ..
For whoever needs the <table> version of jbcurtin's answer:
<form method="post">{% csrf_token %}
<table>
{% for field in form %}
<tr>
<th>{{field.label_tag}}</th>
<td>
{{ field.errors }}
{{ field }}
</td>
</tr>
{% endfor %}
</table>
<hr/>
<input type="submit" value="Conferma" />
</form>
Looks like you might be interested in django-floppyforms (docs), which gives you much more control over field rendering.