I am trying request.data.get('student_name') but it says that list has no attribute get. I just want to get the name of all students before passing to the serializer. I am sending the POST request data in the form of
[
{"student_name": "jack", "last_name": "cale", "fathers_name":"carlos"},
{"student_name": "alex", "last_name": "magasa", "fathers_name":"greg"},
{"student_name": "sia", "last_name": "gunns", "fathers_name":"brett"},
{"student_name": "jacob", "last_name": "woods", "fathers_name":"john"}
]
my views.py
#api_view(['POST'])
def add_students(request):
student_name = request.data.get('student_name')
fathers_name = request.data.get('fathers_name')
serializer = StudentsSerializer(data=request.data, many=True)
if serializer.is_valid():
serializer.save()
return Response("success")
else:
return Response(serializer.errors)
my serializers.py
class StudentsSerializer(serializers.ModelSerializer):
class Meta:
model = Students
fields = ('student_name', 'last_name', 'fathers_name')
my models.py
class Students(models.Model):
student_name = models.CharField(max_length=100, null=True)
last_name = models.CharField(max_length=100, null=True)
fathers_name = models.CharField(max_length=100, null=True)
You are trying to get value from list so you have to iterate through list
for data in request.data:
student_name = data.get('student_name')
father_name = data.get('father_name')
This seems like a question about the format of the request object. My two cents is that it's worth throwing in an import ipdb; ipdb.set_trace() at the beginning of the method, and then using print and dir to get an idea of what the object looks like. Since Django has so many django-specific objects, this helps in a lot of cases.
Related
I am using Django Rest and my request parameter contains:
[
{
"job_role": 2,
"technology": 1
},
{
"job_role": 1,
"technology": 1
},
{
"job_role": 2,
"technology": 1
}
]
My models are:
class Technology(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class JobRole(models.Model):
role_name = models.CharField(max_length=100)
def __str__(self):
return self.role_name
class ExpertPricing(models.Model):
role_name = models.OneToOneField(JobRole, related_name="role", on_delete=models.SET_NULL, null=True)
experience_in_years = models.PositiveBigIntegerField()
technology = models.OneToOneField(Technology, related_name="technology", on_delete=models.SET_NULL, null=True)
salary_per_month = models.PositiveBigIntegerField()
My view looks like this:
class PricingView(APIView):
def post(self, request):
datas = request.data
data_list = []
for data in datas:
job_role_id = data["job_role"]
technology_id = data["technology"]
job_role = JobRole.objects.get(pk=job_role_id)
technology = Technology.objects.get(pk=technology_id)
expert_pricing = ExpertPricing.objects.filter(role_name=job_role, technology=technology)
if expert_pricing:
data_list.append(expert_pricing)
serializer = ExpertPricingSerializer(data_list, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
serializers.py
class TechnologySerializer(serializers.ModelSerializer):
class Meta:
model = Technology
fields = ("id", "name")
class JobRoleSerializer(serializers.ModelSerializer):
class Meta:
model = JobRole
fields = ("id","role_name")
class ExpertPricingSerializer(serializers.ModelSerializer):
role = JobRoleSerializer(many=False, read_only=True)
technology = TechnologySerializer(many=False, read_only=True)
class Meta:
model = ExpertPricing
fields = "__all__"
I am unable to understand why data_list is not being serialized.
the error says:
AttributeError: Got AttributeError when attempting to get a value for field `experience_in_years` on serializer `ExpertPricingSerializer`.
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 'experience_in_years'.
Since you defined in your model that those two fields (experience_in_years and salary_per_month) can not be empty, it seems like you need to do one of these things:
Send experience_in_years and salary_per_month fields in your request too.
Give a default value to those fields
Make it null=True, blank=True
If you do 2 or 3 those solutions require migration, keep that in mind, after doing one of those things you should be good to go
models.py
class Sequence(models.Model):
category_id = models.ForeignKey(SequenceCategory, on_delete=models.CASCADE)
description = models.TextField()
code = models.CharField(max_length=50)
total_divisions = models.IntegerField()
status = models.BooleanField(default=True)
def __str__(self):
return self.code
class SequenceValue(models.Model):
TYPE_CHOICES =(
('N', 'Numeric'),
('A', 'Alphabet')
)
sequence_id = models.ForeignKey(Sequence, on_delete=models.CASCADE, blank=True, null=True, related_name='Sequence_details')
type = models.CharField(max_length=100, choices=TYPE_CHOICES)
value = models.CharField(max_length=50)
starting_value = models.CharField(max_length=50, null=True, blank=True)
increment_value = models.CharField(max_length=50, null=True, blank=True)
def __str__(self):
return self.value
serializers.py
class SequenceValueSerializer(serializers.ModelSerializer):
class Meta:
model = SequenceValue
# fields = '__all__'
exclude = ['sequence_id']
class SequenceSerializer(serializers.ModelSerializer):
Sequence_details = SequenceValueSerializer()
class Meta:
model = Sequence
fields = '__all__'
def create(self, validate_data):
Sequence_details_data = validate_data.pop('Sequence_details')
sequence_id = Sequence.objects.create(**validate_data)
SequenceValue.objects.create(sequence_id=sequence_id, **Sequence_details_data)
return sequence_id
views.py
class SequenceCreate(ListCreateAPIView):
queryset = Sequence.objects.all()
serializer_class = SequenceSerializer
Why do I get the error? When I refer to n number of articles I got a solution that put many=True something like this.
Sequence_details = SequenceValueSerializer(many=True)
But when I make changes on that then I can't get the Sequence details fields. How can I fix this issue? Can you give a solution, please?
Actual error-
Got AttributeError when attempting to get a value for field type on serializer SequenceValueSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the RelatedManager instance.
Original exception text was: 'RelatedManager' object has no attribute 'type'.
Data Passess
Data - {
"Sequence_details": [{
"type": "N",
"value": "123",
"starting_value": "1",
"increment_value": "1"
}],
"description": "asd",
"code": "qwe",
"total_divisions": 2,
"status": false,
"category_id": 3
}
Actual eroor screenshot
Adding many=True works because your request data passes Sequence_details as a list. In order to use it in your serializer, you can just iterate through the field and create your objects like this:
class SequenceSerializer(serializers.ModelSerializer):
Sequence_details = SequenceValueSerializer(many=True)
class Meta:
model = Sequence
fields = '__all__'
def create(self, validate_data):
Sequence_details_data = validate_data.pop('Sequence_details')
sequence_id = Sequence.objects.create(**validate_data)
for details in Sequence_details_data
SequenceValue.objects.create(sequence_id=sequence_id, **details)
return sequence_id
But if you don't want to do this, you can remove many=True and keep your serializer as is, but ensure that Sequence_details in your request data is not a list:
{
"Sequence_details": {
"type": "N",
"value": "123",
"starting_value": "1",
"increment_value": "1"
},
"description": "asd",
"code": "qwe",
"total_divisions": 2,
"status": false,
"category_id": 3
}
I can't comment so I will just mention it here :). type is actually a function in python which tells you about the class type of argument. I am not sure if this the issue but the can you try by renaming type to _type or something of your choice.
I want to know what kind of data should I send to django-rest-framework and dont get the string indices must be integers ?
the function is
#permission_classes((IsAuthenticated,))
def update_interests(request):
user_profile = request.user.userprofile
interests = request.data
user_profile.interests.set(
TopicTag.objects.get(name=interest['name'])[0] for interest in interests
)
user_profile.save()
serializer = UserProfileSerializer(user_profile, many=False)
return Response(serializer.data)
the error is
typeError: string indices must be integers
and the data I have send is a json
{
"name": ["news"]
}
just in case the models.py looks like this
class TopicTag(models.Model):
name = models.CharField(primary_key=True, max_length=150, null=False, blank=False)
def __str__(self):
return self.name
maybe you need the serializers so here you are
class TopicTagSerializer(serializers.ModelSerializer):
class Meta:
model = TopicTag
fields = '__all__'
help me :)
request.data is a dictionary. which has the value as follows:
{
"name": ["news"]
}
when you are traversing it in your for loop it would return you keys of the dictionary in the iterator.
in this case:
"name"
now when you trying to access it like this
interest["name"]
it returns an error because it expects an integer.
you can get names like this
request.data.get("name")
and in your query you can do something like this
TopicTag.objects.get(name=interest)
I just recently started developing for Django and am building an API using Django REST Framework and class based views. I am looking for a way to combine models, sort them based on time and then return a subset of the fields to an API with the table name appended.
Currently I have the following:
views.py
class RunLog(APIView):
"""
List log for a specific run sorted in reverse chronological order
"""
def get(self, request, run_id, format=None):
# Combine and sort based on time (decreasing)
result_list = sorted(chain(Output.objects.filter(run=run_id),
Downtime.objects.filter(run=run_id)),
key=attrgetter('start_time'), reverse=True)
// Replace this with serializer??
response = Response(serializers.serialize('json', result_list), status=status.HTTP_200_OK)
return response
models.py
class Output(models.Model):
start_time = models.DateTimeField(default=datetime.now)
value = models.FloatField()
run = models.ForeignKey(Run, blank=True, null=True)
def __unicode__(self):
return str(self.id)
class Downtime(models.Model):
start_time = models.DateTimeField(default=datetime.now)
end_time = models.DateTimeField(null=True, blank=True)
reason = models.CharField(max_length=500)
run = models.ForeignKey(Run, blank=True, null=True)
I get the following JSON:
"[{\"model\": \"app.downtime\", \"pk\": 91, \"fields\": {\"start_time\": \"2016-07-20T14:46:21Z\", \"end_time\": null, \"reason\": \"reason1\", \"run\": 71}}, {\"model\": \"app.downtime\", \"pk\": 101, \"fields\": {\"start_time\": \"2016-07-20T14:46:21Z\", \"end_time\": null, \"reason\": \"reason2\", \"run\": 71}}]"
I would like to serialize this data in the following JSON format:
[
{
"id": 231,
"type": "speed",
"description": "Some description",
"time": "2016-07-21T21:26:26Z"
}
]
**Where type is the database table and description is concatenated columns from a model.
I have looked at the docs and this similar question without any luck.
As IanAuld suggested in the comments - ModelObj._meta.db_table got the name of the table. I then created a sorted list of dictionaries in views.py:
speedList = Speed.objects.filter(run=run_id)
type = Speed._meta.db_table.split('_', 1)[1]
type = type[0].upper() + type[1:]
for speed in speedList:
description = "Speed change to %.2f (units)" % speed.value
logList.append({'id':speed.id, 'type':type, 'description':description, 'time':speed.start_time})
# Sort list by decreasing time
resultList= sorted(logList, key=itemgetter('time'), reverse=True)
serializer = LogSerializer(resultist, many=True)
return Response(serializer.data)
serializers.py:
class LogSerializer(serializers.Serializer):
id = serializers.IntegerField()
type = serializers.CharField(max_length=100)
description = serializers.CharField(max_length=500)
time = serializers.DateTimeField()
I have been struggling to add many-to-many relation in the django serializer than be accessed through the view.
I created 2 classes in the model file "MODISLevel1" & "FileProperties". Where MODISLevel1 has a field called "filesProperties" pointing to the "FileProperties" class.
The model looks like:
class FileProperties(models.Model):
FileName = models.CharField(blank=True, max_length=1000)
FileID = models.CharField(blank=True, max_length=1000)
FileSize = models.CharField(blank=True, max_length=1000)
Updated = models.CharField(blank=True, max_length=1000)
GeoBox = models.CharField(blank=True, max_length=1000)
def __str__(self):
return self.FileName
class Meta:
ordering = ('FileName',)
class MODISLevel1(models.Model):
ProductLevel = models.CharField(max_length=7,
choices=ProductLevelsChoices,
default='MOD03')
SpacecraftType = models.CharField(max_length=5,
choices=SpacecraftTypeChoices,
default='Terra')
StartTimespan = models.TextField()
EndTimespan = models.TextField()
AOI = models.TextField()
DegreeNumbers = models.TextField()
filesProperties = models.ManyToManyField(FileProperties)
def __str__(self):
return self.ProductLevel
class Meta:
ordering = ('ProductLevel',)
As for the serializer I checked http://django-rest-framework.org/api-guide/relations.html#nested-relationships which tells that nested relationships should be created in the following way:
class FilePropertiesSerializer(serializers.ModelSerializer):
class Meta:
model = FileProperties
fields = ('id', 'FileName', 'FileID', 'FileSize', 'Updated', 'GeoBox')
class MODISLevel1Serializer(serializers.ModelSerializer):
filesProperties = FilePropertiesSerializer(many=True)
class Meta:
model = MODISLevel1
fields = ('id', 'ProductLevel', 'SpacecraftType', 'StartTimespan', 'EndTimespan', 'AOI', 'DegreeNumbers', 'filesProperties')
for the the view file I tried different ways to make it work but with no success.
1-Creating an instance from the Model "MODISLevel1", filling its fields, saving it, then filling the m2m field through iteration:
modisLevel1 = MODISLevel1()
modisLevel1.ProductLevel = productLevel
modisLevel1.SpacecraftType = spacecraftType
modisLevel1.StartTimespan = startTimespan
modisLevel1.EndTimespan = endTimespan
modisLevel1.AOI = AOI
modisLevel1.DegreeNumbers = degreeNumbers
modisLevel1.save()
#Inside a loop
f = FileProperties()
f.FileID = fileID
f.FileName = fileName
f.Updated = updated
f.GeoBox = geoBox
f.FileSize = fileSize
f.save()
modisLevel1.filesProperties.add(f)
serializer = MODISLevel1Serializer(data=modisLevel1)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
the error that i got is:
{
"non_field_errors": [
"Invalid data"
]
}
but for sure it's added in the database as I executed the save command "modisLevel1.save()", but that's not what I need.
2-Creating a json file and appending the 'filesProperties' to it through the iteration:
jsonFile = {u"ProductLevel": productLevel, u"SpacecraftType": spacecraftType, u"StartTimespan": startTimespan,
u"EndTimespan":endTimespan, u"AOI": AOI, u"DegreeNumbers": u"POINT(22.5,28.34) POINT(28.64,28.34) POINT(29.4,19.16) POINT(19.19,19.3067)",
u"filesProperties": [] }
#inside the loop
jsonFile["filesProperties"].append({u"FileName":fileName, u"FileID":fileID, u"FileSize":fileSize, u"Updated":updated, u"GeoBox":geoBox})
serializer = MODISLevel1Serializer(data=jsonFile)
and this one throws an error that the base model has to have a value before setting the m2m field:
Cannot add "": instance is on database "default", value is on database "None"
3-Create a dict and parse the Model to this dictionary, and then convert the FileProperties to the dictionary and append it to the previously created one:
modisLevel1 = MODISLevel1()
modisLevel1.ProductLevel = productLevel
modisLevel1.SpacecraftType = spacecraftType
modisLevel1.StartTimespan = startTimespan
modisLevel1.EndTimespan = endTimespan
modisLevel1.AOI = AOI
modisLevel1.DegreeNumbers = degreeNumbers
modisLevel1.save()
dict = model_to_dict(modisLevel1)
#FIXME!
dict['filesProperties'] = [{"FileName": "fileName", "FileID": "fileID", "FileSize": "fileSize", "Updated": "updated", "GeoBox": "geoBox"},
{"FileName": "fileName", "FileID": "fileID", "FileSize": "fileSize", "Updated": "updated", "GeoBox": "geoBox"},
{"FileName": "fileName", "FileID": "fileID", "FileSize": "fileSize", "Updated": "updated", "GeoBox": "geoBox"}]
serializer = MODISLevel1Serializer(data=dict)
and this one throws the same error as the previous one.
I did check some other posts that might be close to this issue, but none of them did work with me:
django rest nested relation in post/put
My json post request looks like the following:
[
{
"ProductLevel": "MOD03",
"SpacecraftType": "Terra",
"StartTimespan": "2013.11.02",
"EndTimespan": "2013.11.02",
"AOI": "swath",
"DegreeNumbers": "POINT(22.5,28.34) POINT(28.64,28.34) POINT(29.4,19.16) POINT(19.19,19.3067)"
}
]
Please notice that in the 'view.py' file I am able to store values in the database but if I bypass the serializer, like the examples that I've shown above.
So did somebody been through the same problem and know how to get this fixed? will be appreciated!