Posts tagged with django-forms
Published at May 24, 2015
| Tagged with:
Django
,
django-forms
... and some answers
Well I haven't conducted any interviews recently but this one has been laying in my drafts for a quite while so it is time to take it out of the dust and finish it. As I have said in Python Interview Question and Answers these are basic questions to establish the basic level of the candidates.
-
Django's request response cycle
You should be aware of the way Django handles the incoming requests - the execution of the middlewares, the work of the URL dispatcher and what should the views return. It is not necessary to know everything in the tiniest detail but you should be generally aware of the whole picture. For reference you can check "the live of the request" slide from my Introduction to Django presentation.
-
Middlewares - what they are and how they work
Middlewares are one of the most important parts in Django. Not only because they are quite powerfull and useful but also because the lack of knowledge about their work can lead to hours of debugging. From my experience the process_request and process_response hooks are the most frequently used and those are the one I always ask for. You should also know their execution order and when their execution starts/stop. For reference check the official docs.
-
Do you write tests? How?
Having well tested code benefits you, the project and the rest of the team that is going to maintain/modify your code. Django's built-in test client, Django Webtest, Factory boy, Faker or whatever you use, I would like to hear about it and how you do it. There is not only one way/tool for it so I would like to know what are you using and how. You should show that you understand how important is to test your code and how to do it right.
-
select_related and prefetch_related
Django's ORM (as every other) can be both a blessing and a curse. Getting a foreign key property can easily lead you to executing million queries. Using select_related and prefetch_related can come as a saviour so it is important to know how to use them.
-
Forms validation
I expect from the candidates that they know how to build forms, to add custom validation for one field and how to validate fields that depend on each other.
-
Building a REST API with Django
The most popular choices out there are Django REST Framework and Django Tastypie. Have you used any of them, why an how. What issues have you faced? Here is the place to show that you understand the concept of REST APIs, the correct request/response types and the serialisation of the data.
-
Templates
Building website using the built-in template system is often part of your daily tasks. This means that you should understand the template inheritance, how to reuse the block and so on. Having experience with sekizai is a plus.
There are a lot of other things to ask about internationalisation(i18n), localisation(l10n), south/migrations etc. Take a look at the docs and you can see them explained pretty well.
Published at Jan. 23, 2012
| Tagged with:
Python
,
Django
,
django-forms
,
django-models
,
Development
Preface: Sometimes, parts of the data that you have to display in your application reside out of the Django models. Simple example for this is the following case - the client requires that you build them a webshop but they already have CRM solution that holds their products info. Of course they provide you with a mechanism to read this data from their CRM.
Specialty: The problem is that the data in their CRM does not hold some of the product information that you need. For instance it misses SEO-friendly description and product image. So you will have to set up a model at your side and store these images there. It is easy to join them, the only thing that you will need is a simple unique key for every product.
Solution: Here we use the product_id field to make the connection between the CRM data and the Django model.
# in models.py
class Product(models.Model):
product_id = models.IntegerField(_('Original Product'),
unique=True)
description = models.TextField(_('SEO-friendly Description'),
blank=True)
pod_image = FilerImageField(verbose_name=_('Product Image'),
blank=True, null=True)
@property
def name(self):
return crm_api.get_product_name(self.product_id)
# in forms.py
class ProductForm(forms.ModelForm):
name = forms.CharField(required=False,
widget=forms.TextInput(attrs={
'readonly': True,
'style': 'border: none'}))
class Meta:
model = Product
widgets = {
'product_id': forms.Select(),
}
def __init__(self, *args, **kwargs):
super(ProductForm, self).__init__(*args, **kwargs)
self.fields['product_id'].widget.choices = crm_api.get_product_choices()
if self.instance.id:
self.fields['name'].initial = self.instance.name
The form here should be used in the admin(add/edit) page of the model. We define that the product_id field will use the select widget and we use a method that connect to the CRM and returns the product choices list.
The "self.instance.id" check is used to fill the name field for product that are already saved.
Final words: This is a very simple example but its idea is to show the basic way to connect your models with another app. I strongly recommend you to use caching if your CRM data is not modified very often in order to save some bandwidth and to speed up your application.
Also if you have multiple field it may be better to overwrite the __getattr__ method instead of defining separate one for each property that you need to pull from the outer application.
P.S. Thanks to Miga for the code error report.
Published at July 14, 2011
| Tagged with:
Python
,
Django
,
django-forms
,
django-cms
,
django-admin
,
django-models
,
usability
,
Development
,
Django CMS
... how to make usable drop-downs with Django CMS pages
Problem: some times when you create custom applications or plugins for Django CMS you need a property that connects the current item to a page in the CMS. Nothing simple than this - you just add a ForeignKey in your model that points to the Page model and everything is (almost)fine. Example:
from cms.models import Page
class MyModel(models.Model):
# some model attributes here
page = models.ForeignKey(Page)
If you registered your model in Django admin or just add a model form to it you will see something like this:

Cool right? Not exactly. The problem is that these pages are in hierarchical structure and listing them in a flat list may be/is little confusing. So let's indent them accordingly to their level in the hierarchy.
Solution: The easies way to achieve this indentation is to overwrite the choices list of the ForeignKey field in the ModelForm __init__ method.
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyModelForm, self).__init__(*args, **kwargs)
choices = [self.fields['page'].choices.__iter__().next()]
for page in self.fields['page'].queryset:
choices.append(
(page.id, ''.join(['-'*page.level, page.__unicode__()]))
)
self.fields['page'].choices = choices
The magic lies between lines 7 and 11, on line 7 we create a list with one element the default empty option for the drop down. The need to use "__iter__().next()" comes from the fact that the choices attribute of the fields is django.forms.models.ModelChoiceIterator object which is iterable, but not indexable i.e. you can not just use self.fields['url'].choices[0].
After we had the empty choice now it is time to add the real ones, so we iterate over the queryset(8th line) that holds them and for each item we add a tuple to our choices list(10). The first item of the tuple is the page id - nothing special, but the second one... here the python magic comes. We multiple the minus sign('-') by the page level and join the result with the page title. The only thing left is to replace the field choices(line 12) and here is the result:

Final words: For me this is much more usable than the flat list. Of course you can modify the queryset to return only published pages or filter the results in other way and still use the identation code from above.
I'll be happy to hear your thoughts on this.
Published at June 1, 2011
| Tagged with:
Python
,
Django
,
django-forms
,
dynamic values
,
django-admin
,
django-models
,
ForeignKey
,
Development
... or how to limit dynamic foreign key choices in both edit drop-down and admin filter.
The problem: Having a foreign key between models in django is really simple. For example:
class Question(models.Model):
# some fields here
class Answer(models.Model):
# some fields here
question = models.ForeignKey(Question)
Unfortunately in the real live the choices allowed for the connection are frequently limited by some application logic e.g. you may add answers only to questions created by you. In some simple(rare) cases this can be easy achieved using choices or limit_choices_to attributes in the models.ForeignKey call.
In the case of choices you just have to pass list/tuple each element of which contains the value to be stored and human readable name for the choice. Unfortunately this one is computed on server run and is not updated with new items during run-time.
If you use limit_choices_to you may pass to it some kind of filter expression e.g. limit_choices_to = {'pub_date__lte': datetime.now} but this not always can do the job.
Speciality: So if you want dynamic choices in the admin drop down you have to write a method that will return list with options and bind it to the form(as shown in Django forms ChoiceField with dynamic values…) which is used by admin.
This will work great but if you decided to add this column in admin`s list_filter you will see all element from the connected model in filter. How to limit them to the same list used for the form choices?
Solution: The simplest solutions is to extend RelatedFilterSpec, overwrite its default choices and add a single row to the model:
from django.contrib.admin.filterspecs import FilterSpec, RelatedFilterSpec
class CustomFilterSpec(RelatedFilterSpec):
def __init__(self, *args, **kwargs):
super(CustomFilterSpec, self).__init__(*args, **kwargs)
self.lookup_choices = get_questions() #this method returns the dynamic list
FilterSpec.filter_specs.insert(0, (lambda f: bool(f.rel and hasattr(f, 'custom_filter_spec')), CustomFilterSpec))
class Answer(models.Model):
# some fields here
question = models.ForeignKey(Question)
question.custom_filter_spec = True # this is used to identify the fields which use the custom filter
Final word: The solutions is pretty simple and really easy to implement but should be used carefully. If your filtering method(in my case get_questions) is slow/resource consuming it may bring you troubles. Here is the place where and you should think about caching it. This is a place where a application cache can be used. Hope this will help you as much as it helped me.
Published at Jan. 6, 2011
| Tagged with:
Django
,
django-forms
,
ChoiceField
,
template tags
,
Development
... or what to do in case that you need a special design for your choice fields
The problem: Few posts ago I talked(wrote) about Django forms ChoiceField and with dynamic values and now it is time to take a look at the front end and how we display these values to the user. I will use the code from that post:
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=MY_CHOICES)
By default Django provide us with a simple drop-down list as visual representation of the choice field. Just create and instance of the form in your view, pass it in the context:
def my_view(request):
form = MyForm()
return render_response('template.html',{'form': form})
and then display it in the template using {{form.my_choice_field}}.
Speciality: For most cases this drop-down works just fine but sometimes this is not enough. Lets say that instead of drop-down list we need a radio buttons. There are two ways to achieve this - using a custom widget or playing with the template tags and the ChoiceField object. The first solutions is more suitable if you have a repeatable interface for several fields. In my case this was field specific so I chose the second one as faster for implementation.
Solution: You can access the field object and its choices calling the field respectively field.choices properties of the form element in the template. Here is an example
<ul>
{% for choice in form.my_choice_field.field.choices %}
<li>
<input type="radio" name="my_choice_field" value="{{choice.0}}"
{% ifequal form.my_choice_field.data choice.0 %}
checked="checked"
{% endifequal %}/>
<label for="">{{choice.1}}</label>
</li>
{% endfor %}
</ul>
This allows you to specify custom styles/HTML for every element and also to distinct first and last elements using forloop.first and forloop.last - for more information you can check Django documentation about the for template tag
Final words: I did not have the chance to measure the speed difference between these two methods I mentions but I intend to post a also an example of the first one(using custom widget) and a "benchmark" between them both. If someone has already done this please post the results and your opinion about this.
Published at Dec. 5, 2010
| Tagged with:
Python
,
Django
,
django-forms
,
dynamic values
,
ChoiceField
... or how to get a dynamic drop-down list with Django forms
The problem: Lets say that you need a form with a drop-down list that have dynamic values. With Django this can be done simple and fast, but if you are new you may get yourself into a trap. In a standard form(with static values in the drop-down) your code will be something like this:
MY_CHOICES = (
('1', 'Option 1'),
('2', 'Option 2'),
('3', 'Option 3'),
)
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=MY_CHOICES)
So if you want the values to be dynamic(or dependent of some logic) you can simply modify your code to something like this:
def get_my_choices():
# you place some logic here
return choices_list
class MyForm(forms.Form):
my_choice_field = forms.ChoiceField(choices=get_my_choices())
and here you will fail(not absolutely). This is a common mistake and sooner or later you will see what you messed but it my be too late.
Speciality: the trick is that in this case my_choice_field choices are initialized on server (re)start. Or in other words once you run the server the choices are loaded(calculated) and they will not change until next (re)start. This mean that your logic will be executed only once. This will be OK if your logic is server specific(depends from server settings) or "semi-dynamic" in any other way. But you need this list to be updated on every form load you will need to use something the form __init__ method.
Solution: fortunately the form`s class has an __init__ method that is called on every form load. Most of the times you skipped it in the form definition but now you will have to use it.
def get_my_choices():
# you place some logic here
return choices_list
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['my_choice_field'] = forms.ChoiceField(
choices=get_my_choices() )
You first call the __init__ method of the parent class(Form) using the super keyword and then declare your dynamic fields(in this case my_choice_field). With this code get_my_choices is called on every form load and you will get your dynamic drop-down.
Final words: have in mind that this method also have one strong drawback. If your application have a heavy load, executing a logic on every form load may(will) bring you troubles. So some caching of the form or the logic result may be useful.
And remember If you have other approach, idea or question I am always ready to hear it.