Reputation: 341
I'm trying to make a search function that allows me to enter the value of an object in an instance so I can display that instance and several of it's objects on the same page as the search page. Here's what I have so far:
#models.py
class Student(models.Model):
# STEP 1 BASIC INFO
student_id = models.CharField(max_length=128, unique=True)
first_name = models.CharField(max_length=128)
last_name = models.CharField(max_length=128)
ssn = USSocialSecurityNumberField(null=False)
gender = models.CharField(max_length=128, choices=GENDER_CHOICES)
dob = models.DateField(auto_now=False, auto_now_add=False, db_column="date of birth")
contact_number = models.CharField(max_length=128)
address = models.CharField(max_length=128)
city = models.CharField(max_length=128)
state = USStateField(choices=STATE_CHOICES, default='NJ')
zipcode = USZipCodeField(blank=True)
country = CountryField(default='US', blank=True)
home_phone = models.CharField(max_length=128)
cell_phone = models.CharField(max_length=128)
email = models.EmailField(max_length=254, validators=[validate_email])
def __str__(self):
return self.first_name + self.last_name
#views.py
def search_Student(request):
context_dict = {}
if request.method == 'POST':
query = request.POST['last_name_search']
results = Student.objects.filter(last_name=query)
if query:
context_dict['results'] = results
else:
context_dict['no_results'] = query
return render(request, "students/search_student.html", context_dict)
#search_student.html
{% block main_content %}
<form method="post" action="/students/search_student/">
{% csrf_token %}
<label for="last_name_search">Last Name:</label>
<input type="text" name="last_name_search" id="last_name_search">
<input type="submit" name="submit">
</form>
<div id="result_panel">
{% if no_results %}
No results returned for <q>{{ no_results }}</q>
{% else %}
{% for result in results %}
{{ result.last_name }}
{% endfor %}
{% endif %}
</div>
{% endblock %}
#urls.py
urlpatterns = [
url(r'^$', students_views.Students, name='students'),
url(r'^add_student/$', students_views.add_Student, name='add_student'),
url(r'^id=(?P<identify>[\w]+)/add_studentcourse/$', students_views.add_StudentCourse, name='add_studentcourse'),
url(r'^id=(?P<identify>[\w]+)/add_studentemployment/$', students_views.add_StudentEmployment, name='add_studentemployment'),
url(r'test/$', students_views.test, name='test'),
#URL for the search page.
url(r'^search_student/$', students_views.search_Student, name='search_student'),
url(r'^current_student/$', students_views.current_Student, name='current_student'),
url(r'^all_my_student/$', students_views.all_My_Student, name='all_my_student'),
url(r'^public_student/$', students_views.public_Student, name='public_student'),
url(r'^sales_reports/$', students_views.sales_Reports, name='sales_reports'),
url(r'^switch_counselor/$', students_views.switch_Counselor, name='switch_counselor'),
url(r'^source_admin/$', students_views.source_Admin, name='source_admin'),
url(r'^super_tool/$', students_views.super_Tool, name='super_tool'),
url(r'^help_and_settings/$', students_views.help_And_Settings, name='help_and_settings'),
]
Basically, if I type in a last name in the input, I want it to be able to grab all model instances that have a last name equal to that, and to be able to put any information I want about all the matching instances, like the name, gender, and address on the exact same page as the search. The POST method may be confusing, but someone insists that I do this (It didn't work when I changed the method to GET either). Could someone please point out any errors or missing pieces in my code? Thanks.
Edit: Added the urls.py.
Upvotes: 0
Views: 1185
Reputation:
View Source
in the browser to make sure nothing is returned, as opposed to the div being hidden by CSS or JS.views.py
if query:
results = Student.objects.filter(last_name=query)
if results.count():
context_dict['results'] = results
else:
context_dict['no_results'] = query
template
<div id="result_panel">
{% if no_results %}
No results returned for <q>{{ no_results }}</q>
{% else %}
{% for result in results %}
{{ result.last_name }}
{% endfor %}
{% endif %}
</div>
Note that the above cannot ever be empty. It should always show something. If it does not, it is a display error and the data is there. See point 2.
If it shows the "no results" part, then try to replicate the query in the django shell:
python manage.py shell
>>> from yourapp.models import Student
>>> Student.objects.filter(last_name='what you typed')
>>> Student.objects.filter(last_name__iexact='what you typed')
>>> Student.objects.filter(last_name__icontains='what you typed')
>>> Student.objects.count()
If none of the first three returns results, then you made a typo or number 4 will show you have no students.
Upvotes: 1
Reputation: 16666
Of course you can use a view method and try to find the error in your custom search and template code.
OR you can do it in a more Django way, relying on pre-built features of Django:
Use Django's ListView
to query on and display the Student Model objects. You get paging, error handling, context setup for free with this. See other StackOverflow questions like https://stackoverflow.com/a/33350839/621690 for example code.
Your code that filters the Students would go into get_queryset
- or you can use django-filter.
For nice usability, you can add Select2 to your form input which allows autocomplete/lookahead. See django-select2
Upvotes: 0
Reputation: 73
SO won't let me comment quite yet, so here to say that you can indeed (and are) supposed to treat dicts like a list in django templating seen here.
Can you please post your error? I'm not sure I'm seeing whats wrong. Your method adapts over to my code just fine, so I'm a bit lost.
Editing for formatting:
You should maybe make a compile time dictionary, IE:
context_dict = {
"results": results
}
return render(request, "students/search_student.html", context_dict)
Make sure to return in the if, so the scope is in the proper place, and if your if finds nothing return a variable saying so.
If you're bent on sticking to your answer, trying referencing it in the template as so..
{% for result in results.results %}
Your dictionary has a results entry, that points to the variable results. I believe you are iterating through the dictionary in your current example, as opposed to all the queries.
Upvotes: 0