I want to post a data in a serializer, having 2 ForeignKey.
I have these models:
class Child(models.Model):
first_name = models.CharField(max_length=40)
description = models.CharField(max_length=40)
class Parent(models.Model):
name = models.CharField(max_length=20)
pet = models.ForeignKey(pet)
child = models.ForeignKey(Child, related_name='boys')
class Pet(models.Model):
kind = models.CharField(max_length=40)
------------------,
Class PetSerializer(ModelSerializer):
class Meta:
model = Pet
fields = ('kind',)
class ParentSerializer(ModelSerializer):
pet = PetSerializer(many=True):
class Meta:
model = Parent
fields = ('name', 'pet')
class ChildSerializer(ModelSerializer):
boys = ParentSerializer()
class Meta:
model = Child
fields = ('first_name', 'boys')
My first question: Is it possible to get the output as:
{
"first_name": "Peter",
"boys": [
{
"name": "Bill",
"kind": "dog"
}
]
}
My second question:And I am trying to send data to create a new model, by using this method:
def create(self, validated_data):
clean_data = validated_data.pop('boys')
child = Child.objects.create(**validated_data)
for data in clean_data:
Parent.objects.create(child=child, **data)
return child
But I got this error: TypeError: Direct assignment to the reverse side of a related set is prohibited. Use boys.set() instead.
Just for your first question, you can use source parameter in your ParentSerializer class:
class ParentSerializer(ModelSerializer):
kind = serializers.CharField(source='pet.kind'):
class Meta:
model = Parent
fields = ('name', 'kind')
Related
There are 2 models Property and Relationship. I am trying to eagerload Relationship from Property whereIn relationship.id = array of ids.
My code is as follows:
Property Model
public function relationship_items()
{
return $this->hasMany(Relationship::class, 'property_id', 'id');
}
Relationship Model
public function property()
{
return $this->belongsTo(Property::class, 'id', 'property_id');
}
Eloquent
$properties = Property::when($request->relationship_id, function ($q) use ($request) {
$q->whereHas("relationship_items", function ($q) use ($request) {
$q->whereIn("relationship_id", $request->relationship_id);
});
})->get();
In my whereIn function, I think mysql is trying to do where in id = ([....]), etc. Because of this, If I input ids [1,2,3], eloquent will fetch relationship data even if it has only id "1". I want to only get all relationships if and only if it has all the ids.
I have an interface type with many implementation classes. I can serialize/deserialize this either by
#JsonDeserialize(using = AlarmStateDeserializer.class)
#JsonSerialize(using = AlarmStateSerializer.class)
#JsonTypeInfo( use = JsonTypeInfo.Id.NONE)
public interface AlarmState
{
:
or
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(value = AcknowledgedState.class, name = "acknowledged"),
#JsonSubTypes.Type(value = ActivatedState.class, name = "activated"),
#JsonSubTypes.Type(value = DeactivatedState.class, name = "deactivated"),
#JsonSubTypes.Type(value = BlockedState.class, name = "blocked"),
#JsonSubTypes.Type(value = ReactivatedState.class, name = "reactivated"),
#JsonSubTypes.Type(value = DisabledState.class, name = "disabled"),
#JsonSubTypes.Type(value = NormalState.class, name = "normal"),
})
and that works fine when I seralize/deserialize the AlarmState directly in the ObjectMapper.
BUT, if I include the AlarmState as a property in another type, it insists to have a type for that field.
I have tried just about every other way I can think of, but for instance;
#JsonTypeInfo( use = JsonTypeInfo.Id.NONE )
#JsonDeserialize(as = AlarmImpl.class)
public interface Alarm
{
AlarmState getState();
:
(It doesn't matter if I deserialize the AlarmImpl directly either, same result)
And I will get the following exception;
Could not resolve subtype of [simple type, class com.sensetif.pipes.alarms.AlarmState]: missing type id property 'type' (for POJO property 'state')
I have also tried to put all kinds of annotations on the getState() method, but to no prevail.
FTR; the json in question is;
{
"labels": [],
"state": {
"name": "normal",
"description": "Normal state indicates everything is fine.",
"creationTime": "1970-01-01T00:00:00Z"
},
"counter": 0,
"name": "niclas1",
"description": null,
"condition": false,
"alarmClass": "C",
"organization": 0,
"parameters": null
}
How can it be that the underlying type deserializes fine, but not when it is part of an outer object??
I'm trying to work with inheritance. I have three models
class Animal {string name;}
class Cat : Animal {int meowPerHour}
class Dog : Animal {bool mixedBreed}
Ef core has created a Discriminator column and I can list Cats or Dogs seperately and I can create new items.
The problem is that I'd like to list both all animals with their respective unique properties. E.g. if the row is a Cat, print meowPerHour. But the mewPerHour is not a property or method in the Animal Class. I'm using the code below to print all animals.
public IList<Animal> Aniamls { get;set; }
public async Task OnGetAsync()
{
Animals = await _context.Animal.ToListAsync();
}
How may I solve this?
You can use following approach but be careful about this approach is eagerly loading all Animals and may not be suits best for all your cases.
public IEnumerable<IAnimal> GetAllAnimals()
{
List<IAnimal> allAnimals = GetAllEntriesByEntityInterface<IAnimal>();
return allAnimals;
}
Method for combining all entitties in one list
private List<T> GetAllEntries<T>() where T : class
{
List<IQueryable<T>> sets = typeof(T).IsInterface ? GetAllSetsByInterface<T>() : GetAllSetsByBaseClass<T>();
List<T> allEntries = new List<T>();
foreach (var item in sets)
{
allEntries.AddRange(item.ToList());
}
return allEntries;
}
Here we are gettings all Sets of entities implementing generic class of T. This method may be useful if you need to work with Interfaces.
private List<IQueryable<T>> GetAllSetsByInterface<T>() where T : class
{
var types = context.Model.GetEntityTypes().Select(t => t.ClrType).ToList().Where(t => t.GetInterfaces().Any(i => i == typeof(T))).ToList();
var sets = types.Select(type =>
context.GetType()
.GetMethod("Set")
.MakeGenericMethod(type)
.Invoke(context, null)
as IQueryable<T>
).ToList();
return sets;
}
And method for fetching all Sets of entities derived from generic class of T
private List<IQueryable<T>> GetAllSetsByBaseClass<T>() where T : class
{
var types = context.Model.GetEntityTypes().Select(t => t.ClrType).Where(x => x.IsSubclassOf(typeof(T))).ToList();
var sets = types.Select(type =>
context.GetType()
.GetMethod("Set")
.MakeGenericMethod(type)
.Invoke(context, null)
as IQueryable<T>
).ToList();
return sets;
}
I would like to render partial response using Akka HTTP. In the request the client should specify which fields to include in the response (e.g. using a fields request parameter, for example: https://www.acme.com/api/users/100?fields=id,name,address).
I would appreciate any pointers on how to solve this.
Akka http provides a useful DSL known as Directives to solve these types of problems. You can match on a particular path and then extract the HttpRequest query string for the "fields" key:
import akka.http.scaladsl.server.Directives._
val route = get {
path("api" / "users" / IntNumber) { pathInt =>
parameter('fields) { fields =>
complete(generateResponse(pathInt, fields))
}
}
}
For the given example request ("https://www.acme.com/api/users/100?fields=id,name,address") the generateResponse function will be called with 100 and id,name,address as the input variables. Say you have some lookup table of the values:
case class Person(id : String, name : String, address : String, age : Int)
val lookupTable : Map[Int, Person] = ???
You can then use this lookup table to get the person and extract the appropriate fields:
def personField(person : Person)(field : String) = field match {
case "id" => s"\"id\" = \"${person.id}\""
case "name" => s"\"name\" = \"${person.name}\""
...
}
//generates JSON responses
def generateResponse(key : Int, fields : String) : String = {
val person = lookupTable(key)
"{ " +
fields
.split(",")
.map(personField(person))
.reduce(_ + " " + _)
+ " }"
}
this is my Model:
public class UserDetails
{
public string UserName { get; set; }
public virtual Category Category { get; set; }
}
this is my query to fetch user details along with category:
var data = (from temp in context.UserDetails.Include("Category") select temp).OrderBy(c => c.UserId);
this is how i am accessing on controller:
List<UserDetails> staffDetails = staffBal.fetchStaffDetails();
var categoryModel = new CategoryModel();
Data = staffDetails.Select(x =>
{
var userDetailModel = new UserDetailsModel();
userDetailModel.UserId = x.UserId;
userDetailModel.FName = x.FName;
categoryModel.CategoryName = x.Category.Name;//i am getting error on this line.object reference not set to instance of object
can anybody tell me what is the solution???
You say in your comment: for some records it is coming null for some records it is not null meaning that x.Category is null. Therefore, any attempt to access x.Category.Name will fail. Change the line to this:
categoryModel.CategoryName = x.Category == null ? "" : x.Category.Name;