首页 > 解决方案 > 创建返回过滤对象的 django api 视图

问题描述

问题描述
我是 django-rest-framework 的新手,在我看来遇到了问题。我有三个模型,即#User、#Profession 和#StudentProfessions。我需要创建一个将 user_id 作为请求参数并返回属于特定 user_id 的所有职业的列表的 api-view。

这是我的代码

职业应用>>模型.py

from django.db import models

class Profession(models.Model):
    profession_name = models.CharField(max_length=100)

    def __str__(self):
        return self.profession_name

用户模型

我使用了 django 默认模型。

student_profile_app >> models.py


from django.contrib.auth.models import User
from department_app.models import Department
from profession_app.models import Profession
from program_app.models import Program
from django.db import models

class StudentProfile(models.Model):
    student_status = models.BooleanField()
    phone_number = models.CharField(max_length=100)
    year_of_study = models.CharField(max_length=100)
    program_id = models.ForeignKey(Program, on_delete=models.CASCADE)
    student_id = models.OneToOneField(User, on_delete=models.CASCADE, related_name="student_id")
    organization_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="organization_id")
    profile_image = models.ImageField(upload_to='images/', blank=True)
    field_supervisor_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="field_supervisor")
    department_id = models.ForeignKey(Department, on_delete=models.CASCADE)
    academic_supervisor_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="academic_supervisor")

    def __str__(self):
        return f'{self.student_id.username } Profile'


class StudentProfession(models.Model):
    student_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="student_profession_id")
    profession_id = models.ForeignKey(Profession, on_delete=models.CASCADE)

    def __str__(self):
        return f'{self.student_id.username } Profession' 

student_profile_app >> views.py

from .models import StudentProfile, StudentProfession

def getStudentProfessions(request, studentId):
    professions = StudentProfession.objects.filter(student_id=studentId)
    return professions

在我的网址中

from student_profile_app.views import getStudentProfessions
from rest_framework import routers

router.register('getStudentProfessions/<int:studentId>', getStudentProfessions, 'getStudentProfessions')

urlpatterns = router.urls

但是当我运行服务器时出现以下错误

    urlpatterns = router.urls
  File "E:\Codes\FIP\fipEnv\lib\site-packages\rest_framework\routers.py", line 77, in urls
    self._urls = self.get_urls()
  File "E:\Codes\FIP\fipEnv\lib\site-packages\rest_framework\routers.py", line 338, in get_urls
    urls = super().get_urls()
  File "E:\Codes\FIP\fipEnv\lib\site-packages\rest_framework\routers.py", line 236, in get_urls
    routes = self.get_routes(viewset)
  File "E:\Codes\FIP\fipEnv\lib\site-packages\rest_framework\routers.py", line 152, in get_routes
    extra_actions = viewset.get_extra_actions()
AttributeError: 'function' object has no attribute 'get_extra_actions'

标签: pythondjango-rest-framework

解决方案


首先,StudentProfession.student_id有错误的模型参数集(它与用户模型有关 - 它应该是学生模型)。

Django rest 框架使用视图集作为路由器。您需要的是序列化程序,它将代表您的端点 api 结构和视图集

我将为您编写简单的序列化程序和视图集,但您确实需要阅读文档。

评论编辑后:

序列化器类:

from rest_framework import serializers
#...other imports

class StudentProfessionSerializer(serializers.ModelSerializer):
    class Meta:
        model = StuedentProfession
        fields = ('profession')

Viewset 类(这就是您在路由器中注册的内容!)

from rest_framework import viewsets, mixins
#...other imports

class StudentProfessionViewSet(viewsets.GenericViewSet,
                               mixins.ListModelMixin,
                               mixins.RetrieveModelMixin):
    serializer_class = StudentProfessionSerializer
    queryset = StudentProfession.objects

    def get_queryset(self):
        student_id = self.kwargs.get('studentId')
        return self.queryset.filter(student_id=student_id)

我的一些提示:

  • 阅读文档

  • 您不需要在 ForeignKey 字段中编写“_id”后缀(django 会自动使其处于底层 - 意味着您的表中的列无论如何都会有 _id 后缀),然后您可以使用没有这个丑陋的 _id 的参数......就像这样

     StudentProfession.objects.filter(student=somestudentid)
    
  • 你的 API 应该像这样构造

     router.register(r'students/(?P<studentId>\d+)/professions', StudentProfessionViewSet, 'student-profession')
    
  • 尽量不要在 url 中使用对象的“真实”ID - 改用 UUID - 它更安全


推荐阅读