在模板Django Rest Framework中使用searializer字段

时间:2018-05-13 10:28:25

标签: django django-rest-framework

我是Django Rest Framework的新用户,并编写了第一个API应用程序。

我的 contacts / models.py

class Contact(models.Model):
    user_id = models.ForeignKey(User, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100, blank=True, null=True)
    date_of_birth = models.DateField(blank=True, null=True)

    class Meta:
        db_table = 'contacts'

    def full_name(self):
        return self.first_name + ' ' + self.last_name

    def __str__(self):
        return self.full_name()


class ContactEmail(models.Model):
    contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
    email = models.EmailField()
    primary = models.BooleanField(default=False)

    class Meta:
        db_table = 'contact_emails'

    def __str__(self):
        return self.email

联系人/ searializers.py

class ContactSerializer(serializers.HyperlinkedModelSerializer):
    primary_email = serializers.SerializerMethodField()

    class Meta:
        model = Contact
        fields = ('url', 'full_name', 'date_of_birth', 'primary_email')

    def get_primary_email(self, obj):
        primary_email = obj.contactemail_set.filter(primary=True).first()

        if primary_email:
            return primary_email.email

        return ''

联系人/ views.py

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,
                          IsOwnerOrReadOnly,)

    def perform_create(self, serializer):
        serializer.save(user_id=self.request.user)

class ContactList(APIView):
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'contacts/list.html'
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get(self, request):
        queryset = Contact.objects.all()
        return Response({'contacts': queryset})

ContactViewSet可以访问http://<ip>:<port>/api/contactsContactList可以访问http://<ip>:<port>/contacts

http://<ip>:<port>/api/contacts在json响应中提供了 primary_email ,但在 list.html {{ contact.primary_email }}

中没有使用任何内容

使用** APIView 时我不能使用Serializer字段吗?**

我是否需要重写ContactList()中的函数才能获取primary_email字段?

  

编辑2:contacts/list.html

{% for contact in contacts %}
    <h4 class="card-title">{{ contact.full_name }}</h4>
    <h5>{{ contact.primary_email }}
    <a href="{% url 'contact:detail' contact.pk %}">Click here</a>
{% endfor %}

这是打印用户的全名但不是主电子邮件

1 个答案:

答案 0 :(得分:1)

您必须使用APIView中的序列化程序才能访问其字段。您还需要使用Django render帮助程序在上下文中传递联系人以呈现模板,因为APIView不了解有关呈现自定义模板的知识。

一种选择是在将数据添加到ContactList中的上下文之前序列化数据。像这样:

from django.shortcuts import render


class ContactList(APIView):
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'contacts/list.html'
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def get(self, request):
        serialized_contacts = ContactSerializer(
            Contact.objects.all(), many=True).data
        context = {'contacts': serialized_contacts}
        return render(request, self.template_name, context)

但是我没有看到在该视图中使用API​​View或序列化程序的原因。我会做什么:

  1. primary_email属性添加到Contact模型:

    class Contact(models.Model):
        user_id = models.ForeignKey(User, on_delete=models.CASCADE)
        first_name = models.CharField(max_length=100)
        last_name = models.CharField(max_length=100, blank=True, null=True)
        date_of_birth = models.DateField(blank=True, null=True)
    
        class Meta:
            db_table = 'contacts'
    
        @property
        def full_name(self):
            return self.first_name + ' ' + self.last_name
    
        @property
        def primary_email(self):
            primary_email = self.contactemail_set.filter(primary=True).first()
    
            if primary_email:
                return primary_email.email
    
            return ''
    
        def __str__(self):
            return self.full_name
    
  2. 使用这个新模型,在get_primary_email中定义ContactSerializer方法是不必要的:

    class ContactSerializer(serializers.HyperlinkedModelSerializer):
        primary_email = serializers.SerializerMethodField()
    
        class Meta:
            model = Contact
            fields = ('url', 'full_name', 'date_of_birth', 'primary_email')
    
  3. 我没有将APIView用于ContactList视图,而是使用Django的generics.ListView。

    from django.views.generic import ListView
    from django.contrib.auth.mixins import LoginRequiredMixin
    
    
    class ContactList(LoginRequiredMixin, ListView):
        template_name = 'contacts/list.html'
        permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
        queryset = Contact.objects.all()