Form Field API? - python

I am iterating through list of form fields. How do I identify the type of each field? For checkbox I can call field.is_checkbox...are there similar methods for lists, multiplechoicefields etc. ?
Thanks

Have a look at the class for each field on your form:
for f_name, f_type in my_form_instance.fields.items():
print "I am a ",type(f_type)
# or f_type.__class__
This will produce output similar to <class 'django.forms.fields.BooleanField'>.
You can get the name as a simple string, if you prefer that, with:
print type(f_type).__name__
# produces 'BooleanField'
Edit: Also be careful about the distinction between a field and a widget. There isn't a Checkbox field in Django, but only a CheckboxInput widget, which is the default for a BooleanField. Do you mean to look up the widget (which is very rendering specific), or the field (which has more of a relation to the data type and validation for that form field)? If the widget, you can get the widget type using:
f_type.widget
Hope that helps!

I am not sure if this is what you want, but if you want to know what kind of field it is going to end up being in the HTML, you can check it with this:
{% for field in form %}
{{ field.field.widget.input_type }}
{% endfor %}
widget.input_type will hold text, password, select, etc.
P.S. I did not know this until 5 seconds ago. #django irc.freenode.net always has good help.

Presuming you're using HTML here... Because it isn't very clear.
How about giving it an extra class.
And if you didn't know allready, the class attribute will recognise this:
class="hello there you"
as having 3 classes. The class 'hello', the class 'there', and the class 'you'.
So if they allready have a class, just add a space and your custom clasname.

Related

Is there a way to enforce "one of theses inputs but not all are required" for Django forms?

I'm writing a function that updates one of three possible fields in Django--either a boolean, a string, or an integer.
I attempted to to it this way:
class AccountsForm(forms.Form):
update_key = forms.CharField(required=True)
update_value = forms.ComboField(fields=[forms.CharField(),
forms.IntegerField(), forms.BooleanField()],
required=True)
But this is not the functionality I'm looking for, as it expects a combination of a CharField+IntegerField+BooleanField. I need at exactly one of the three fields to be present in the form. Is this possible with django forms?
Yes there is. The Django docs actually show you how to do that:
Use three separate fields
Make all of them not required (required=False)
Add a clean() method to your form where you validate the three fields together. If you first call super().clean(), you can be sure that the fields have been validated separately first, e.g. that the input to the IntegerField is actually an integer, so you don't need to do that anymore.
Use the cleaned_data dictionary to look at the values for each field. You could also check self.errors[<field>] to see if any of the fields was filled in incorrectly.
Raise a ValidationError is you're not happy with the input.
In your template, don't forget to display the {{ form.non_field_errors }} at the top of your form so the user knows the error you're raising. Or just add the error on specifically one of the fields to display it close to the field.

Print all properties of an App Engine Model

I'm trying to find a way to easily loop through a Google App Engine (Python) Model and to print out each property and the property name.
This is how I'm trying it, and after some research I realize I can't next variables in each other. Is there a way to do this with filters or a way to return all of the values of the properties of a Model?
Thanks
templateargs = {'properties':MyModel.properties(), 'user1':MyModelObj, 'user2':MyModelObj}
{% for property in properties %}
Property: {{property}}
User1: {{user1.{{property}}}}
User2: {{user2.{{property}}}}
{% endfor %}
Take a look at how this to_json method grabs all the property values on a Model instance, it should point you in the right direction.
After some more research I realized the proper way to do this was with gettattr. I used a filter along the lines of:
#register.filter
def mygetattr(obj, name):
return getattr(obj, name)
As suggested here
Try:
vars(user1)[property]
See Built-in Functions.html#vars for a short explanation of how vars returns a dictionary of the instance variables.

Django: avoiding multiple evaluations of the same expression in a template?

When passing an object called widget as part of the context to rendering a django template, I may have a method which is a bit expensive, but I want to display the result of it more than once.
Python:
class Widget:
def work(self):
# Do something expensive
Template
This is a widget, the result of whose work is {{widget.work}}. Do
you want to save {{widget.work}} or discard {{widget.work}}?
Clearly I could work around this by evaluating the method once in the view code, and then passing the result in, but this seems to couple the view and the template too much. Is there a way for the template author to stash values for re-use later in the template? I would like to do something like this:
{% work_result = widget.work %}
This is a widget, the result of whose
work is {{work_result}}. Do you want to save {{work_result}} or discard {{work_result}}?
Does such a construct exist in the django template language?
{% with %}
{% with work_result=widget.work %}
Look Django docs for more information

Additional fields in Django admin interface

Suppose I have some persistent model property that's not backed up by a model field, how do I allow editing this field in the admin interface?
Example setup:
# models.py
# appropriate imports...
class MyModel(Model):
# regular fields.
foo = CharField(max_length=50)
bar = BooleanField()
# ...
# custom property, backed by a file.
def _get_meh ( self ):
return ... # read from file
def _set_meh ( self, value ):
... # write to file.
meh = property(_get_meh, _set_meh)
meh's value is actually stored in a file on disk who's path depends on the value in foo. I'd like to be able to edit meh's value from the admin interface.
# admin.py
# appropriate imports...
class MyModelAdmin(ModelAdmin):
# what do I put here?
Note: in case someone needs to ask, I'm using Django version 1.2.1, but upgrading is possible if that is required by your solution. Anything that runs on Python 2.5 will do, this I can't really upgrade for the moment.
Take a look at this:
http://www.scribd.com/doc/68396387/Adding-extra-fields-to-a-model-form-in-Django%E2%80%99s-admin-%E2%80%93-Hindsight-Labs
(this one went offline, http://www.hindsightlabs.com/blog/2010/02/11/adding-extra-fields-to-a-model-form-in-djangos-admin/)
Basically, you'll create a MyModelFrom subclassed from forms.ModelForm and:
Add the extra meh fields to the MyModelFrom definition.
Override the constructor of the MyModelFrom, set the self.initial meh property if a model instance was passed to the form.
Override the save method of the MyModelFrom, set the meh property on the model instance based on the form fields.
This way, the meh property would be correctly filled at your Model, but you'll also need to override MyModel's save() method to actually persist this value to your disk file:
(Google for "django model override save", sry, it seems I can't post more than a link per answer till I get more than 10 rep...)
Cheers,
Ny Django knowledge isn't that great, but depending on how complicated you want it to be, I'm not sure something like this can be easily done without much hackery.
Anyhow, if you want to add it to Add MyModel page, you can edit the appropriate admin template.
So in your template directory, create something like:
admin/app_label/MyModel/change_form.html
Then extend the base template, and add your own content:
{% extends "admin/change_form.html" %}
{% block something_you_want_to_override %}
<p>Your HTML goes here</p>
{% endblock %}
Is there really no way you can get this custom field into an actual Django field though? Surely you can override the save() method on the model and do it that way? Or use a pre_save signal?
Cheers,
Victor

Dynamically Display field values in Django template (object.x)

I am currently working on an app that uses custom annotate querysets. Currently i have 2 urls setup, but i would need one for each field that the users would like to summarize data for. This could be configured manually, but it would violate DRY! I would basically have +-8 urls that basically do the same thing.
So here is what i did,
I have a created custom model manager
I have a view
I have the URLS configured
All of the above works.
So basically the URL config passes to the view the name of the field to annotate by (group by for SQL folks), the view does some additional processing and runs the custom model manager based on the field that was passed to it.
The URL looks like this:
url('^(?P<field>[\w-]+)/(?P<year>\d{4})/(?P<month>\d+)/(?P<day>\d+)/$','by_subtype', name='chart_link'),
The field is the column in db the that is used when the queryset is actually run. It is passed from the view, to my custom manager. Below is an example of the code from the manager:
return self.filter(start_date_time__year=year).filter(start_date_time__month=month).filter(start_date_time__day=day).values(field).annotate(Count(field))
In addition, i pass the value of field as context variable. This is used to dynamically build the links. However the problem is actually looping through the query set and displaying the data.
So your typical template code looks like this:
{% for object in object_list %}
{{ object.sub_type }} : {{ object.sub_type__count|intcomma }}
{% endfor %}
Basically you have to hard code the field to diplay (i.e object.x), is there anyway to dynamically assign this? i.e
if field = business
then in the template it should automatically process:
{{ object.business }}
Can this be done? Or would i need to create several URLS? Or is there a better way to achieve the same result, a single view and url handling queries dynamically.
You can find the code over at github, the template part is now working using this snippet: http://www.djangosnippets.org/snippets/1412/ So if you come across this later and want to do something similar have a look at the code snippet at github. : http://gist.github.com/233262
It sounds like you want to do something along the lines of:
# in the views.py:
field = 'business'
{# in the template: #}
{{ object.field }}
and have the value of object.business appear in the output. This isn't possible with the Django template language out of the box.
There are snippets that define template filters you can use to accomplish this though: http://www.djangosnippets.org/snippets/1412/
As mentioned above, you can do this with a custom template filter.
For example:
#register.filter(name='get_attr')
def get_attr(obj, field_name):
if isinstance(obj, dict):
return obj.get(field_name)
return getattr(obj, field_name)
Then, using it in your template:
{{ obj|get_attr:'business' }}

Categories

Resources