Django forms: custom error list format - django

New to python and django. Using the forms module and going through the errors one by one (so not just dumping them at the top)
I noticed this solution to be able to set a custom format for errors, in my case, it'd be:
<dd class="error">errstr</dd>
And more or less copying the example provided, I have the following:
forms.py ( I expanded it slightly just for my sake)
class DefinitionErrorList(forms.util.ErrorList):
def __unicode__(self):
return self.view_as_dd()
def view_as_dd(self):
if not self:
return u''
return u'<dd class="error">%s</dd>' % '<br />'.join([u'<span>%s</span>' % e for e in self])
main.py
from poke.forms import PokeForm, DefinitionErrorList
def create_new(response, useless):
if response.method == 'POST':
# They posted something, so collect it (duh)
f = PokeForm(response.POST, error_class=DefinitionErrorList)
if f.is_valid():
cd = f.cleaned_data
template for reference
<dt>A small message to remind yourself</dt>
{{ form.message.errors }}
<dd>
<span class="input_border" style="width: 75%;"> {{ form.message }}</span>
<span class="tooltip_span">{{ tooltip.message }}</span>
</dd>
The problem is is that with the above, if a field has an error, it still uses the default format (the ), and no matter what I try I can't get my one to be used. I'm pretty sure I missed something small or misunderstood some instructions.
Thanks for any help and I'm sorry if I forgot any information!
Edit: I'm using Django 1.1, if that helps any. And to make it (possibly) clearer, the errors are displaying fine, they just aren't looking the way I want them to.

there has been a long lasting ticket on this. http://code.djangoproject.com/ticket/6138
latest update says it's fixed. see if it works in trunk. if not, submit your bug. if it does, get the patch or wait til the next release. (although i thought the latest release was after the date of the last update on the ticket).

Related

Removing built-in fields from wagtailstreamforms

I'm trying to remove the date, time, and multiselect fields from the wagtailstreamforms Admin page, such that they can't be used in any form site-wide.
I've tried calling register('<field_name>', None) to get rid of it, but this doesn't work:
# wagtailstreamforms_fields.py
from wagtailstreamforms.fields import register
#register('date', None)
#register('time', None)
#register('multiselect', None)
And creating an AppConfig to manually purge the wagtailstreamforms.fields._fields dict of the entries, but that doesn't seem to work either. I've made sure that this AppConfig is part of an app that loads after wagtailstreamforms.
class UpdatedConfig(AppConfig):
name = 'my_new_app'
def ready(self):
from wagtailstreamforms.fields import _fields
_fields.pop('date')
_fields.pop('datetime')
_fields.pop('multiselect')
for x in _fields.keys():
print('{}: {}'.format(x, _fields[x]))
Is there any way to do this, hacky or otherwise? I'm using Wagtailstreamforms 3.1 and Wagtail version 2.2.2.
Im the author of wagtailstreamforms and came across this. The ability to restrict what default form fields are loaded from the package is a great idea.
What I propose is to not load them from the the register method but to load them from a settings dict ie:
WAGTAILSTREAMFORMS_DEFAULT_FIELDS = {
'singleline': 'wagtailstreamforms.fields.SingleLineTextField',
'multiline': 'wagtailstreamforms.fields.MultiLineTextField',
'dropdown': 'wagtailstreamforms.fields.DropdownField'
}
the defaults being all the internal fields. This way it can easily be overridden. We will leave the register decorator in place as to not break anything.
https://github.com/AccentDesign/wagtailstreamforms/pull/110
Please leave any comments / suggestions on the pr or the open issue. If you are happy with this will update docs, merge, release then can amend this as an answer.
Cheers, Stu.
One way would be to override this template: https://github.com/wagtail/wagtail/blob/master/wagtail/admin/templates/wagtailadmin/block_forms/stream_menu.html
{% for child_block in child_blocks.list %}
{% if child_block.name != "date" and child_block.name != "datetime" and child_block.name != "multiselect" %}
<li><button type="button" class="button action-add-block-{{ child_block.name }} icon icon-{{ child_block.meta.icon }}"><span>{{ child_block.label }}</span></button></li>
{% endif %}
{% endfor %}
We were able to get what we needed by putting following code in the app's wagtailstreamforms_fields.py
# wagtailstreamforms_fields.py
from wagtailstreamforms.fields import _fields
if _fields.get('date'):
del(_fields['date'])
if _fields.get('datetime'):
del(_fields['datetime'])
if _fields.get('multiselect'):
del(_fields['multiselect'])
So I guess you can say its a mix of the above 2 methods. It might be obsolete in the near future, see Stuart George's answer and its linked PR.

Submit Button Confusion and Request being sent Twice (Using Flask)

I'm pretty much trying to create a web app that takes 2 svn urls and does something with them.
The code for my form is simple, I'm also using WTForms
class SVN_Path(Form):
svn_url=StringField('SVN_Path',[validators.URL()])
I'm trying to create 2 forms with 2 submit buttons that submit the 2 urls individually so my test3.html looks like this:
<form action="" method="post" name="SVNPath1">
{{form1.hidden_tag()}}
<p>
SVN Directory:
{{form1.svn_url(size=50)}}
<input type="submit" value="Update">
<br>
{% for error in form1.svn_url.errors %}
<span style="color: red;">[{{error}}]</span>
{% endfor %}
</p>
</form>
<form action="" method="post" name="SVNPath2">
{{form2.hidden_tag()}}
<p>
SVN Directory:
{{form2.svn_url(size=50)}}
<input type="submit" value="Update">
<br>
{% for error in form2.svn_url.errors %}
<span style="color: red;">[{{error}}]</span>
{% endfor %}
</p>
</form>
MY FIRST QUESTION is how do I know which submit button was clicked so I can run the proper function on the corresponding svn url. I have tried doing something like
if request.form1['submit'] == 'Update':
if request.form2['submit'] == 'Update':
but that does not work at all. I'm new to web dev in general and flask so a detailed explanation would be helpful.
SECONDLY, since submits weren't working properly I also tried an alternative to keep my work moving so in my .py file I have
#app.route('/test3', methods=['GET','POST'])
def test3():
basepath=createDir()
form1=SVN_Path()
form2=SVN_Path()
if request.method=="POST":
if form1.validate_on_submit():
svn_url = form1.svn_url.data
prev_pdf=PDF_List(svn_url,basepath,'prev') #some function
if form2.validate_on_submit():
svn_url2 = form2.svn_url.data
new_pdf=PDF_List(svn_url,basepath,'new') #some function
return render_template('test3.html', form1=form1, form2=form2)
CreateDir is a function that creates a directory in the local /tmp using timestamps of the local time.
Whenever I go the webpage it creates a directory, lets call it dir1, since its calling CreateDir. Thats what I want, but when I click submit on the form it creates another directory dir2 in the tmp folder which is NOT what I want since I want everything to being the same dir1 directory.
In addition when I put a url in one of the forms and click submit, it automatically puts it the same value in the 2nd form as well.
Sorry if this is really long and possibly confusing, but any help is appreciated.
:) Let's see if we can clarify this a little.
To your first question:
As #dim suggested in his comment, You have a few options:
You can submit your form to separate unique urls. That way you know which form was submitted
You can create two similar but different Form classes (the fields will need different names like prev_svn_url and cur_svn_url). This way in your view function, you instantiate two different forms and you'll know which form was submitted based on form.validate_on_submit()
The third option would be to add a name attribute to your submit button and then change the value attributes to something like 'Update Previous' and 'Update Current'. This way in your view function you can check the value of request.data[<submit button name>] to determine if 'Update Previous' was pressed or 'Update Current'.
To your second question:
Multiple directories are being created because you're calling createDir() each time the page is loaded to show the forms and when the forms get posted. In order to create just once, you'll need some kind of logic to determine that the directory was not previously created before calling createDir()
In addition: Since both forms are from the same SVN_Path class, they read post data exactly the same way, that's why whatever you type in form 1 appears in form 2.
Now for my 2 cents:
I assume you're trying to write some kind of application that takes two SVN urls as input, creates a folder and does something with those URLs in that folder. If this is the case, the way you are currently going about it is inefficient and won't work well. You can achieve this with just one form class having 2 svn_url fields (with different names of course) and then handling all of that in one post.
EDIT: The job of the submit button is to tell the browser that you're ready to send the data on the form to the server. In this case you should only need one submit button (SubmitFiled => when rendered). Clicking that one submit button will send data from both input fields to your view function.
Your form should look something like:
class SVN_Path(Form):
prev_svn_url=StringField('Previous SVN_Path',[validators.URL()])
new_svn_url=StringField('New SVN_Path',[validators.URL()])
and your view function:
def test():
form = SVN_Path()
if request.method == "POST":
if form.validate_on_submit():
basepath = createDir() # Only create dir when everything validates
prev_svn_url = form.prev_svn_url.data
new_svn_url = form.new_svn_url.data
prev_pdf = PDF_List(prev_svn_url, basepath, 'prev')
new_pdf = PDF_List(new_svn_url, basepath, 'new')
...
return render_template('test3.html', form1=form1, form2=form2)

What is the right way of iterating over django form?

I am dynamically creating a form like so;
def partial_order_item_form(item):
"""dynamic form limiting optional_items to their items"""
class PartialOrderItemform(forms.Form):
quantity = forms.IntegerField(widget=forms.TextInput(attrs={'size':'2', 'class':'quantity','maxlength':'5'}))
option = forms.ModelChoiceField(queryset=OptionalItems.objects.filter(item=item),widget= forms.RadioSelect())
return PartialOrderItemform
with that,i can render the options in the template like so and it works perfectly;
{% for item in form.option %}
{{ item }}
{%endfor%}
but this {{ item.price }} does not work. I need a brief explanation on why its not working and a way to go about it.
I have looked around but failed to find similar questions (i must not be searching the right way ), links are much appreciated.
I think you need the field queryset if you want to iterate. Use manage.py shell to instantiate a form and introspect. Why not use form.as_XXX?

Django/Haystack - best option to have a listview with search capability

I have an app with a Restaurant model. I'd like to understand what is the best way to put together a view that displays the list of restaurant objects, but also has a search form above that a user could enter parameters to filter the results displayed. If no parameters are entered, all the restaurants should be shown. I'm already using haystack and have a search form, but currently it is on a standalone search.html template. I also have an ListView on a separate template, and I guess I'm looking for an end result that combines these.
I did some reading on line and it's unclear what the best way to do it is:
using just listview from Django with some queryset filtering
combining haystack SearchView with django class based views?
this is my best bet so far - creating a customized version of SearchView from Haystack
ideally, ultimately the search capabilities would include things like allow autocompleting the user's inputs, and dynamically filter the results as the user types.
any thoughts on what the best way is to go about this and any examples out there?
There probably is out there some package that gives you everything automatically, displaying the queryset list and allowing simple adding of a search bar and so on (like the admin site). But I take it you are still a beginner to web development, so I'd strongly suggest you drop the listviews, drop haystack, drop everything, and do it all yourself.
See, they're not bad approaches or anything, but they're like shortcuts. And shortcuts are good only if they shorten the original way, which in your case isn't all that long.
To give you an example, here's a simple approach to displaying a list of items:
views.py
def restaraunt_list(request):
restaraunts = Restaraunt.objects.all().order_by('name')[:100] # Just for example purposes. You can order them how you'd like, and you probably want to add pagination instead of limiting the view number arbitrarily
context = {'restaraunts': restaraunts}
return render_to_response('index.html', context)
index.html:
<ul>
{% for rest in restaraunts %}
<li>{{ rest }}</li>
{% endfor %}
</ul>
That's it. Now it displays it in a list. Now to add a search filter all you need to do is this:
index.html (add this anywhere you want it)
<form>
<input type='text' name='q' id='q'></input>
<input type='submit' value='search!'></input>
</form>
When a user sends the data from 'q' it is sent through GET, and then on server side you add this:
def restaraunt_list(request):
restaraunts = Restaraunt.objects.all()
# filter results!
if request.method == 'GET':
q = request.GET['q']
if q != '':
restaraunts = restaraunts.filter(name__contains=q)
# ordering is the last thing you do
restaraunts = restaraunts.order_by('name')[:100]
context = {'restaraunts': restaraunts}
return render_to_response('index.html', context)
Now, this will work, but from what you wrote I understand you want the search to be live the moment a key is pressed. For that, you'd need to use AJAX (go learn how it works, I'm not gonna delve into it here). As for autocomplete, you should check out jQuery UI.
But, like I said, before jumping ahead and using all those stuff, I suggest you first learn the basics. Go through the django tutorial (if you haven't already), and use the amazingly detailed django-docs every step of the way. When some specific things won't work and you're stuck, come here to Stackoverflow and someone will surely help you. good luck!

Using the Django assignment_tag built-in tag the right way

I'm working on a project in Django.
Earlier today, I discovered the new (Django >= 1.4) assignment_tag. I immediately decided that it was just what I needed EVERYWHERE and threw some logic into one that executed a very simple query against the database and returned the resulting queryset. The function I wrapped takes an argument that allows the invoking context to specify how many results to grab, directly in the template when I am using the template tag.
It is quite convenient - I don't have to update my view when I decide this list should have 5 items, not 3 - but it seems like one of those gray areas where we aren't supposed to tread (i.e. pushing application logic into templates) when writing good, maintainable Django code.
Now, a couple of hours separated from writing the code, I'm wondering if I should scrap the assignment_tag entirely.
Code:
models.py:
class SomeObject(models.Model):
is_active = models.BooleanField(default=False)
(...)
templatetags/myapp_tags.py:
from django import template
from myapp.models import SomeObject
register = template.Library()
#register.assignment_tag
def get_someobjects_list(max_results=0):
queryset = SomeObject.objects.filter(is_active=True)
if max_results == 0:
return queryset
elif max_results > 0:
return queryset[:min(max_results, queryset.count())]
else:
return None
templates/myapp/chunks/someobject_list.html:
{% load myapp_tags %}
{% get_someobjects_list as someobjects_list %}
# or {% get_some_objects_list 5 as someobjects_list %} ... flexible!
{% if someobjects_list %}
<ul>
{% for someobject in someobjects_list %}
<li>
<a href="{{ someobject.get_absolute_url }}">
{{ someobject.name }}
</a>
</li>
{% endfor %}
</ul>
{% else %}
<span>No someobjects exist</span>
{% endif %}
I was really excited to discover these existed - it's convenient for me in this particular case. Now that my excitement over finding a new feature has passed, it seems pretty clear that I'm misusing it. The example given in the Django docs seems like a better application of this - grabbing the string representation of current datetime, something that doesn't require a DB query. My worry is that I'm setting myself up for heartache if I start using this pattern regularly. Following the slippery slope all the way down: I'll end up not even bothering to pass a context to my templates and ALL my DB queries will be hidden away in template tags where nobody would think to look for them.
It seems the code would be cleaner if I just threw out this whole "great idea" I had when I discovered assignment_tags and created a custom model manager instead.
Are there other clean ways of accomplishing this that I am missing? Are manager methods the consensus best way among Django developers?
assignment template tags are especially helpful if you need to get some information into the template context for a few pages of a website, but don't want to (or can't) put the info into every view on the website, and don't want to or can't rely on a context processor.
they basically guarantee that your information will be available in the template.