How to handle calculated models in django? - django

From a model called Suggestion, I need to calculate another model that is called Task.
Task objects doesn't need to store anything in the database since it is totally calculated using Suggestion fields.
An exemple would be a task of approving a suggestion using fields :
approver
state
approving_deadline
Is their a standard way in django to handle this kind of models that doesn't need to store any information but are fully calculated using other models ?

You should use a SerializerMethodField:
In your Serializer, create a field for your Task like task = serializers.SerializerMethodField()
Still, in your serializer, create a method called get_taks(self, obj). obj is your current Suggestion, from which you need to calculate your task and return it as serialized data (the Task primary key using task.pk, or a serialized Task using TaskSerializer(task).data, or whatever you prefer).
ex.:
class SuggestionSerializer(serializers.ModelSerializer):
task = serializers.SerializerMethodField()
class Meta:
model = Suggestion
fields = [
'id', 'approver', 'state', 'approving_deadline',
..., 'task'
]
def get_tasks(self, obj):
# obj is a Suggestion instance
task = my_get_task_from_suggestion_helper(obj)
return task.id # or TaskSeriaizer(task).data
You can read more detail about SerializerMethodField on Django REST Framework docs

Related

django how to create a serializer ListField that accepts DictField with images values

As the title describes I need to create a Custom serializer ListField that accepts dictionary of string keys and value of Image
Example input:
[ {'1':FirstImage} , {'3',ThirdImage} ]
What I've tried:
customSerializer = serializers.ListField(
child=serializers.DictField(
child=serializers.ImageField(allow_empty_file=True, use_url=False)
)
)
Obviously my serializer doesnt work as it should, anyone have an idea how can I make this work?
Thanks In Advance
Create a separate serializer class and use that in your ListField like this:
class ImageSerializer(serializers.Serializer):
id = serializers.IntegerField()
image = serializers.ImageField(allow_empty_file=True, use_url=False)
class FinalSerializer(serializers.Serializer):
my_field = serializers.ListField(child=ImageSerializer())
I suggest you don't add the child instance arg, as this will validate all the fields in the model table which will in turn increase endpoint latency.
As specified in the doc:
child - A field instance that should be used for validating the objects in the list. If this argument is not provided then objects in the list will not be validated.
You can write your own validator methods (just the relevant ones).

How to design a Django API to handle a "Dynamic" form?

I have built an Angular form that contains a form array. So the user has the control to add fields or delete fields from the form. What I am trying to understand is how I can design a Django API that can handle the post for this kind of dynamic form?
I do not want the user to create an account on the website in order to place his order. Is that even possible?
You should be more concerned about how to model your data, than you can think about your interface. Here a few options for modeling your data:
Option One is to use regular Django ORM, and in this case you may use the JSONField for any dynamic properties.
Option two is to use any schemaless data model, such as document-based databases(e.g MongoDB).
Here a simple example, on how to use Django's JSONField:
your model:
class Order(models.Model):
customer = models.ForeignKey(User, on_delete=models.CASCADE)
#any additional static fields
properties = JSONField()
your view:
def create_order_view(request):
if request.method == "POST":
#do your validation
Order.objects.create(user=request.user, properties=request.POST["properties"])
return Response(status=200)
this example is totally incomplete as you have to add validation error handling, and it is a better idea to use Django rest-framework for constructing your API.
Finally as I said there many option to model your data, in addition to what I mentioned above there are many other. To decide what model to use, you have to know how your data gonna be consumed, so you can optimze for query time, in addition there are many other factors but this is out of scope of this asnwer.
For me, I used Django-RESTframework to build the api.
The way to achieve this is simple, just create the model and iterate through the items which is the dynamic part, and assign the Foreignkey field to obj.id created. First, I created the main model instance, then created the instances of the child instances. I will use Order and Item to demonstrate the idea, The Item instance will have Foreinkey field to Order model.
In the Item model, add "related_name" argument to the Foreinkey field
order = models.ForeignKey(Order, related_name='items',on_delete=models.CASCADE)
serializers.py
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = [
....your fields...
]
class OrderSerializer(serializers.ModelSerializer):
items = ItemSerializer(many=True)
class Meta:
model = Order
fields = [
'order', ....
]
def create(self, validated_data):
items_data = validated_data.pop("items")
order = Order.objects.create(**validated_data)
order.total_fees = order.delivery_fees
for item in items_data:
i = Item.objects.create(order=order, **item)
return order

Django: How to Properly Use ManyToManyField with Factory Boy Factories & Serializers?

The Problem
I am using a model class Event that contains an optional ManyToManyField to another model class, User (different events can have different users), with a factory class EventFactory (using the Factory Boy library) with a serializer EventSerializer. I believe I have followed the docs for factory-making and serializing, but am receiving the error:
ValueError: "< Event: Test Event >" needs to have a value for field "id"
before this many-to-many relationship can be used.
I know that both model instances must be created in a ManyToMany before linking them, but I do not see where the adding is even happening!
The Question
Can someone clarify how to properly use a ManyToManyField using models, factory boy, and serializers in a way I am not already doing?
The Set-Up
Here is my code:
models.py
#python_2_unicode_compatible
class Event(CommonInfoModel):
users = models.ManyToManyField(User, blank=True, related_name='events')
# other basic fields...
factories.py
class EventFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.Event
#factory.post_generation
def users(self, create, extracted, **kwargs):
if not create:
# Simple build, do nothing.
return
if extracted:
# A list of users were passed in, use them
# NOTE: This does not seem to be the problem. Setting a breakpoint
# here, this part never even fires
for users in extracted:
self.users.add(users)
serializers.py
class EventSerializer(BaseModelSerializer):
serialization_title = "Event"
# UserSerializer is a very basic serializer, with no nested
# serializers
users = UserSerializer(required=False, many=True)
class Meta:
model = Event
exclude = ('id',)
test.py
class EventTest(APITestCase):
#classmethod
def setUpTestData(cls):
cls.user = User.objects.create_user(email='test#gmail.com',
password='password')
def test_post_create_event(self):
factory = factories.EventFactory.build()
serializer = serializers.EventSerializer(factory)
# IMPORTANT: Calling 'serializer.data' is the exact place the error occurs!
# This error does not occur when I remove the ManyToManyField
res = self.post_api_call('/event/', serializer.data)
Version Info
Django 1.11
Python 2.7.10
Thank you for any help you can give!
Regarding the error:
It seems like the missing id is due to the use of .build() instead of .create() (or just EventFactory()). The former does not save the model, and therefore it does not get an id value, whereas the latter does (refer to factory docs and model docs).
I suspect the serializer still expects the object to have an id, even though the many-to-many relationship is optional, because it cannot enforce a potential relationship without an id.
However, there might be a simpler solution to the actual task. The above method is a way of generating the POST data passed to post_api_call(). If this data was instead created manually, then both the factory and serializer become unnecessary. The explicit data method might even be better from a test-perspective, because you can now see the exact data which has to produce an expected outcome. Whereas with the factory and serializer method it is much more implicit in what is actually used in the test.

How can I update two models in one serializer in Django Rest Framework?

I have a database schema that has each object of a certain type being stored across two separate tables (one row in each table, different data in each, with a foreign key from one to the other.)
Unfortunately, Django Rest Framework tends to assume that there is a one to one correspondence between serializers and models, which is not true of my case. How should I be approaching this? It seems like the serializer should return the representation of the object which will be the actual HTTP response of the ajax requests, so using two serializers doesn't seem right. I've looked at extending BaseSerializer (which is how I currently plan to implement this if I don't find better solutions), but certain methods take in an instance, which should contain all the data needed to serialize the object, whereas I have two instances relevant.
Any advice would be super appreciated! Thank you.
Writable nested representations section might help you.
You have 2 models ModelA and ModelB. Create your first model's serializer
class ModelASerializer(serializers.ModelSerializer):
class Meta:
model = ModelA
fields = ('fields',..) #
Then in other model's serializer add the first serializer and override the required methods (like create, update). Something like this:
class ModelBSerializer(serializers.ModelSerializer):
# add the serializer for the foreignkey model
model_a = ModelASerializer()
class Meta:
model = ModelB
fields = ('fields',..) #
def create(self, validated_data):
modela_data = validated_data.pop('model_a')
model_b = ModelB.objects.create(**validated_data)
ModelA.objects.create(model_b=model_b, **modela_data)
return model_b
# override update too ..

Django - does model need own table if it inherits solely to change the manager?

I've read this thread which deals with the issue of making Django comments use select_related() on “user” field thereby reducing needless sql queries.
The suggestion I like best is to create my own comment model and override the manager currently used.
This is what I have:
#models.py
class LightCommentManager(CommentManager):
def get_query_set(self):
qs = (super(CommentManager, self).get_query_set().select_related('user'))
return qs
class LightComment(Comment):
objects = LightCommentManager()
class meta:
managed = False
This all works fine but when I syncdb, Django still creates a table for LightComment. Do I really need to have this table if all I'm changing is the manager, and why does Django create it if managed is set to false?
Thanks in advance,
For a start, your inner class should be called Meta, not meta.
But rather than managed = False, you should be using proxy = True to signify that you are creating a proxy model rather than another real model.