I got an error,
AttributeError at /app/api/get
Got AttributeError when attempting to get a value for field task_name on serializer TaskSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Color instance.
Original exception text was: 'Color' object has no attribute 'task_name'.
Now I wanna make a page that shows model's content in json format.
models.py is
from django.db import models
# Create your models here.
class Color(models.Model):
name = models.CharField(max_length=255)
background_color = models.CharField(max_length=255)
h1_color = models.CharField(max_length=255)
p_color = models.CharField(max_length=255)
def __str__(self):
return self.name
serializers.py is
from .models import Color
from rest_framework import serializers
class TaskSerializer(serializers.Serializer):
task_name = serializers.CharField(max_length=100)
status = serializers.SerializerMethodField('get_task_status')
def get_task_status(self, instance):
return instance.status.status
class Meta:
model = Color
fields = ('name',
'background_color',
'h1_color',
'p_color',
'task_name')
urls.py is
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'api/get',views.TaskGet.as_view(),name='task-get')
]
views.py is
from django.shortcuts import render
from .models import Color
from .forms import ColorForm
from .serializers import TaskSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
# Create your views here.
def index(request):
d = {
'colors': Color.objects.all(),
'form': ColorForm(),
}
return render(request, 'index.html', d)
class TaskGet(APIView):
def get(self, request, format=None):
obj = Color.objects.all()
serializers = TaskSerializer(obj, many=True)
return Response(serializers.data, status.HTTP_200_OK)
I wrote url(r'api/get',views.TaskGet.as_view(),name='task-get') in urls.py,so I really cannot understand why this error happens.I already run commands of migration of model. How can I fix this?
My ideal web page is like
You try get status by foreign key instance.status.status but in your model class Color i don't see any foreign keys or methods for it.
And for task_name did you want to see the model field name try to add source params
task_name = serializers.CharField(max_length=100, source='name')
# ^^^^^^^^^
are you sure you want serialize Task for model Color?
new edit
in your get_task_status the 'instanceis instance of serializer model, so if your modelColorhas no property or methodstatus` you will catch an error
Related
I would like to fetch the entire table. My model and serializer seems to be correct but I am getting the below error
Got AttributeError when attempting to get a value for field symbol on serializer CompanySerializer.
The serializer field might be named incorrectly and not match any attribute or key on the QuerySet instance.
Original exception text was: 'QuerySet' object has no attribute 'symbol'.
Below is my Model
models.py
from django.db import models
class Companies(models.Model):
symbol = models.CharField(max_length=100)
name = models.CharField(max_length=255)
isin = models.CharField(max_length=255)
serializers.py
from rest_framework import serializers
from .models import Companies
class CompanySerializer(serializers.ModelSerializer):
class Meta:
fields = ['symbol', 'name', 'isin',]
# fields = '__all__'
model = Companies
Below is my view
views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Companies
from .serializers import CompanySerializer
from django.core.serializers import json
class companiesView(APIView):
def get(self, request):
companies = Companies.objects.filter(id=1)
serializer = CompanySerializer(companies)
# json_serializer = json.Serializer()
# json_serialized = json_serializer.serialize(companies)
response = Response()
response.data = {
'named' : serializer.data,
}
return response
I am not sure what is causing this issue. Thanks in Advance.
companies is a queryset, so what you have is a list of companies. If you want your serializer to work with a list of objects, just add many=True:
companies = Companies.objects.filter(id=1)
serializer = CompanySerializer(companies, many=True)
# ^^^ Add this
Another way is to just get the company with id 1 using get instead of filter. In this case you don't have to add many=True since the serializer is working on a single object:
companies = Companies.objects.get(id=1)
# ^^^ Use get instead of filter
serializer = CompanySerializer(companies)
A newbie here in the world of Django. I am struggling with creating a hyperlink for a nested route.
The error I am getting is:
Could not resolve URL for hyperlinked relationship using view name "rest:campaign-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
Some project setup notes
Using django rest framework
using DRF-extensions to create the routes
Using ModelViewSet
Expected end points:
/accounts/
/accounts/< pk >/
/accounts/< pk >/campaigns/
/accounts/< pk >/campaigns/< pk >/
/accounts/< pk >/campaigns/adgroup/
/accounts/< pk >/campaigns/adgroup/< pk >/
Set a namespace of rest in urls.py
Using HyperlinkedIdentityField to create the hyperlink. It only works with the parent object i.e.
url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')
However fails with any nested object i.e.
url = serializers.HyperlinkedIdentityField(view_name='rest:campaign-detail')
The model is quiet simple, an Account can have many Campaigns, and a campaign can have many AdGroups. See code below:
models.py
from django.db import models
from django.db.models import Q
from model_utils import Choices
ORDER_COLUMN_CHOICES = Choices(
('0', 'id'),
('1', 'keyword'),
('2', 'status'),
('3', 'match_type'),
)
# Account
class Account(models.Model):
account_name = models.CharField(max_length=128)
def __str__(self):
return self.account_name
# Campaign
class Campaign(models.Model):
class Status(models.TextChoices):
Enabled = "Enabled"
Paused = "Paused"
account = models.ForeignKey(
to=Account, on_delete=models.CASCADE, related_name='campaigns'
)
campaign_name = models.CharField(max_length=128)
status = models.CharField(max_length=21, choices=Status.choices, default=Status.Paused)
def __str__(self):
return self.campaign_name
# AdGroup
class AdGroup(models.Model):
class Status(models.TextChoices):
Enabled = "Enabled"
Paused = "Paused"
campaign = models.ForeignKey(
to=Campaign, on_delete=models.CASCADE, related_name='adgroups'
)
adgroup_name = models.CharField(max_length=128)
status = models.CharField(max_length=21, choices=Status.choices, default=Status.Enabled)
def __str__(self):
return self.adgroup_name
views.py
from rest_framework import viewsets
from .serializers import *
from . import models
from rest_framework_extensions.mixins import NestedViewSetMixin
class AccountViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = AccountSerializer
queryset = models.Account.objects.all()
class CampaignViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = CampaignSerializer
queryset = models.Campaign.objects.all()
class AdGroupViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = AdGroupSerializer
queryset = models.AdGroup.objects.all()
serializers.py
from rest_framework import serializers
from . import models
class CampaignSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="rest:campaign-detail")
class Meta:
model = models.Campaign
fields = '__all__'
class AccountSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')
class Meta:
model = models.Account
fields = '__all__'
class AdGroupSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='rest:adgroup-detail')
class Meta:
model = models.AdGroup
fields = '__all__'
I have 2 URL files. The project is named Vanilla and an app named rest where the DRF logic sits.
Vanilla urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('rest.urls', namespace='rest')),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('admin/', admin.site.urls)
]
Rest urls.py
from django.urls import include, path
from . import views
from rest_framework_extensions.routers import ExtendedSimpleRouter
app_name = 'rest'
router = ExtendedSimpleRouter()
(
router.register(r'accounts',
views.AccountViewSet,
basename='account')
.register(r'campaigns',
views.CampaignViewSet,
basename='campaign',
parents_query_lookups=['account__id'])
.register(r'adgroups',
views.AdGroupViewSet,
basename='adgroup',
parents_query_lookups=['campaign__account', 'campaign'])
Thank You!
use hyperlinkedModelSerializer in all of your related serializer. that should work
I am using Django 3.0 djangorestframework==3.11.0. I have created a task update view and passing the pk to url. The problem is - Although I have set the serializer instance to the model object I want to update. The serializer instance is not showing up.
models.py
from django.db import models
# Create your models here.
class Task(models.Model):
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False, blank=True, null=True)
def __str__(self):
return self.title
serializers.py
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = '__all__'
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.apiOverview, name='api-overview'),
path('task-list/', views.taskList, name='task-list'),
path('task-detail/<str:pk>/', views.taskDetail, name='task-detail'),
path('task-create/', views.taskCreate, name='task-create'),
path('task-update/<str:pk>/', views.taskUpdate, name='task-update'),
]
views.py
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Task
from .serializers import TaskSerializer
#api_view(['POST'])
def taskUpdate(request, pk):
task = Task.objects.get(id=pk)
serializer = TaskSerializer(instance=task, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
expected behavior on url http://localhost:8000/api/task-update/4/
actual behaviour on http://localhost:8000/api/task-update/4/
as you can see the content field is empty but I want the already associated json to be shown there with pk = 4.
I have a APIView that provides my model instances. I want to use different serializers based on url parameters, beacause I want to serve different fields based on parameter. I didn't want to use if else check for all situations, so I used a function that provide serializer from serializer objects dict based on type key. Is there a good solution? Does anyone have a better suggestion?
Also what are you thinking about use different endpoints instead of this method.
Here is the code:
urls.py
from django.urls import path
from .views import MySerializerTestView
urlpatterns = [
path('<slug:type>', MySerializerTestView.as_view()),
]
models.py
from django.db import models
class MyModel(models.Model):
field_first = models.CharField(max_length=10)
field_second = models.CharField(max_length=10)
field_third = models.CharField(max_length=10)
views.py
from .models import MyModel
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import MyFirstSerializer,MySecondSerializer,MyThirdSerializer
class MySerializerTestView(APIView):
def get(self, request, **kwargs):
my_data = MyModel.objects.all()
serializer = self.get_serializer(self.kwargs['type'],my_data)
return Response(serializer.data)
def get_serializer(self,type,data):
my_serializers = {
'first':MyFirstSerializer(data,many=True),
'second':MySecondSerializer(data,many=True),
'third':MyThirdSerializer(data,many=True),
}
return my_serializers[type]
serializers.py
from .models import MyModel
from rest_framework import serializers
class MyFirstSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ['field_first']
class MySecondSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ['field_second']
class MyThirdSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ['field_third']
You can send a parameter or select the serializer based on the action that is taken.
In your "view.py" file you can use the "get_serializer_class (self)" method to do it.
def get_serializer_class(self):
if 'parameter' in self.request.query_params:
return ParameterSerializer
if self.action == "list" or self.action == 'retrieve':
return ListSerializer
else:
return CreateSerializer
I started to code a two-apps django project. ModelA belongs to appone and ModelB belongs to apptwo. My purpose is to create a ModelA instance everytime that the user creates a ModelB instance. And the value of a ModelA CharField (that is ckeditor widgeted) must be the source code of a ModelB admin view. I used a post_data signal to link a function of creation for that. The problem is that i use the id of each instance of ModelB in order to create the good content for each instance of ModelA. When I try to use a string of the url sending the id parameter, the content field has for value the source code of the debug page
(error 500, DoesNotExist at /admin/apptwo/modelb/my_view/ref=76, [76 is an example] ModelB matching query does not exist. Exception location : /home/me/Desktop/env/lib/python3.5/site-packages/django/db/models/query.py in get, line 385)
But when I try to visit the url "http://localhost:8000//admin/apptwo/modelb/my_view/ref=76", or when I hardcode the url, without a str(instance.id), the page exists and everything works perfectly.
I don't understand why.
Could anybody give me some help to solve this problem ?
Thanks in advance,
PS :
The first app has a model.py that contains the following code :
from django.db import models
from django.contrib.auth.models import User
from registre.models import *
class ModelA(models.Model):
content = models.CharField(max_length=255, null=True)
def __str__(self):
return "ModelA : " + str(self.id)
the admin.py of this first app also contains :
from django.contrib import admin
from appone.models import *
from apptwo.models import ModelB
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.conf.urls import url
from registre import views
from django.db.models.signals import post_save
from django.dispatch import receiver
import datetime
from django.contrib.auth.models import User
from django import forms
from ckeditor.widgets import CKEditorWidget
from django.template.loader import render_to_string
import requests
class ModelAAdminForm(forms.ModelForm):
content = forms.CharField(widget=CKEditorWidget())
class Meta:
model = ModelA
fields = '__all__'
class ModelAAdmin(admin.ModelAdmin):
form = ModelAAdminForm
def create_A(sender, instance, **kwargs):
string = "http://localhost:8000/admin/apptwo/modelb/my_view/ref=" + str(instance.id)
r = requests.get(string)
ModelA.objects.create(contenu=r.text.encode('utf-8'))
post_save.connect(create_A, sender=ModelB)
admin.site.register(ModelA, ModelAAdmin)
the second app (apptwo) has a models.py like this :
from django.db import models
from django.contrib.auth.models import User
class ModelB(models.Model):
owner = models.ForeignKey(User, null=True)
name = models.CharField(max_length=255, null=True)
def __str__(self):
return self.name
and an admin.py that contains :
from django.contrib import admin
from appone.models import *
from apptwo.models import *
import datetime
from django.conf.urls import url, include
from django.template.response import TemplateResponse
class ModelBAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(ModelB, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)
def save_model(self, request, obj, form, change):
obj.owner = request.user
obj.save()
def get_urls(self):
urls = super(ModelBAdmin, self).get_urls()
my_urls = [
url(r'^my_view/ref=(?P<id>\d+)$', self.my_view),
]
return my_urls + urls
def my_view(self, request, id):
context = dict(
self.admin_site.each_context(request),
selector = ModelB.objects.get(id=id),
)
return TemplateResponse(request, "myview.html", context)
admin.site.register(ModelB, ModelBAdmin)
and finally a template myview.html with :
<p>Test {{ selector.name }}</p>