NickBraunagel
NickBraunagel

Reputation: 1599

Django faster loading of form

I have a model named Title, which contains some ForeignKey fields:

class Title(models.Model):
    name = models.CharField(max_length=120)
    department = models.ForeignKey('Department')
    rank = models.ForeignKey('Title_rank')

I have a form that has parameter choices set to all of the Title entries:

class Emp_titleForm(forms.Form):

    title = forms.MultipleChoiceField(
                choices=( (x.id, x.department.name + " - " + x.name) for x in Titles.objects.all() ),
                widget=forms.SelectMultiple(),
                required=True,
            )

The page loads fine but is slow (~6-10sec) from (I assume) there being many objects in the Title class (currently ~5,000).

Is there anyway to adjust my form or model to speed up page load? Unfortunately, filtering to reduce choices is not an option. Also, note that I would like to display the department with the title (e.g.: "Dept - Title")

Upvotes: 0

Views: 332

Answers (2)

tatlar
tatlar

Reputation: 3176

The standard Django approach (not version dependent) to solving this is to create a property in your Title model:

class Title(models.Model):
    name = models.CharField(max_length=120)
    department = models.ForeignKey('Department')
    rank = models.ForeignKey('Title_rank')

    @property
    def department_name(self):
        return u'%s-%s' % (self.department, self.name)

You can then reference this directly in your form. Good luck.

UPDATE

As noted in the comments, you cannot perform lookups on model properties. You will first need to add this field to your model using the save() method, then you can do the filter:

class Title(models.Model):
    name = models.CharField(max_length=120)
    department = models.ForeignKey('Department')
    rank = models.ForeignKey('Title_rank')

    def save(self, *args, **kwargs):
        self.department_name = u'%s-%s' % (self.department, self.name)
        super(Title, self).save(*args, **kwargs)

Upvotes: 0

NS0
NS0

Reputation: 6096

(x.id, x.name) for x in Titles.objects.all()

Instead of looping over all Title objects, try a more efficient query:

Title.objects.values_list('id', 'name')

Edit:

To combine fields, assuming you are using Django 1.8+, you can do the following:

from django.db.models import Concat, Value
Title.objects.annotate(
    department_name=Concat('department__name', Value(' - '), 'name')
).values_lists('id', 'department_name')

Upvotes: 2

Related Questions