MiniGunnR
MiniGunnR

Reputation: 5800

How to filter queryset based on value of another model in Django?

I'm trying to make a simple search function. I'm using the User model and a UserProfile model with a OneToOne relationship. I've successfully managed to search by the username, first name and last name, all three field being in the User model. However, I want to filter by the fields present in UserProfile model, e.g. sex, age, location, etc.

views.py

def Home(request):
    query = request.GET.get('query', '')
    queryset = User.objects.none()
    if request.method == "GET":
        form = SearchForm(request.GET)
        if form.is_valid():
            if query != '':
                queryset = User.objects.filter(Q(username__icontains=query)
                                             | Q(first_name__icontains=query)
                                             | Q(last_name__icontains=query)).exclude(is_staff=True)
    else:
        form = SearchForm()
    return render(request, "main/home.html", {'form': form, 'queryset': queryset})

home.html

{% extends "base.html" %}

{% block body %}
    <h3>Home</h3>
    <p>
    <form method="get" action="">
        {{ form.as_p }}

        <input type="submit" value="Search"/>
    </form>
    </p>

    <p>
    {% for user in queryset %}
        <a href="{% url 'main:profile' user.id %}">{{ user.get_full_name }}</a> <br/>
    {% endfor %}
    </p>
{% endblock %}

forms.py

class SearchForm(forms.Form):
    query = forms.CharField(max_length=100, label="", widget=forms.TextInput(attrs={'placeholder': 'Search...'}), required=False)
    age_from = forms.IntegerField(label="", widget=forms.NumberInput(attrs={'placeholder': 'Age from'}), required=False)
    age_to = forms.IntegerField(label="", widget=forms.NumberInput(attrs={'placeholder': 'Age to'}), required=False)

models.py

UserProfile(models.Model):
    sex_choices = (
        ('Male', 'Male'),
        ('Female', 'Female'),
        ('Other', 'Other'),
    )
    sex = models.CharField(max_length=6,
                           choices=sex_choices,
                           default='Male')
    birth_date = models.DateField()

How can I include options to search based on other fields on UserProfile model which has a OneToOne relation with User model?

Upvotes: 1

Views: 3935

Answers (1)

Gocht
Gocht

Reputation: 10256

You need to use the related name.

As you haven't shared your models definition, let's suppose:

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    sex = models.CharField(...)
    ...

So, when you query:

User.objects.filter(user_profile_set__sex='female')

EDIT

To query based in age, given that you ask for an 'age' in your form and you store a birthdate in your model, you could try something like this:

from datetime import datetime
age = 18  # this shoudl come from form
birth_year = datetime.now().year - age
User.objects.filter(user_profile_set__birth_date__year=birth_year)

Upvotes: 3

Related Questions