views:

55

answers:

2

I have a Django form that uses an integer field to lookup a model object by its primary key. The form has a save() method that uses the model object referred to by the integer field. The model's manager's get() method is called twice, once in the clean method and once in the save() method:

class MyForm(forms.Form):
    id_a = fields.IntegerField()

    def clean_id_a(user_id):
        id_a = self.cleaned_data['id_a']
        try:
            # here is the first call to get
            MyModel.objects.get(id=id_a)
        except User.DoesNotExist:
            raise ValidationError('Object does not exist')

    def save(self):
        id_a = self.cleaned_data['id_a']
        # here is the second call to get
        my_model_object = MyModel.objects.get(id=id_a)

        # do other stuff

I wasn't sure whether this hits the database two times or one time so I returned the object itself in the clean method so that I could avoid a second get() call. Does calling get() hit the database two times? Or is the object cached in the thread?

class MyForm(forms.Form):
    id_a = fields.IntegerField()

    def clean_id_a(user_id):
        id_a = self.cleaned_data['id_a']
        try:
            # here is my workaround
            return MyModel.objects.get(id=id_a)
        except User.DoesNotExist:
            raise ValidationError('Object does not exist')

    def save(self):
        # looking up the cleaned value returns the model object
        my_model_object = self.cleaned_data['id_a']

        # do other stuff
A: 

This query is not cached. get() calls never are. QuerySets on the other hand, are (sometimes) cached after the first evaluation.

Matthias Kestenholz
In that case, is the way I avoided the second call a good way to do it? Or is there a canonical Django way to do this?
hekevintran
with querysets all non-callable field values are cached, while the callable ones are not
Satoru.Logic
@Satoru.Logic What is a callable field value? How do you call a value?
hekevintran
A: 

No, the value wouldn't be cached. Your second example is the right way to go.

(The first snippet actually contains an error, in that nothing is returned from the clean method, so the id_a attribute would end up empty.)

Daniel Roseman