Reputation: 1234
I have used django rest api to create an api that looks like this -
{
"count": 2,
"next": null,
"previous": null,
"results": [
{
"url": "http://127.0.0.1:8000/app/student/1/",
"id": 1,
"title": "mr",
"name": "student1",
"address": "somewhere",
"city": "Mumbai",
"tests": [
{
"test_name": "Math",
"section_1": "34",
"section_2": "54",
"date_added": "2015-12-15"
}
]
},
{
"url": "http://127.0.0.1:8000/app/student/2/",
"id": 2,
"title": "mr",
"name": "student2",
"address": "somewhere",
"city": "Delhi",
"tests": [
{
"test_name": "English",
"section_1": "34",
"section_2": "65",
"date_added": "2015-12-15"
}
]
}
]
}
I have another app in the same project the uses this data using something like this -
def Peoplelist(request):
data= requests.get('http://127.0.0.1:8000/app/students/').json()
send_list = []
for i in range(2):
send_list.append(data['results'][i]['name'])
context = RequestContext(request, {
'send_list': send_list,
})
return render_to_response('taskmanager/numbers.html', context)
which creates a list of the student names.
I want to display a list of student names depending on the city name and then click on the names to view the student and test details. Can't figure out how to do that. Can someone suggest a way?Thanks.
models.py
class Test(models.Model):
date_added = models.DateField(default=datetime.datetime.now)
test_name = models.CharField(max_length=200,default='',blank=False)
section_1 = models.CharField(max_length=100,default='')
section_2 = models.CharField(max_length=100,default='')
def __str__(self):
return self.test_name
class Person(models.Model):
tests = models.ManyToManyField(Test)
title = models.CharField(max_length=3,default="mr",blank=False)
name = models.CharField(max_length=50,default='',blank=False)
address = models.CharField(max_length=200,default='',blank=False)
city = models.CharField(max_length=100,default='',blank=False)
def __str__(self):
return self.name
serializers.py
class TestSerializer(serializers.ModelSerializer):
class Meta:
model = Test
fields = ('test_name','section_1','section_2','date_added')
class PersonSerializer(serializers.HyperlinkedModelSerializer):
tests = TestSerializer(many=True, read_only=True)
class Meta:
model = Person
fields = ('id','title', 'name', 'address', 'city','tests')
numbers.html
{% extends "index.html" %}
{% block names %}
{% for list in send_list %}
<a href="/"><p>{{list}}</p></a>
{% endfor %}
{% endblock %}
******************************EDIT*************************
models.py
class City(models.Model):
city_name=models.CharField(max_length=100,default='',blank=False)
def __str__(self):
return self.city_name
class Person(models.Model):
tests = models.ManyToManyField(Test)
title = models.CharField(max_length=3,default="mr",blank=False)
name = models.CharField(max_length=50,default='',blank=False)
address = models.CharField(max_length=200,default='',blank=False)
city = models.CharField(max_length=100,default='',blank=False)
views.py
class StudentList(generics.ListCreateAPIView):
queryset = Person.objects.all()
serializer_class = PersonSerializer
class CityList(generics.ListCreateAPIView):
queryset = City.objects.all()
serializer_class = CitySerializer
class CityDetail(generics.ListCreateAPIView):
city = City.objects.all()
serializer_class = CitySerializer
class StudentDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer
Upvotes: 1
Views: 1822
Reputation: 213193
So basically you need 3 different APIs:
/cities/
- Gives you list of cities./cities/<pk>/students
- Gives you list of students in given city./students/<pk>/
- Gives details of Student with id pk
.So, that single API is not going to handle all 3 pages you want.
You'll need 3 template views:
def cities(request):
data = requests.get('http://127.0.0.1:8000/app/cities/').json()
context = RequestContext(request, {
'cities': data.cities,
})
return render_to_response('taskmanager/cities.html', context)
def Peoplelist(request, pk):
data = requests.get('http://127.0.0.1:8000/app/cities/' + pk + '/students/').json()
context = RequestContext(request, {
'students': data.students,
})
# Better rename this one to students.html
return render_to_response('taskmanager/numbers.html', context)
def student_details(request, pk):
data = requests.get('http://127.0.0.1:8000/app/students/' + pk).json()
context = RequestContext(request, {
'student': data.student,
})
return render_to_response('taskmanager/student_detail.html', context)
Configure the urls for these views. Now the templates would be like:
{% extends "index.html" %}
{% block names %}
{% for city in cities %}
<a href="{% url 'student_list' city.id %}"><p>{{city.name}}</p></a>
{% endfor %}
{% endblock %}
{% extends "index.html" %}
{% block names %}
{% for student in students %}
<a href="{% url 'student_detail' student.id %}"><p>{{student.name}}</p></a>
{% endfor %}
{% endblock %}
{% extends "index.html" %}
{% block names %}
{{ student.name }}
<table>
<tr>
<th>Test Name</th>
<th>Section 1</th>
<th>Section 2</th>
<th>Date Added</th>
</tr>
{% for test in student.tests %}
<tr>
<td>{{ test.test_name }}</td>
<td>{{ test.section_1 }}</td>
<td>{{ test.section_2 }}</td>
<td>{{ test.date_added }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
Modification in models:
Since you've now a City
model, you can change the city
field to ForeignKey
in Person
model. Also, let's rename Person
to Student
:
class Student(models.Model):
# Removing the tests field. Rather add `student` field in `Test` model
# tests = models.ManyToManyField(Test)
title = models.CharField(max_length=3,default="mr",blank=False)
name = models.CharField(max_length=50,default='',blank=False)
address = models.CharField(max_length=200,default='',blank=False)
city = models.ForeignKey(City)
then change the Test
model:
class Test(models.Model):
student = models.ForeignKey(Student)
date_added = models.DateField(default=datetime.datetime.now)
test_name = models.CharField(max_length=200,default='',blank=False)
section_1 = models.CharField(max_length=100,default='')
section_2 = models.CharField(max_length=100,default='')
def __str__(self):
return self.test_name
For views:
/cities/
- For this CityList
view in your code is fine./cities/<pk>/students/
- For this, change your StudentList
view like this:
class StudentList(generics.ListCreateAPIView):
serializer_class = PersonSerializer
def get_queryset(self):
city = City.objects.get(pk=self.kwargs.get('pk', None))
students = Student.objects.filter(city=city)
return students
And then for last one:
/students/<pk>/
- StudentDetail
view would be like:
class StudentDetail(generics.RetrieveAPIView):
serializer_class = PersonSerializer
def get_object(self):
student_id = self.kwargs.get('pk', None)
return Student.objects.get(pk=student_id)
Now for serializers, change your PersonSerializer
to this one:
class StudentSerializer(serializers.ModelSerializer):
test_set = TestSerializer(many=True, required=False)
class Meta:
model = Student
fields = ('id','title', 'name', 'address', 'city', 'test_set')
Upvotes: 3
Reputation: 10609
If I correctly understand, you want to have hyperlink for students in your api response. Inorder to this add the following in serializer.py:
class StudentByCityField(serializers.RelatedField):
def to_representation(self, city):
student_list = self.objects.filter(city=city)
link_list = list()
append_link = link_list.append
for student in student_list:
append_link("/app/students/%s" % student.name)
return link_list
class PersonByCitySerializer(serializers.ModelSerializer):
city_name = StudentByCityField(source='city', read_only=True)
class Meta:
model = Test
fields = ('city_name',)
But in case you want to do this HTML side this will be trivial
def get_cities(request):
pesrons = Person.objects.all()
pesrons.query.group_by = ['city']
city_set = set([i.city for i in persons])
context = RequestContext(request, {
'city_list': list(city_set),
})
return render_to_response('cities.html', context)
def get_students_by_city(request, city):
student_list = Person.objects.filter(city=city)
context = RequestContext(request, {
'students': student_list,
})
# Better rename this one to students.html
return render_to_response('students_by_city.html', context)
def get_student_details(request, id):
student = Person.objects.get(id=id)
context = RequestContext(request, {
'student': student,
})
return render_to_response('student_detail.html', context)
cities.html
{% extends "index.html" %}
{% block names %}
<ul>
{% for city in city_list %}
<li><a href="{% url 'student_by_city' city.name %}">
{{city.name}}
</a></li>
{% endfor %}
</ul>
{% endblock %}
students_by_city.html
{% extends "index.html" %}
{% block names %}
<ul>
{% for student in student_list %}
<li><a href="{% url 'student_detail' student.id %}"><p>{{student.name}}</p></a></li>
{% endfor %}
</ul>
{% endblock %}
student_detail.html
{% extends "index.html" %}
{% block names %}
<!-- Display here your data as you like -->
{% endblock %}
urlpatterns = patterns('',
url(r'^app/cities/$', views.get_cities, name="participant-register"),
url(r'^app/students/(?P<id>\d+)$', views.get_student_by_city, name="student_by_city"),
url(r'^app/student/(?P<city>\w+/$', views.get_student_detail, name="student_detail"),
)
Upvotes: 1