Serializer for mongo models excluding specific related class type - serialization

Consider the following models:
class Line(Document):
name = StringField()
class Root(Document):
name = StringField()
children = ListField(fields=ReferenceField('RootContent'))
class RootContent(Document):
meta = { 'allow_inheritance': True }
class Directory(RootContent):
name = StringField()
children = ListField(fields=ReferenceField('RootContent'))
class File(RootContent):
name = StringField()
children = ListField(fields=ReferenceField('Line'))
I need a serializer using django-rest-framework-mongoengine that may provide me with all roots having all directories and files, but not lines. I may set a fairly large value of "depth". How do I write a serializer that does it?

Finally I ended up doing something like the following:
from rest_framework_mongoengine import serializers as mongo_serializers
class ChildField(mongo_serializers.serializers.Serializer):
def to_native(self, value):
return self.parent.to_native(value)
class TreeSerializer(mongo_serializers.MongoEngineModelSerializer):
name = mongo_serializers.fields.SerializerMethodField(method_name='get_name')
children = ChildField(many=True)
class Meta:
model = Root
def get_name(self, obj):
"""Mainly in to nullify children of
object"""
if isinstance(obj, File):
obj.children = []
return obj.name

Related

Django - id null - foreign key error

Error:
app_a.desc_id may not be NULL
I believe my problem is I'm not passing the id from formB to formA when I save. please please lead me to a solution for this problem.
Here's my view:
def form(request):
if request.method == 'GET':
formB = BForm()
formA = AForm()
return render(request,r'app/form.html',{'formA':formA,'formB':formB})
elif request.method == 'POST':
formA = AForm(request.POST)
formB = BForm(request.POST)
formB.save()
formA.save()
return HttpResponseRedirect('/log')
Here are my models:
# Descprition
class B(models.Model):
id = models.AutoField(primary_key=True)
description = models.CharField(max_length=50)
# Title
class A(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField('Name',max_length=20)
desc = models.ForeignKey(B)
and here is my form:
class BForm(forms.ModelForm):
class Meta:
model = B
fields = ['description']
class AForm(forms.ModelForm):
class Meta:
model = A
fields = ['name']
Your program has multiple errors but the main problem for this is because desc is a foreign key in class A that points to class B, and you don't have null=True on it, meaning you never want that field to be empty. In other words, each instance of A should have a foreign key desc.
If you just save() both forms, formA tries to save an instance of A, without having a value for desc field, hence the error. You should assign the instance that formB creates to the instance that formA creates:
new_b = formB.save()
new_a = formA.save(commit=False)
new_a.desc = new_b
new_a.save()
Other problems in your program including never called form.is_valid(), having redundant id fields(django would create one for you). I suggest you read django tutorial first before jumping into coding. It would save a lot of time like figuring out errors like this.

How to pass ActiveRecord model class to Resque

Let's say I have the following Resque job:
class Archive
#queue = :file_serve
def self.perform(repo_id, branch = 'master')
repo = Repository.find(repo_id)
repo.create_archive(branch)
end
end
What if I wanted to make this more generic by passing an object id and the object's class so that I can do something like this:
class Archive
#queue = :file_serve
def self.perform(object_class, object_id, branch = 'master')
object = object_class.find(object_id)
object.create_archive(branch)
end
end
This doesn't work, obviously, and I don't have a sense for what I should be doing, so if anyone can give some guidance, that would be really appreciated!
I would pass the name of the class to the job, rather than the class itself. Then you could call constantize on the name to get the class back, and call find on it. eg.
def self.perform(class_name, object_id, branch = 'master')
object = class_name.constantize.find(object_id)
object.create_archive(branch)
end

How to create object of one Model after creating another Model's object using serialization and modelViewSet

These are MODELS:
class Event (models.Model):
status = models.CharField(max_length = 30, blank = True)
time = models.DateTimeField()
point = models.ForeignKey(Point)
person = models.ForeignKey(Person)
device = models.ForeignKey(Device)
organization = models.ForeignKey(Organization)
class Presence(models.Model):
point = models.ForeignKey(Point)
person = models.ForeignKey(Person)
date_from = models.DateTimeField()
date_to = models.DateTimeField()
This is SERIALIZERS:
class EventSerializer(serializers.ModelSerializer):
person = serializers.SlugRelatedField(queryset=Person.objects.all(), slug_field='card_tag')
class Meta:
model = Event
fields = ['id','time','point','person','device','organization']
this is API:
class EventAPI(viewsets.ModelViewSet):
serializer_class = cs.EventSerializer
This is URL:
url(r'^event/', api.EventAPI.as_view({'post':'create'}), name='event_create'),
so I want these:
after every creation of Event object, check it by %2 (getting number of objects by card_tag, which is in body of request), if it's number
of events %2 == 0 => create object of Presence, how can I do it ?
Thanks and sorry
You should be able to use the perform_create method, which by default looks something like:
def perform_create(self, serializer):
serializer.save()
Now you can override it and do pretty much anything you want.
def perform_create(self, serializer):
serializer.save()
if ..something.. % 2:
Presence.objects.create(...)

How to use Jackson JsonSubTypes annotation in Kotlin

I'm trying to convert some Java code that uses Jackson's #JsonSubTypes annotation to manage polymorphism.
Here is the working Java code:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(value = Comment.class, name = "CommentNote"),
#JsonSubTypes.Type(value = Photo.class, name = "PhotoNote"),
#JsonSubTypes.Type(value = Document.class, name = "DocumentNote")
})
public abstract class Note implements Identifiable {
[...]
Here is the Kotlin code I think would be equivalent:
JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
JsonSubTypes(
JsonSubTypes.Type(value = javaClass<Comment>(), name = "CommentNote"),
JsonSubTypes.Type(value = javaClass<Photo>(), name = "PhotoNote"),
JsonSubTypes.Type(value = javaClass<Document>(), name = "DocumentNote")
)
abstract class Note : Identifiable {
[...]
But I get the following errors on each of the three "JsonSubTypes.Type" lines :
Kotlin: An annotation parameter must be a compile-time constant
Kotlin: Annotation class cannot be instantiated
Any idea?
I believe this has been resolved and nowadays you can write it like this:
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
#JsonSubTypes(
JsonSubTypes.Type(value = Comment::class, name = "CommentNote"),
JsonSubTypes.Type(value = Photo::class, name = "PhotoNote"),
JsonSubTypes.Type(value = Document::class, name = "DocumentNote"))
interface Note
Note the missing # and class notation in the JsonSubTypes.Type.
Turns out it's a bug in the compiler, thanks for reporting it. To work around this issue, you can import JsonSubTypes.Type and use it without qualification:
import org.codehaus.jackson.annotate.JsonSubTypes.Type
JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
JsonSubTypes(
Type(value = javaClass<Comment>(), name = "CommentNote"),
Type(value = javaClass<Photo>(), name = "PhotoNote"),
Type(value = javaClass<Document>(), name = "DocumentNote")
)
abstract class Note : Identifiable {
[...]
I know this is an old question, nevertheless if someone is still searching for a solution to serialise/deserialise inherited classes in kotlin with jackson, I'd suggest using sealed classes and not using #JsonSubTypes.
I'd also suggest using include as EXISTING_PROPERTY and getting the property through a val inside the sealed class. Otherwise, if you add combined inherited objects inside an array, jackson won't be able to deserialise and will throw a com.fasterxml.jackson.databind.exc.InvalidTypeIdException.
Here is the example usage:
#JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "type")
sealed class Note{
val type = this::class.java.simpleName
}
data class Document(val text: String, ...) : Note()
this should work like a charm, including using this class inside an array!
Another big advantage of this approach is, you don't need to set anything manually. As we all know, manual operations are error prone, as you can forget to add/remove/modify in case you add or remove a sub class, modify name etc. In this approach, you neither need to have a manually carved sub type list, nor need to give a json representation of the class name manually.
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type")
#JsonSubTypes(
JsonSubTypes.Type(Car::class, name = "car"),
JsonSubTypes.Type(Truck::class, name = "truck")
)
abstract class Vehicle(val type: String)
data class Car #JsonCreator constructor(#JsonProperty("manufacturer") val manufacturer: String) : Vehicle("car")
data class Truck #JsonCreator constructor(#JsonProperty("weight") val weight: Double) : Vehicle("truck")
#Test
public fun jacksonInheritanceKt() {
val s = "[{\"type\": \"car\", \"manufacturer\": \"audi\"}, {\"type\": \"truck\", \"weight\": 3000.0}]"
val mapper = ObjectMapper()
val vehicles = mapper.readValue(s, object : TypeReference<List<Vehicle>>() {})
println(vehicles)
}

JSON Grail Groovy Update SQL

Using a Groovy script with grails and want to do an update to a record in the database. I do the basic get the object from JSON and convert it to the Domain class and then do save() on it. From what I understand since I am new to Groovy and grails the save should update if the "id" is already there. But I don't get that, I get the standard SQL error of "Duplicate entry '1' for key 'PRIMARY'". How do I fix this?
def input = request.JSON
def instance = new Recorders(input)
instance.id = input.getAt("id")
instance.save()
and my domain is:
class Recorders {
Integer sdMode
Integer gsmMode
static mapping = {
id generator: "assigned"
}
static constraints = {
sdMode nullable: true
gsmMode nullable: true
}
}
Instead of doing a new Recorders(input), you probably ought to get it:
def input = request.JSON
def instance = Recorders.get(input.getAt('id'))
instance.properties = input
instance.save()
Edit
(From your comment) If it doesn't exist and you want to insert it:
def input = request.JSON
def id = input.getAt('id')
def instance = Recorders.get(id)
if(!instance) {
instance = new Recorders(id: id)
}
instance.properties = input
instance.save()
I don't use assigned id generators much, so I'm not sure if Grails will bind the id automatically (since it's expecting it to be assigned). If it does, you can probably remove the id: id from the Recorders() constructor.