How to apply filters to extra fields from model serializer that are not in the model with django Rest - django-rest-framework

We have the SecurityEventItem that have the owner taken from another security_location model and returned.
The logic behind not having security_location direct as a foreign key is that we get events with security_location names that are not added yet to database, but we want them to be registered without adding the missing security location to the database.
class SecurityEventItemGetSerializer(serializers.ModelSerializer):
epc = RfidTagNestedSerializer()
owner = serializers.SerializerMethodField('get_owner')
def get_owner(self, member):
location = SecurityLocationSerializer(models.SecurityLocation.objects.get(name=member.security_location)).data
owner_name = ProductOwnerSerializer(models.ProductOwner.objects.get(id=location["owner"])).data
return owner_name["owner_name"]
class Meta:
model = models.SecurityEventItem
fields = ["id", "epc", "acknowledged", "firstSeenTimestamp", "security_location", "owner"]
The ViewSet bellow
class SecurityEventItemGetViewset(viewsets.ModelViewSet):
"""SecurityEventItemGet Viewset
API endpoint that allows security event items to be viewed.
Allowed actions:
"GET"
"""
queryset = models.SecurityEventItem.objects.all()
serializer_class = serializers.SecurityEventItemGetSerializer
http_method_names = ['get']
filter_backends = [DjangoFilterBackend]
search_fields = ["owner"]
filterset_fields = {
'acknowledged': ['exact'],
'epc': ['exact', "in"],
'security_location': ['exact', "in"],
'firstSeenTimestamp': ['gte', 'lte'],
}
I have tryed SearchFilter unsuccesfull as simillar to DjangoFilterBackend it does not recognize the owner field added that does not belong to the SecurityEventItem model.
The response is like this: and I would like to make a filter on the request passing a parameter "owner" added to the existing ones.
[
{
"id": 73,
"epc": {
"id": 8371,
"number": "1234",
"product": {
"id": 1,
"name": "default_product",
"ean": "",
"description": "default product for foreign/unknown RFID tags",
"category": {
"id": 1,
"name": "default_category",
"description": "default category for foreign/unknown RFID tags"
},
"info": []
},
"state": 1,
"info": [],
"owner": {
"id": 1,
"owner_id": 1,
"owner_name": "George"
}
},
"acknowledged": false,
"firstSeenTimestamp": "2022-02-21T09:44:08",
"security_location": "Test Location",
"owner": "Second Owner"
},
{
"id": 72,
"epc": {
"id": 105177,
"number": "303625D4580B2484000002CA",
"product": {
"id": 590,
"name": "A78R07",
"ean": "5940000792305",
"description": "Fata de perna 50x70",
"category": {
"id": 1,
"name": "default_category",
"description": "default category for foreign/unknown RFID tags"
},
"info": "{\"company\": \"HOTEL Nr1\"}"
},
"state": 1,
"info": [],
"owner": {
"id": 1,
"owner_id": 1,
"owner_name": "Regina"
}
},
"acknowledged": false,
"firstSeenTimestamp": "2022-02-21T09:31:16",
"security_location": "Front Desk",
"owner": "Second Company"
}
]
I would really appreciate if someone could teach me how to do that, there are plenty of information regarding model filtering, but no filters for the filters added to extra fields

SerializerMethodField is read-only.
This field is generated only at the time of serialization and does not exist in the database.
Filters work only with the database, but the owner field is not there.
I think you should annotate the queryset with the data you want (.annotate(owner=...), Subquery() ), then the filter can work because that field will be returned from the database.

Related

DRF Serailze Parent-Child Relation models

I have Parent-Children Relation Table in Model which is as follows:
models.py
class ProductCategory(models.Model):
parent = models.ForeignKey(to='ProductCategory', blank=True, null=True, related_name="sub_cats", on_delete=models.CASCADE)
name = models.CharField(max_length=30, blank=False, null=False)
desc = models.TextField(blank=True, null=True, db_column='description')
def __str__(self):
return self.name
Data in table
Using this data I want to make a tree in react component where a user see how many types of categories a product has.
right now getting this
[
{
"id": 1,
"parent": null,
"name": "Electronics",
"desc": "All kinds of electronics items comes in this category",
"sub_cats": [
{
"id": 2,
"parent": 1,
"name": "Mobiles",
"desc": "Category for Smartphones, Features-Phone, etc.",
"sub_cats": [3]
}
]
},
{
"id": 2,
"parent": 1,
"name": "Mobiles",
"desc": "Category for Smartphones, Features-Phone, etc.",
"sub_cats": [
{
"id": 3,
"parent": 2,
"name": "X-Mobile",
"desc": "All Smartphones of X-Mobile",
"sub_cats": []
}
]
},
{
"id": 3,
"parent": 2,
"name": "X-Mobile",
"desc": "All Smartphones of X-Mobile",
"sub_cats": []
}
]
or any other idea for making tree

How do i customize the response gotten from python "djoser" package when creating a user

I had to override the serializer to make some changes, but after successful creation/registration, I want to customize the output
Serializer override
class RegisterSerializer(UserCreatePasswordRetypeSerializer):
first_name = serializers.CharField(max_length=100)
last_name = serializers.CharField(max_length=100)
class Meta(UserCreatePasswordRetypeSerializer.Meta):
model = get_user_model()
# add extra fields to the "djoser" default fields
fields = UserCreatePasswordRetypeSerializer.Meta.fields + ("first_name", "last_name")
output
{
"email": "test14#user.com",
"id": 17,
"first_name": "reni",
"last_name": "brake"
}
desired output
{
"data": {
"email": "test14#user.com",
"id": 17,
"first_name": "reni",
"last_name": "brake"
},
"success": True
}

Access control at property level (hiding/showing properties in api response based on the role)

I have a spring-boot based micro-service generated using JHipster.
I am using keycloak as my Auth Server. I could enable Role-based & scope based authorization on my resources(apis).
Now the requirement is: based on the role of the client, I need to restrict the information to send in the response (either mask the attributes or nullify them).
eg:
consider the following api to get the person's profile
/api/person/{id}
{
"name": {
"firstName": "Jack",
"lastName": "Sparrow"
},
"gender": "MALE",
"emails": {
"details": [
{
"emailId": "jack.sparrow#gmail.com"
}
]
},
"phones": {
"details": [
{
"phoneNumber": "1234567890",
"countryCode": "+1"
}
]
},
"addresses": {
"details": [
{
"addressLine1": "aaaaaaaa",
"addressLine2": "bbbbbbb",
"city": "cccccc",
"state": "ddddd",
"country": "South Africa",
"postalCode": "987654"
}
]
},
"photo": "string",
"nationality": "South Africa",
"countryOfResidence": "string",
"active": true,
"createdAt": 1537431339569,
"modifiedAt": 1537436600693,
"createdBy": "admin",
"modifiedBy": "admin"
}
Now, when a person with BASIC role calls this API, the requirement is to show only basic information like:
- name, gender
If he has INTERMEDIATE role then we can send something more than basic but not full information. eg: name, gender, photo, nationality
If he has ADMIN role then we can send the complete information.
Can anyone please let me know What is the best approach to achieve this.
-- Thanks in advance :)

How to simulate multiple child elements with different values in the same Jmeter POST request body?

The below request being the base request,
[
{
"name": "Test1",
"description": "testings",
"unitname": simple,
"ID": 02,
"val": "item"
},
{
"name": "Test2",
"description": "testing",
"unitname": simple3,
"ID": 23,
"val": "item"
}
]
I want to simulate this with multiple (1000) 'child' sections like the below in a single JMeter request:
It should create 1000 data set(name,description,unitname,ID,val) with unique values and then post the request. Instead of manually creating multiple tags, can i automate it or create a script to generate this automatically ?
[
{
"name": "Test1",
"description": "testings",
"unitname": simple,
"ID": 02,
"val": "item"
},
{
"name": "Test2",
"description": "testing",
"unitname": simple3,
"ID": 23,
"val": "item"
}
{
"name": "Test3",
"description": "testing",
"unitname": simple4,
"ID": 23,
"val": "item"
}
{
"name": "Test4",
"description": "testing",
"unitname": simple6,
"ID": 23,
"val": "item"
}
]
Any help please?
Add JSR223 PreProcessor as a child of your request where you need to send the generated JSON
Put the following code into "Script" area:
import groovy.json.JsonBuilder
import groovy.json.internal.LazyMap
import org.apache.commons.lang3.RandomStringUtils
def data = new ArrayList()
1.upto(1000, {
def entry = new LazyMap()
entry.put('name', 'test' + it)
entry.put('description', RandomStringUtils.randomAlphabetic(10))
entry.put('unitname', 'simple')
entry.put('ID', it)
entry.put('val', 'item')
data.add(entry)
})
def builder = new JsonBuilder()
builder(
data.collect {
[
name : it.get('name'),
descrtiption: it.get('description'),
unitname : it.get('unitname'),
ID : it.get('ID'),
val : it.get('val')
]
}
)
sampler.setPostBodyRaw(true)
sampler.addNonEncodedArgument("", builder.toPrettyString(), "")
Tick Cache compiled script if available box
Make sure groovy is selected in "Language" dropdown
That's it, the above script will generate a JSON Array and set it as the HTTP Request sampler's body.
More information:
Groovy: Parsing and producing JSON
Apache Groovy - Why and How You Should Use It

Laravel eager loading with field limit

I have three tables:
users
id
name
role_id
password
...
role_user
id
role_id
user_id
roles
id
name
slug
...
Now I want to get a user list with users.id,users.name,
roles.id. That's my code:
$query = User::with(['roles'=>function($q){
$q->lists('role_id');
}])->get(['id','name']);
the response like that
{
"id": "1",
"name": "aaaa",
"roles": []
},
{
"id": "2",
"name": "bbbb",
"roles": []
},
when i don't pass the array to get method,the response like that:
{
"id": 1,
"name": "aaaa",
"password": "xxxxxxx",
"created_at": "2015-05-07 14:15:00",
"roles": [
{
"role_id": 2,
"pivot": {
"user_id": 1,
"role_id": 2
}
}
]
},
{
"id": 2,
"name": "bbbb",
"password": "xxxxxxx",
"created_at": "2015-05-05 14:15:00",
"roles": [
{
"role_id": 2,
"pivot": {
"user_id": 2,
"role_id": 2
}
}
]
},
But i do not want the password,created_at and pivot field. How to filter these?
To get relations you need to get the foreign keys. Try this
$query = User::with(['roles'=>function($q){
$q->get(['id', 'name', 'slug']);
}])->get(['id','name', 'role_id']);
As for the pivot table, can you post you roles relation in the user model?
Edit
Add this to your user model to hide the pivot properties
protected $hidden = ['pivot'];
You can add more fields to that property to remove them from all queries.

Resources