Django REST Meta data for M2M missing - django

On my json output I don't seem to get key value pairs on my m2m field attribute_answers. see the code below. How to I add in the attribute_answers fields?
json
{
"id": 20,
"name": "Jake",
"active": true,
"type": {
"id": 1,
"name": "Human",
"active": true,
"created": "2013-02-12T13:31:06Z",
"modified": null
},
"user": "jason",
"attribute_answers": [
1,
2
]
}
Serializer
class ProfileSerializer(serializers.ModelSerializer):
user = serializers.SlugRelatedField(slug_field='username')
attribute_answers = serializers.PrimaryKeyRelatedField(many=True)
class Meta:
model = Profile
depth = 2
fields = ('id', 'name', 'active', 'type', 'user', 'attribute_answers')
def restore_object(self, attrs, instance=None):
"""
Create or update a new snippet instance.
"""
if instance:
# Update existing instance
instance.name = attrs.get('name', instance.name)
instance.active = attrs.get('active', instance.active)
instance.type = attrs.get('type', instance.type)
instance.attribute_answers = attrs.get('attribute_answers', instance.attribute_answers)
return instance
# Create new instance
return Profile(**attrs)

If I understand your question correctly, you want a Nested Relationship. In your ProfileSerializer, you'll want:
attribute_answers = AttributeAnswerSerializer(many=True)
This will display all the attributes of each associated attribute_answer model and give you something like:
{
"id": 20,
"name": "Jake",
"active": true,
"type": {
"id": 1,
"name": "Human",
"active": true,
"created": "2013-02-12T13:31:06Z",
"modified": null
},
"user": "jason",
"attribute_answers": [
{"id": 1, "foo": "bar"},
{"id": 2, "foo": "bar2"}
]
}

Related

How to change DRF API SlugRelatedField Response template

I have managed to create a working model with 2 different serializers, depending on what we are doing. Right now, ReadTitleSerializer returns the below JSON object:
[
{
"id": 1,
"category": {
"id": 1,
"name": "Movies",
"slug": "movie"
},
"genres": [
{
"id": 1,
"name": "Drama",
"slug": "drama"
}
],
"name": "Drama Llama",
"year": "1998-02-02",
"description": null,
"rating": null
}
]
And this is the response from WriteTitleSerializer:
{
"id": 1,
"category": "movie",
"genres": [
"drama"
],
"name": "Drama Llama",
"year": "1998-02-02",
"description": null,
"rating": null
}
How can I make WriteTitleSerializer respond similarly to ReadTitleSerializer? I am using SlugRelatedField in WriteTitleSerializer because the JSON input should be a list of slugs.
Input JSON
{
"name": "Drama Llama",
"year": "1998-02-02",
"category": "movie",
"genres": [
"drama"
]
}
serializers.py
class ReadTitleSerializer(serializers.ModelSerializer):
category = CategorySerializer()
genres = GenreSerializer(many=True)
class Meta:
model = Title
fields = '__all__'
read_only_fields = ('category', 'genres')
class WriteTitleSerializer(serializers.ModelSerializer):
category = SlugRelatedField(
slug_field='slug',
queryset=Category.objects.all(),
required=True
)
genres = SlugRelatedField(
slug_field='slug',
queryset=Genre.objects.all(),
many=True,
required=True
)
class Meta:
model = Title
fields = '__all__'

How can i group by all data according to model in DRF?

Currently, I am working on a DFR project where can successfully get all data but i need some modify with the json data.
Here Is the code
class PermissionSerializers(serializers.ModelSerializer):
class Meta:
model = Permission
fields = ['id', 'name', 'codename']
def to_representation(self, instance):
return {
'model': instance.content_type.name,
'data' :{
'id': instance.id,
'name': instance.name,
'codename': instance.codename,
}
}
And i get this JSON format,
{
"next": "http://127.0.0.1:8000/en/ga/api-version/common/admin/permissions/?page=4",
"previous": "http://127.0.0.1:8000/en/ga/api-version/common/admin/permissions/?page=2",
"total": 33,
"page": 3,
"page_size": 10,
"results": [
{
"model": "user",
"data": {
"id": 25,
"name": "Can add user",
"codename": "add_user"
}
},
{
"model": "user",
"data": {
"id": 29,
"name": "Admistrative Access",
"codename": "admin_access"
}
},
But I want to modify with something like this which has model name on top and then all available data inside a dictionary:
{
"model": "user",
"data": {
"id": 26,
"name": "Can change user",
"codename": "change_user"
},
{
"id": 25,
"name": "Can add user",
"codename": "add_user"
},
},
You get something like this because you have pagination in your API, if you don't want it just disable pagination.
I came up with this solution:
def list(self, request):
_models_list = [
'organization','user','group', 'logentry', 'organizationtype',
'keyword', 'productsupport','feedbacksupport','twittercredential']
models = ContentType.objects.filter(model__in = _models_list)
model_dict = {
'model': '',
'data':''
}
results = []
for model in models:
_permissions = []
access = ' Access'
if model.model == 'group':
model_dict['model'] = 'Role'+ access
elif model.model == 'organizationtype':
model_dict['model'] = 'Organization Type'+ access
elif model.model == 'productsupport':
model_dict['model'] = 'Product'+ access
elif model.model == 'feedbacksupport':
model_dict['model'] = 'Feedback'+ access
else:
model_dict['model'] = model.model.capitalize()+ access
permissions = Permission.objects.filter(content_type = model)
for premission in permissions:
_permissions.append(premission)
serializer = PermissionSerializers(_permissions, many=True)
data = serializer.data
model_dict['data'] = data
results.append(model_dict.copy())
return Response(results)

How to serialize ForeignKey in Django rest?

I'm using the latest version of django rest framework.
I have this model:
class Subscriptions(models.Model):
subs_list = models.ForeignKey(SubsList, verbose_name='Subscription list', on_delete=models.CASCADE, related_name='subs_list') # идентификатор подписного листа
subscriber = models.ForeignKey(Subscribers, verbose_name='Subscriber', on_delete=models.CASCADE) # идентификатор подписчика
created_date = models.DateTimeField(verbose_name='Created date', auto_now=True) # дата добавления подписчика в подписной лист
deleted = models.NullBooleanField(verbose_name='Deleted') # True-удален из подписного листа, False/null-в подписном листе
How do I serialize it? The main question is how to serialize ForeignKey, that would be associated with the query related data, i.e. NOT:
"id": 29,
"created_date": "2018-03-01T14:28:41.237742Z",
"deleted": false,
"subs_list": 1,
"subscriber": 1
but like this
"id": 29,
"subs_list": {
"id": 1,
"uuid": "d183bab7-af26-48f8-9ef5-ea48e09a95a9",
"name": "TEST",
"description": "TEST",
"created_date": "2018-03-01T13:15:18.808709Z",
"deleted": null,
"user": 6
},
"subscriber": {
"id": 1,
"bot_id": "1",
"name_messenger": "11",
"username": "1",
"first_name": "1",
"last_name": "1",
"created_date": "9999-03-01T16:47:51.440000Z",
"subscribed": true,
"chat_bot": "1",
"phone": "1",
"user": 1
},
"created_date": "2018-03-01T14:28:41.237742Z",
"deleted": false
I have such a serializer:
...
class SubscriptionsSerializer(serializers.ModelSerializer):
subs_list = SubsListSerializer(read_only=True)
subscriber = SubscribersSerializer(read_only=True)
class Meta:
model = Subscriptions
fields = '__all__'
When get requests everything is ok, but how to update and add data is not clear, error:
IntegrityError at /subscriptions/subscriptions/
null value in column "subs_list_id" violates not-null constraint
DETAIL: Failing row contains (41, 2018-03-01 16:10:02.383625+00, f, null, null).
I struggle with this problem for a very long time, read all the related answers, but there is no clarity.
remove read_only=True and change your serializer.py as below
class SubscriptionsSerializer(serializers.ModelSerializer):
subs_list = SubsListSerializer()
subscriber = SubscribersSerializer()
class Meta:
model = Subscriptions
fields = '__all__'
def create(self, validated_data):
sub_lst = SubsList.objects.create(**validated_data['subs_list'])
subscriber = Subscribers.objects.create(**validated_data['subscriber'])
return Subscriptions.objects.create(subs_list=sub_lst, subscriber=subscriber, deleted=validated_data['deleted'])
And your creation payload will be like this,
{
"subs_list": {
"uuid": "d183bab7-af26-48f8-9ef5-ea48e09a95a9",
"name": "TEST",
"description": "TEST",
# etc etc
},
"subscriber": {
"bot_id": "1",
"name_messenger": "11",
"username": "1",
# etc etc
},
"deleted": null
}
I think you have several ForeignKey relationships are there, so you have to map those things carefully in create()
Similar way, you can override update() and which can be used while API updation too.
See this official doc for more info

Distinct field Rest Framework Django

I need to make a distinct with a field of my model and not how to make
My model is:
class CheckList(CoreModel):
date = models.DateTimeField(default=datetime.now, blank=True, null=True, verbose_name=_('Date'))
establishment = models.ForeignKey(Establishment, related_name="checklists", on_delete=models.CASCADE, null=True, verbose_name=_('Establishment'))
user = models.ForeignKey(ITManager, related_name="checklists", on_delete=models.CASCADE, null=True, verbose_name=_('User'))
class Meta:
verbose_name_plural = _("Checklist")
verbose_name = _("Checklists")
def __str__(self):
return str(self.date)
My serializer and view:
class CheckListSerializer(BulkSerializerMixin, serializers.ModelSerializer):
user = ITManagerSerializer()
class Meta:
model = CheckList
list_serializer_class = BulkListSerializer
fields = ['id', 'user', 'establishment', 'date']
class ChecklistBulkViewSet(BulkModelViewSet):
queryset = CheckList.objects.values('establishment', 'user', 'date').distinct()
model = CheckList
serializer_class = CheckListSerializer
filter_class = ChecklistFilter
The api return me:
"results": [
{
"id": 1,
"user": {
"id": 3,
"first_name": "Andres",
"last_name": "Gallardo",
"rut": "21312",
"email": null,
"user_name": "andres",
"password": null,
"user": 4,
"country": [],
"active": true
},
"establishment": 3,
"date": "2016-06-14T15:15:00Z"
},
{
"id": 2,
"user": {
"id": 2,
"first_name": "Ramiro",
"last_name": "Gutierrez",
"rut": "15616+",
"email": null,
"user_name": null,
"password": null,
"user": 2,
"country": [
{
"id": 1,
"name": "Argentina",
"code_area": null
}
],
"active": false
},
"establishment": 3,
"date": "2016-06-09T15:40:04Z"
}]
I need you just leave me an establishment with the same id
any suggestions??
Thanks !

Django Tastypie - How to get related Resources with a single request

Suppose following Resources are given:
class RecipeResource(ModelResource):
ingredients = fields.ToManyField(IngredientResource, 'ingredients')
class Meta:
queryset = Recipe.objects.all()
resource_name = "recipe"
fields = ['id', 'title', 'description',]
class IngredientResource(ModelResource):
recipe = fields.ToOneField(RecipeResource, 'recipe')
class Meta:
queryset = Ingredient.objects.all()
resource_name = "ingredient"
fields = ['id', 'ingredient',]
A HTTP Request to myhost.com/api/v1/recipe/?format=json gives following response:
{
"meta":
{
...
},
"objects":
[
{
"description": "Some Description",
"id": "1",
"ingredients":
[
"/api/v1/ingredient/1/"
],
"resource_uri": "/api/v1/recipe/11/",
"title": "MyRecipe",
}
]
}
So far so good.
But now, I would like to exchange the ingredients resource_uri ("/api/v1/ingredient/1/") with something like that:
{
"id": "1",
"ingredient": "Garlic",
"recipe": "/api/v1/recipe/1/",
"resource_uri": "/api/v1/ingredient/1/",
}
To get following response:
{
"meta":
{
...
},
"objects":
[
{
"description": "Some Description",
"id": "1",
"ingredients":
[
{
"id": "1",
"ingredient": "Garlic",
"recipe": "/api/v1/recipe/1/",
"resource_uri": "/api/v1/ingredient/1/",
}
],
"resource_uri": "/api/v1/recipe/11/",
"title": "MyRecipe",
}
]
}
The answer is the attribute full=True:
ingredients = fields.ToManyField('mezzanine_recipes.api.IngredientResource', 'ingredients', full=True)