我是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/contacts
,ContactList
可以访问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 %}
这是打印用户的全名但不是主电子邮件
答案 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)
但是我没有看到在该视图中使用APIView或序列化程序的原因。我会做什么:
将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
使用这个新模型,在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')
我没有将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()