I'm building an API with the django rest framework. I have these models:
class Organisme(models.Model):
nom = models.CharField(max_length=255)
adresse = models.ForeignKey(Adresse, on_delete=models.CASCADE)
class Adresse(models.Model):
rue = models.CharField(max_length=255, blank=True)
This is the view for my mode Organisme :
class OrganismeViewSet(viewsets.ModelViewSet):
queryset = Organisme.objects.all()
serializer_class = OrganismeSerializer
pagination_class = StandardResultsSetPagination
filter_backends = (filters.SearchFilter, DjangoFilterBackend)
filter_class = OrganismeFilter
search_fields = ('nom')
And my serializer:
class OrganismeSerializer(serializers.ModelSerializer):
class Meta:
model = Organisme
fields = '__all__'
depth = 1
So I'm trying to create a new Organisme by sending this:
{
"adresse": {
"rue": "test"
},
"nom":"TestTest",
}
or
{
"adresse": pk_id,
"nom":"TestTest",
}
But I always end up with this error:
IntegrityError at /organismes/
(1048, "Column 'adresse_id' cannot be null")
If you guys know how to proceed... Thank you in advance.
You need to override create method to make writable nested serializer:
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Addresse
fields = ('rue',)
class OrganismeSerializer(serializers.ModelSerializer):
addresse = AddressSerializer()
class Meta:
model = Organisme
fields = '__all__'
def create(self, validated_data):
address_data = validated_data.pop('adresse')
address = Adresse.objects.create(**address_data)
organism = Organisme.objects.create(address=address, **validated_data)
return organism
Related
id field and name field not showing in result.
in models.py:
class Group(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
admin = models.ForeignKey(User, on_delete=models.CASCADE)
member = models.ManyToManyField(User, related_name='groups_user')
def __str__(self):
return self.name
in serializers.py:
class SimpleUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id','first_name', 'last_name')
class GroupSerializer(serializers.Serializer):
admin = SimpleUserSerializer()
class Meta:
model = Group
fields = ('id','name','admin')
views.py:
#api_view(['GET'])
#permission_classes((IsAuthenticated,))
def getSomeGroup(request):
allGroup = Group.objects.all().count()
randomGroupId = random.sample(range(allGroup), 3)
randomGroup = Group.objects.filter(id__in=randomGroupId)
serializer = GroupSerializer(randomGroup, many=True)
#print(serializer)
return Response(serializer.data)
the result comes like this:
[{"admin":{"id":1,"first_name":"asif","last_name":""}},{"admin":{"id":3,"first_name":"Test2","last_name":"lastname"}},{"admin":{"id":3,"first_name":"Test2","last_name":"lastname"}}]
why id and name field not showing?
class SimpleUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
First try to access all admin
#api_view(['GET'])
#permission_classes(IsAuthenticated)
def getSomeGroup(request):
randomGroup = Group.objects.all()
serializer = GroupSerializer(randomGroup, many=True)
return Response(serializer.data)
If that works there may be issue in your these two line
The Issue may be in these two lines
allGroup = Group.objects.all().count()
randomGroupId = random.sample(range(allGroup), 3)
Modify serializers.py:
class GroupSerializer(serializers.ModelSerializer):
I'm a Django Rest Framework and Django newbie
i can use random data to make stages but i can't use serializer to add new stages.
My model and serializer
class Stage(models.Model):
class Meta:
db_table = 'stage'
stage_id = models.AutoField(primary_key=True)
stage_name = models.CharField(max_length=64, null=False)
company = models.ForeignKey(
Company,
db_column='id',
on_delete=models.CASCADE,
)
class StageSerializer(ModelSerializer):
stage_id = IntegerField(read_only=True)
class Meta:
model = Stage
fields = [
'stage_id',
'stage_name',
'company',
]
def update(self, instance, validated_data):
pass
def create(self, validated_data):
# create stages
stage = create_stage(**validated_data)
return stage
view.py
class StageListAPIView(APIView):
def post(self, request, company_id):
data = request.data.copy()
company = get_company_by_id(company_id)
data['company'] = company.pk
serializer = StageSerializer(data=data)
if not serializer.is_valid(raise_exception=True):
return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)
new_data = serializer.validated_data
serializer.save(company=company)
return Response(new_data, status=HTTP_200_OK)
request.data
<QueryDict: {'stage_name': ['kAkSdKq9Gt'], 'company': [6]}>
i will receive error:
TypeError: Object of type Company is not JSON serializable
i can't understand it and i don't know how to use serializer to save foreign key.
You need to serialize the Company instance before you can include it in your StageSerializer.
A simple example would be something like
class CompanySerializer(ModelSerializer):
class Meta:
model = Company
fields = '__all__'
And then to include that in your StageSerializer:
class StageSerializer(ModelSerializer):
stage_id = IntegerField(read_only=True)
company = CompanySerializer(source='company', read_only=True)
class Meta:
model = Stage
fields = [
'stage_id',
'stage_name',
'company',
]
I'm currently starting a simple Task App and I'm using Django 2.0.7, DRF 3.8.2 and drf-nested-routes 0.90.2
I have these models :
class Client(TimeStampedModel):
"""
This model describes a client for the railroader. It can be created by the manager in the back office
We have at least one internal Client, which is Seelk, for internal projects
"""
name = models.CharField(max_length=255, unique=True)
description = models.TextField(null=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return "{} : {}".format(self.name, self.description)
class Project(TimeStampedModel):
"""
This model represents a project for a client, which we are gonna track actions on
"""
client = models.ForeignKey(
'railroader.Client', on_delete=models.PROTECT, related_name='projects')
name = models.CharField(max_length=255, unique=True)
description = models.TextField(null=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return "{} for client {}".format(self.name, self.client.name)
So, following the documentation of drf-nested-routers, I set up my serializers like this :
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = Client
fields = ("id", "name", "description", "is_active", "projects")
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = ("id", "name", "description", "is_active")
And my viewsets like this :
class ClientViewset(viewsets.ModelViewSet):
serializer_class = ClientSerializer
permission_classes = (permissions.IsAuthenticated, AccountPermission)
def get_queryset(self):
queryset = Client.objects.all()
is_active = self.request.query_params.get("is_active")
if is_active:
queryset = queryset.filter(is_active=is_active)
return queryset
class ProjectViewset(viewsets.ModelViewSet):
serializer_class = ProjectSerializer
permission_classes = (permissions.IsAuthenticated, AccountPermission)
def get_queryset(self):
queryset = Project.objects.filter(client=self.kwargs["client_pk"])
is_active = self.request.query_params.get("is_active")
if is_active:
queryset = queryset.filter(is_active=is_active)
return queryset
And finally, my urls like so :
router = routers.SimpleRouter()
router.register(r"clients", viewsets.ClientViewset, base_name="clients")
projects_router = routers.NestedSimpleRouter(router, r"clients", lookup="client")
projects_router.register(r"projects", viewsets.ProjectViewset, base_name="projects")
urlpatterns = [
re_path(r"^", include(router.urls)),
re_path(r"^", include(projects_router.urls))
]
With this setup, I'm able to have the desired nested routes, but I can't have my routes to create a new object if I post on a nested route.
I've seen an issue on the github speaking about it, but as it was 2 years ago, I wonder if anyone knows how to do it.
Thanks in advance.
Found out I just forgot that returning an instance in DRF create method of the serializer would not create the object in base. At the end I have this serializer :
class ProjectSerializer(serializers.ModelSerializer):
def create(self, validated_data):
client = Client.objects.get(pk=self.context["view"].kwargs["client_pk"])
validated_data["client"] = client
return Project.objects.create(**validated_data)
class Meta:
model = Project
fields = ("id", "name", "description", "is_active")
Can I add the Model function property in the API?
I have a Model:
class PhysicalServer(models.Model):
name = name = models.CharField(max_length=32)
trade_record = models.ForeignKey(to=TradeRecord, null=True, blank=True)
#property
def is_applied(self):
if self.trade_record == None:
return False
else:
return True
my PhysicalServerListAPIView of it:
class PhysicalServerListAPIView(ListAPIView):
serializer_class = PhysicalServerListSerializer
permission_classes = [AllowAny]
queryset = PhysicalServer.objects.all()
the PhysicalServerListSerializer:
class PhysicalServerListSerializer(ModelSerializer):
class Meta:
model = PhysicalServer
fields = "__all__"
I have a requirement, how can I add the is_applied to the list API?
I mean, if I access the ListAPI, the results data will be like:
{
name: xxx,
trade_record: xxx
},
...
How can I add this?
{
name: xxx,
trade_record: xxx
is_applied: xxx
},
...
just add the field description to the serializer
from rest_framework import serializers
class PhysicalServerListSerializer(ModelSerializer):
is_applied = serializers.BooleanField(read_only=True)
class Meta:
model = PhysicalServer
fields = "__all__"
I think the SerializerMethodField is what are you looking for.
Try this way.
class PhysicalServerListSerializer(ModelSerializer):
is_applied = serializers.SerializerMethodField()
class Meta:
model = PhysicalServer
fields = "__all__"
def get_is_applied(self, obj):
return self.trade_record is not None:
For more info: http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
How can I returns serval list in Rest Framework?
I have serializers.py
class HostTypeSerializer(ModelSerializer):
class Meta:
model = HostType
fields = "__all__"
class DiskOSTypeSerializer(ModelSerializer):
class Meta:
model = DiskOSType
fields = "__all__"
class DiskEssenceTypeSerializer(ModelSerializer):
class Meta:
model = DiskEssenceType
fields = "__all__"
I have the three Serializers, and I want to return data like bellow:
{
hosttypes:[the HostTypeSerializer's list data ],
diskostype:[the DiskOSTypeSerializer's list data],
diskessencetype:[the DiskEssenceTypeSerializer's list data],
}
I tried but failed, but I don't know how to do with that:
class DiskPreCreateSerialzer(ModelSerializer):
hosttypes = HostTypeSerializer(many=True, read_only=True)
diskostypes = DiskOSTypeSerializer(many=True, read_only=True)
diskessencetypes = DiskEssenceTypeSerializer(many=True, read_only=True)
class Meta:
fields = (
"hosttypes",
"diskostypes",
"diskessencetypes",
)
In views.py:
class DiskPreCreateAPIView(APIView):
serializer_class = DiskPreCreateSerialzer
permission_classes = []
...
I want to use this Serializer to returns my requirement, but failed, how can I get that?
EDIT
I don't know how to write my DiskPreCreateAPIView now, because I don't know how to get the data to return.
class DiskPreCreateAPIView(APIView):
serializer_class = DiskPreCreateSerialzer
permission_classes = []
def post(self, request):
return Response(data=xxx, status=HTTP_200_OK)
Try to use base Serializer instead of ModelSerializer:
class DiskPreCreateSerialzer(Serializer):
hosttypes = HostTypeSerializer(many=True, read_only=True)
diskostypes = DiskOSTypeSerializer(many=True, read_only=True)
diskessencetypes = DiskEssenceTypeSerializer(many=True, read_only=True)
And in your view pass dict with your lists to this serializer:
class DiskPreCreateAPIView(APIView):
serializer_class = DiskPreCreateSerialzer
permission_classes = []
def post(self, request):
...
serializer = self.serializer_class({
'hosttypes': hosttypes_qs,
'diskostype':diskostype_qs,
'diskessencetype': diskessencetype_qs,
})
return Response(data=serializer.data, status=HTTP_200_OK)