Как сделать related_name для модели пользователя в Django? Я хочу запросить имя пользователя из другой модели

django-rest-framework

#django-rest-framework

Вопрос:

Цель состоит в том, чтобы показать уроки, которые были вставлены только текущим пользователем, а именно: user_author_lesson. user_author_lesson на самом деле является внешним ключом к модели пользователя. Я хочу запросить поле имени пользователя в наборе запросов сериализатора. Или, может быть, есть другой способ реализовать это. Спасибо.

Модели

 from django.contrib.auth.models import User
# from django.utils import timezone
from datetime import date


class Student(models.Model):

   
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    information = models.TextField(blank=True)
    user_author_student = models.ForeignKey(
        User, null=True, on_delete=models.CASCADE)
    objects = models.Manager()  # default manager


    class Meta:
        ordering = ('-first_name',)

    def __str__(self):
        return self.first_name


class Lesson(models.Model):

 
    options = (
        ('paid', 'Paid'),
        ('not paid', 'Not Paid'),
    )
    student = models.ForeignKey(
        Student, on_delete=models.CASCADE, related_name='lessons')
    paid = models.CharField(
        max_length=10, choices=options, default='not paid')
    title = models.CharField(max_length=50)
    task1 = models.CharField(max_length=50)
    description1 = models.TextField(blank=True)
    task2 = models.CharField(max_length=50)
    description2 = models.TextField(blank=True)
    user_author_lesson = models.ForeignKey(
        User, null=True, on_delete=models.CASCADE)
    lesson_date = models.DateField(default=date.today, null=False)
    objects = models.Manager()  # default manager
   
    class Meta:
        ordering = ('-lesson_date',)

    def __str__(self):
        return '%s: %s %s %s' % (self.student, self.title, self.lesson_date, self.paid)
 

число просмотров

 from django.http import request
from rest_framework import generics
from rest_framework.serializers import Serializer
from private_models.models import Lesson, Student
from .serializers import LessonSerializer, LessonDetailSerializer, StudentDetailSerializer, StuSerializer, CreateLessonSerializer,DeleteLessonSerializer
from rest_framework.permissions import SAFE_METHODS, DjangoModelPermissions, BasePermission, AllowAny
from django.shortcuts import get_object_or_404


class LessonUserWritePermission(BasePermission):
    message = 'editing lesson is restricted to the authors only'

    def has_object_permission(self, request, view, obj):
        if request.method in SAFE_METHODS:
            return True

        return obj.user_author_lesson == request.user


class LessonList(generics.ListCreateAPIView):
   
    # permission_classes = [DjangoModelPermissions]
    permission_classes = [AllowAny]
    queryset = Lesson.objects.all()
    
    #queryset = Lesson.objects.filter(user_author_lesson=request.user.username).all()
    
    serializer_class = LessonSerializer
    #print(self.request.user)
    #def get_queryset(self):
    #    print(queryset.objects.filter(user_author_lesson=self.request.user))
    #    return Lesson.objects.filter(user_author_lesson=).all()


class StuDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [AllowAny]

    queryset = Student.objects.all()
    serializer_class = StudentDetailSerializer
    # def get_object(self, queryset=None, **kwargs):
    #     item = self.kwargs.get('pk')
    #     return get_object_or_404(Student, pk=item)


class StuList(generics.ListCreateAPIView):
    # permission_classes = [DjangoModelPermissions]
    permission_classes = [AllowAny]
    queryset = Student.objects.all()
    serializer_class = StuSerializer


class LessonDetail(generics.RetrieveUpdateDestroyAPIView):
    # class LessonDetail(generics.RetrieveUpdateDestroyAPIView, LessonUserWritePermission):
    # the above line is to use when i fix the user permissions!!!
    # permission_classes = [LessonUserWritePermission]
    permission_classes = [AllowAny]
    queryset = Lesson.objects.all()
    serializer_class = LessonDetailSerializer


class CreateLesson(generics.CreateAPIView):
    permission_classes = [AllowAny]
    queryset = Lesson.objects.all()
    serializer_class = CreateLessonSerializer

class DeleteLesson(generics.DestroyAPIView):
    permission_classes =[AllowAny]  
    queryset = Lesson.objects.all()
    serializer_class = DeleteLessonSerializer

 

сериализаторы

 from rest_framework import serializers, fields
from private_models.models import Lesson, Student



class LessonSerializer(serializers.ModelSerializer):
    student = serializers.SerializerMethodField()
    user_author_lesson = serializers.StringRelatedField(read_only=True)

    # def __init__(self, *args, **kwargs):
    #     super().__init__(*args, **kwargs)

    #     try:
    #         if self.context['request'].method in ['GET']:
    #             self.fields['student'] = serializers.SerializerMethodField()
    #     except KeyError:
    #         pass

    class Meta:
        model = Lesson
        fields = ('id', 'student', 'title', 'lesson_date',
                  'paid', 'user_author_lesson')

    def get_student(self, obj):
        
        return obj.student.first_name

    def post():
        pass    


class LessonDetailSerializer(serializers.ModelSerializer):
   
    class Meta:
        model = Lesson
        fields = ('id', 'student', 'title', 'task1', 'description1',
                  'task2', 'description2', 'lesson_date', 'paid',)


class StudentDetailSerializer(serializers.ModelSerializer):
    lessons = LessonSerializer(many=True, read_only=True)

    class Meta:
        model = Student

        fields = ('first_name', 'last_name', 'information', 'lessons')


class StuSerializer(serializers.ModelSerializer):
    user_author_student = serializers.StringRelatedField(read_only=True)

    class Meta:
        model = Student
        # lessons = LessonDetailSerializer(many=True)
        fields = ('id', 'first_name', 'last_name',
                  'information', 'user_author_student')


class CreateLessonSerializer(serializers.ModelSerializer):
    # student = serializers.SerializerMethodField()
    student_id = serializers.IntegerField(write_only=False)

    class Meta:
        model = Lesson
        fields = ('student_id', 'title', 'task1', 'description1',
                  'task2', 'description2', 'lesson_date', 'paid',)

class DeleteLessonSerializer(serializers.ModelSerializer):
      class Meta:
          model = Lesson
          fields =('student_id', 'title', 'task1', 'description1',
                  'task2', 'description2', 'lesson_date', 'paid',)                
 

Ответ №1:

Напишите LessonsViewset и определите метод get_queryset следующим образом:

 class LessonViewsets(viewsets.ModelViewset):
    queryset = Lesson.objects.all()
    serializer_class = LessonSerializer
    permission_classes = []

    def get_queryset(self, *args, **kwargs):
        super().get_queryset()
        student_id = Student.objects.get(
        users_lessons = Lesson.objects.select_related.("student").filter(student=self.request.user.id)
        return users_lessons
 

Наборы представлений из DRF очень эффективны. Однако вы можете использовать ListCreateAPIView; просто определите метод get_queryset, чтобы возвращать только уроки, связанные с аутентифицированным пользователем.

Комментарии:

1. Спасибо. Итак, мне нужно создать класс UserSerializer?

2. Простите, это должны быть LessonSerializers, а не UseeSerializer. Вы знаете, как настроить сериализатор? Дайте мне знать

3. мой get_queryset должен фильтровать user_author_lesson, и я не смог его реализовать, потому что внешний ключ не имеет related_name .

4. Я вижу. Затем сделайте это: перейдите к модели вашего урока; в вашем уроке user_author выполните: user_author урок = модели. ForeignKey(User, related_name=»урок», on_delete=модели. КАСКАД)

5. текущий пользователь — это user_author_lesson, и я хочу отображать только его вставки данных, означающие введенные им уроки. Студенты не имеют значения. Итак, я попытался создать get_queryset, но как его отфильтровать? (Я привык к flask ..) Я не могу фильтровать по user_author_lesson, потому что он ничего не возвращает и говорит, что ожидает целое число, если я помню.

Ответ №2:

Существует более простой способ выполнения обратных запросов.

По умолчанию django позволяет выполнять обратные запросы, используя имена, связанные с умолчанию, которые есть <ModelName>_set .

например, если вы хотите fetch all the lessons против некоторых user .

user_instance.lesson_set.all()

Попробуйте переписать LessonList класс View как:

 class LessonList(generics.ListCreateAPIView):
   
    # permission_classes = [DjangoModelPermissions]
    permission_classes = [AllowAny]
    queryset = Lesson.objects.all()
    
    serializer_class = LessonSerializer

    def get_queryset(self, *args, **kwargs):
        return self.request.user.lesson_set.all()
 

В документации Django есть более полезные примеры.

Комментарии:

1. Спасибо. Я попробую. Я также столкнулся с функцией preform_create, которая, я думаю, мне нужна для определения пользователя, который вошел в урок.