【问题标题】:How to filter a User model with a ForeignKey using custom URL format如何使用自定义 URL 格式过滤带有 ForeignKey 的用户模型
【发布时间】:2019-02-18 05:14:24
【问题描述】:

预期的 URL 格式:

api/v1/users?applicant={applicantId}

当前(工作)URL 格式:

path('users/applicant/<int:pk>/')

如何使用申请人ID(与Users表有外键关系)检查申请人是否已经在系统上设置了用户帐户?

models.py:

class Applicant(models.Model):

     APPLICATION_STATUS = (
      (1, 'Pending'),
      (2, 'Accept'),
      (3, 'Reject'),
    )

    first_name = models.CharField(max_length=200, blank=False, 
    null=False)
    last_name = models.CharField(max_length=200, blank=False, 
    null=False)
    email = models.EmailField(max_length=200, blank=False, null=False, 
    unique=True)
    phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', 
    message="Phone number must be entered in the format: '+999999999'. 
    Up to 15 digits allowed.")
    phone_number = models.CharField(validators=[phone_regex], 
    max_length=17, blank=True, null=False, unique=True) # validators 
    should be a list
    linkedin_url = models.URLField(max_length=255, unique=True, 
    blank=True, null=True) #make sure diff users cant use two same 
    profile
    twitter_url = models.URLField(max_length=255, unique=True) #make 
    sure diff users cant use two same profile
    articles = ArrayField(models.URLField(), blank=False, null=False, 
    unique=True, size=3)
    country = models.ForeignKey(Country, on_delete=models.CASCADE, 
    blank=False, related_name="applicant")
    category = models.ForeignKey(Category, on_delete=models.CASCADE, 
    related_name="applicant", blank=False)
    status = models.CharField(max_length=200, 
    choices=APPLICATION_STATUS, default=1)

    def __str__(self):
        return self.first_name



 class User(AbstractUser):

     USER_TYPE_CHOICES = (
       (1, 'Journalist'),
       (2, 'Admin'),
     )

     GENDER = (
       (1, 'Male'),
       (2, 'Female')
      )

     first_name = models.CharField(max_length=200, blank=False)
     last_name = models.CharField(max_length=200, blank=False)
     # is_active = models.BooleanField(default=True)
     password = models.CharField(max_length=200)
     email = models.EmailField(max_length=250, unique=True)
     phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', 
     message="Phone number must be entered in the format: 
     '+999999999'. Up to 15 digits allowed.")
     phone_number = models.CharField(validators=[phone_regex], 
     max_length=17, unique=True, blank=False) # validators should be a 
     list
     user_type = models.CharField(max_length=200, 
     choices=USER_TYPE_CHOICES, default=1)
     category = models.ForeignKey(Category, on_delete=models.CASCADE, 
     related_name="users")
     # posts_url = ArrayField(models.URLField(), size=3)
     country = models.ForeignKey(Country, on_delete=models.CASCADE, 
     blank=True, related_name="users")
     gender = models.CharField(max_length=200, choices=GENDER)
     image_url = models.URLField(max_length=255)
     about = models.TextField()
     applicant = models.ForeignKey(Applicant, 
     on_delete=models.CASCADE, blank=True, null=True, 
     related_name="users")


    def __str__(self):
        return self.username

    class Meta:
        ordering = ("-date_joined",)

views.py:

class IdentifyUserApplicantID(generics.RetrieveAPIView):

    queryset = User.objects.all()
    serializer_class = ApplicantSerializer
    permission_classes = (IsAuthenticated,)

    # def get_queryset(self, pk):
    #   return Applicant.objects.get(id=pk)

    def get(self, request):

        data = request.data.get('pk')

        admin_user = User.objects.get(user_type=2)

        if request.user == admin_user:

            try:
                 queryset = User.objects.get(applicant=data)
                 serializer = UserSerializer(queryset)
                 return Response(jsend.success({'users': 
                 serializer.data}))

            except User.DoesNotExist:
                 return Response(jsend.success({'users': '[]'}))

         else:
             return Response((jsend.error("You are not authorized to 
             perform this action")),
                       status=status.HTTP_404_NOT_FOUND)

P.S:我检查了 django-filter 模块,但文档没有写清楚,有点难以理解。如果 django-filter 是实施该解决方案的推荐方式,如果在这方面做出更多说明,将很高兴。

【问题讨论】:

  • 不相关,但只有当您只能拥有一个管理员用户时,request.user == admin_user 才有意义。无论如何,只要做if request.user.user_type == 2就简单多了。
  • 感谢@DanielRoseman,是的,系统上有一个管理员用户。肯定会调查你的实现,看起来更干净。

标签: python django url filtering


【解决方案1】:

我不知道我是否理解你的问题,但你的意思是这样的:

if User.objects.filter(applicant__id=pk).exists():

【讨论】:

  • 是的......以及如何将其放入此 URL:api/v1/users?applicant={applicantId}。注意:我之前使用过类似的东西:re_path(r'^users/(?P )[0-9] $/', view.as_view ())
【解决方案2】:
path('api/v1/users', views.YOURVIEW.as_view())

在视图中

applicantId = request.GET.get('applicant', None)

【讨论】:

    【解决方案3】:

    关键是过滤查询参数,这里完成:http://www.django-rest-framework.org/api-guide/filtering/#filtering-against-query-parameters

    使用 request.query_params.get() 在 .get_queryset() 方法中通过 URL 获取用户查询...并在创建响应对象时将其作为查询集传递。

    我更新的views.py:

    class IdentifyUserApplicantID(generics.ListAPIView):
        serializer_class = UserSerializer
        permission_classes = [IsAuthenticated,]
        queryset = User.objects.all()
    
    def get_queryset(self):
        queryset = User.objects.all()
        applicant = self.request.query_params.get("applicant", None)
        if applicant is not None:
            queryset = queryset.get(applicant=applicant)
    
        return queryset
    
        def get(self, request):
    
            if request.user.user_type == "2":
                try:
                    queryset = self.get_queryset()
                    serializer = UserSerializer(queryset)
                    return Response(jsend.success({'user': serializer.data}))
    
                except User.DoesNotExist:
                    return Response(jsend.success({'user': '[]'}))
            else:
                return Response((jsend.error("You are not authorized to perform 
                this action")),status=status.HTTP_403_FORBIDDEN)
    

    我更新的 urls.py

    re_path(r'^users$', IdentifyUserApplicantID.as_view(), name="identify- 
            applicant"),
    

    示例查询:

    http://example.com/api/v1/users?applicant=2
    

    希望这会有所帮助。谢谢大家的回答。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 1970-01-01
      • 2019-05-05
      • 1970-01-01
      • 1970-01-01
      • 2017-07-20
      • 1970-01-01
      相关资源
      最近更新 更多