views.py
def districts_list(request):
obj_districts_list = Districts.objects.all()
data = serializers.serialize(
'json', obj_districts_list, fields=('district_name'))
return HttpResponse(data, content_type="application/json")
models.py
class Districts(models.Model):
id = models.AutoField(primary_key=True)
district_name = models.CharField(max_length=40)
country = models.ForeignKey('Country', on_delete=models.CASCADE)
state = models.ForeignKey('States', on_delete=models.CASCADE)
def __str__(self):
return '{}'.format(self.district_name)
OUTPUT:
But i just want the fields inside the Accounts.districts as output in JSON format.
Use QuerySet.values() to retrieve the fields you're interested in as dicts, then pass this to json.dumps(), ie:
>>> qs = User.objects.values("username", "first_name", "last_name", "email", "userprofile__nickname")
>>> print(json.dumps(list(qs), indent=2))
[
{
"username": "toto",
"first_name": "",
"last_name": "",
"email": "toto#example.com",
"userprofile__nickname": "Toto le toto"
},
{
"username": "root",
"first_name": "Root",
"last_name": "Root",
"email": "root#example.com",
"userprofile__nickname": "Root"
},
]
Depending on your models fields, you may have to provide a custom JSONDecoder subclass for datetimes and other types not directly handled by the default JSONEncoder.
Related
The Customer class has a foreign key to User class. I want to return this information but I don't want to show user__ before username, first_name, etc.
data = {"customers": list(p.values("id", "user__username", "user__first_name",
"user__last_name", "user__email", "phone",
"address", "balance"))}
How can I get something like that:
{
"customers": [
{
"id": 12,
"username": "leon2",
"first_name": "lee",
"last_name": "michalson",
"email": "hamed#example.com",
"phone": "042-22334455",
"address": "Tehran, No.1",
"balance": 20000
}
]
}
Use annotate:
from django.db.models import F
for field in ('username', 'first_name', 'last_name', 'email'):
p = p.annotate(**{field: F('user__' + field)})
data = {"customers": list(p.values("id", "username", "first_name",
"last_name", "email", "phone",
"address", "balance"))}
I'm trying to create a serializer which outputs the Report and also the User information.
My task is accomplished by this serializer:
class ReportSerializer(serializers.ModelSerializer):
latitude = serializers.CharField()
longitude = serializers.CharField()
city = serializers.IntegerField()
type = serializers.IntegerField()
# We have created a field which returns a value from get_marker_icon_url
marker_icon = serializers.SerializerMethodField('get_marker_icon_url')
status_str = serializers.SerializerMethodField('convert_status_toStr')
type_str = serializers.SerializerMethodField('convert_type_toStr')
status_color = serializers.SerializerMethodField('get_status_color')
likes = serializers.SerializerMethodField('random_likes')
user = ReportUserSerializer()
class Meta:
model = Reports
fields = [
'user',
'id',
'type',
'city',
'latitude',
'longitude',
'likes',
'type_str',
'status_str',
'status_color',
'attached_message',
'marker_icon',
'attached_photo',
'date_created'
]
...
With this code my serializer returns a response like this:
[
{
"user": {
"id": 1,
"username": "3nematix",
"profile_pic": "http://192.168.0.29:8000/frontend/static/frontend/images/reports/user_profile_pic.jpg",
"verified": false
},
"id": 1,
"type": 9,
"city": 0,
"latitude": "6.5123333",
"longitude": "51.512586",
"likes": 27,
"type_str": "OTHER",
"status_str": "PENDING",
"status_color": "orange",
"attached_message": "test",
"marker_icon": "OTHER",
"attached_photo": "http://192.168.0.29:8000/frontend/static/frontend/images/reports/user_profile_pic_VRjIYTs.jpg",
"date_created": "2020-10-21T23:19:06.899302Z"
},
......
]
And this is exactly what I need, but the problem is that when I'm trying to create a new object by a POST request, I get this response:
{
"user": [
"This field is required."
]
}
If I would remove 'user' from Meta and user = ReportUserSerializer() from the ReportSerializer class, then I can create a new object, but when I wish to get the Reports I with the Users information I need to add these two again, how can I fix it?
You need to fill the user field yourself before calling save.
Here's the easy way:
class YourView(generics.ListCreateAPIView):
...
def perform_create(self, serializer):
serializer.save(user=self.request.user)
Or slightly differently:
class YourView(generics.ListCreateAPIView):
...
def perform_create(self, serializer):
serializer.validated_data['user'] = self.request.user
return super().perform_create(serializer)
I'm trying to make custom create()method to save my user profile when a User is created, the serializer works perfect for the GET method, but for POST it only shows one field instead of all fields.
I specified the fields = '__all__' property, but still don't work
GET:
JSON Response:
[
{
"job_title": {
"id": 1,
"name": "Desarrollador"
},
"birthdate": "2019-11-06",
"roles": [
{
"id": 1,
"name": "Administrador",
"description": "Administrador del sistema",
"key": "ADMIN"
}
]
}
]
POST:
Expected JSON:
[
{
"birthdate": "2019-11-06",
}
]
Serializers:
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = '__all__'
depth = 1
class UserSerializer(serializers.ModelSerializer):
user_profile = UserProfileSerializer(read_only=False, many=False)
class Meta:
model = User
fields = '__all__'
depth = 1
def create(self, validated_data):
profile_data = validated_data.pop('user_profile')
user = User.objects.create(**validated_data)
UserProfile.objects.create(user=user, **profile_data)
return user
views.py
class UserDetail(generics.RetrieveUpdateDestroyAPIView):
profile = serializers.PrimaryKeyRelatedField(many=False, queryset=UserProfile.objects.all())
queryset = User.objects.all()
serializer_class = UserSerializer
class UserProfileList(generics.ListCreateAPIView):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='user_profile', on_delete=models.CASCADE)
birthdate = models.DateField(default=datetime.date.today)
job_title = models.ForeignKey(JobTitle, related_name='job_title', on_delete=models.CASCADE)
roles = models.ManyToManyField(Role)
def createProfile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.created(user=kwargs['instance'])
post_save.connect(createProfile, sender=User)
def __str__(self):
return self.user.username
I need that POST method also requires the full JSON, the same as the GET JSON response, in order to complete the create method. Need this for POST method:
{
"id": 1,
"user_profile": {
"job_title": {
"id": 1,
"name": "Desarrollador"
},
"birthdate": "2019-11-06",
"roles": [
{
"id": 1,
"name": "Administrador",
"description": "Administrador del sistema",
"key": "ADMIN"
}
]
},
"password": "pbkdf2_sha256$150000$0XdmQpeiPtVl$rQh2MEYV+IO5Y4gm2o1md2cVzgn/mL95r6m1TvRmG3g=",
"last_login": "2019-11-06T00:34:25-06:00",
"is_superuser": true,
"username": "aruiz",
"first_name": "",
"last_name": "",
"email": "correo#correo.com",
"is_staff": true,
"is_active": true,
"date_joined": "2019-11-05T11:37:49-06:00",
"groups": [],
"user_permissions": []
}
I'm working with a legacy database which has 2 records, the data in each record contain the following values: Name, Email, Company, Phone
These 2 records contain the same data value except the value for Phone which is different.
When I retrieve them in JSON I get the following output:
"results": [
{
"Name": "Mack",
"Email": "Mack#email.com",
"Company": "Company Name",
"Phone": "123456789"
},
{
"Name": "Mack",
"Email": "Mack#email.com",
"Company": "Company Name",
"Phone": "1111111"
}
]
My question: As you can see there is some duplicate data in the output above, so is there a way to arrange the JSON output to the following:
"results": [
{
"Name": "Mack",
"Email": "Mack#email.com",
"Company": "Company Name",
"Phone": "123456789"
"Phone 2": "1111111"
}
]
Here is the code for Views.py file:
class DataView(viewsets.ModelViewSet):
queryset = DataList.objects.all()
serializer_class = DataSerializer
Here is the code for Serializers.py file:
class DataSerializer(serializers.ModelSerializer):
data_details = serializers.SerializerMethodField()
class Meta:
model = DataList
fields = 'data_details'
def get_data_details(self, obj):
return [{
'name': obj.name,
'email': obj.email,
'company': obj.company,
'phone': obj.phone,
}]
Here is the code for models.py file:
class Data(models.Model):
name = models.CharField(db_column='name', primary_key=True, max_length=50)
email = models.CharField(db_column='email', max_length=50)
company = models.CharField(db_column='company', max_length=100)
phone= models.TextField(db_column='phone')
class Meta:
managed = False
db_table = 'data_table'
Thank you.
I'm trying to implement two serializer classes which will allow me to create both user and profile objects from a flattened POST request.
I tried the implementation described here and it works perfectly fine for updating (and only updating) existing objects.
Here is my current implementation:
# serializers.py
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(
write_only=True, required=True, style={"input_type": "password"}
)
class Meta:
model = User
fields = (
"username",
"password",
# ...
"date_joined",
)
read_only_fields = ("date_joined")
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer()
def to_representation(self, instance):
representation = super().to_representation(instance)
representation.update(representation.pop("user"))
return representation
def to_internal_value(self, data):
user_internal = {}
for key in UserSerializer.Meta.fields:
if key in data:
user_internal[key] = data.pop(key)
internal = super().to_internal_value(data)
internal["user"] = user_internal
return internal
def create(self, validated_data):
user_data = validated_data.pop("user")
user = User.objects.create(**user_data)
user.set_password(user_data["password"])
user.save()
profile = UserProfile.objects.create(user=user, **validated_data)
return profile
class Meta:
model = UserProfile
fields = (
"user",
"date_updated",
# ...
"phone_number",
)
# views.py
class Register(generics.CreateAPIView):
serializer_class = UserProfileSerializer
name = "userprofile-create"
I expect the app to take the flattened JSON and create both user and profile objects.
Example POST body:
{
"username": "test_user",
"password": "P#$$w0rd",
"first_name": "Foo",
"last_name": "Boo",
"email": "foo#example.com",
"street": "Random Street",
"street_number": "11",
"flat_number": "11",
"zip_code": "11-111",
"city": "Some City",
"province": 1,
"phone_number": "111222333"
}
When I'm browsing through the API, the view still expects JSON with nested User object:
{
"user": {
"username": "",
"password": "",
"first_name": "",
"last_name": "",
"email": ""
},
"street": "",
"street_number": "",
"flat_number": "",
"zip_code": "",
"city": "",
"province": null,
"phone_number": ""
}
Overriding to_internal_value() and to_representation() wasn't correct approach.
I've created only one serializer with all fields and overriden create() method:
class UserProfileSerializer(serializers.ModelSerializer):
username = serializers.CharField(source="user.username")
password = serializers.CharField(
source="user.password",
write_only=True,
required=True,
style={"input_type": "password"},
)
first_name = serializers.CharField(source="user.first_name")
last_name = serializers.CharField(source="user.last_name")
email = serializers.EmailField(source="user.email")
def create(self, validated_data):
user_data = validated_data.pop("user")
user = User.objects.create(**user_data)
user.set_password(user_data["password"])
user.save()
profile = UserProfile.objects.create(user=user, **validated_data)
return profile
class Meta:
model = UserProfile
fields = (
"username",
"password",
"first_name",
"last_name",
"email",
"date_updated",
"street",
"street_number",
"flat_number",
"zip_code",
"city",
"province",
"phone_number",
)