Ways to save django model using nested dictionary - python

I'll try to make this as simple as I can:
I have 2 models
from django.db import models
class OrderDetail(models.Model):
product = models.CharField(max_length=100)
price = models.CharField(max_length=50)
class Order(models.Model):
url = models.CharField(max_length=255, unique=True)
loaded_info = models.BooleanField(default=False)
status = models.CharField(max_length=100, null=True)
details = models.OneToOneField(OrderDetail)
And I whish to save using a dict like this:
data = {
"order": {
"url": "http://stackoverflow.com/",
"loaded_info": True,
"status": "complete",
"details": {
"product": "Fresh answer",
"price": "50 points"
}
}
}
I'd like to do something close to:
order = Order(**data).save()
And get Order and OrderDetail saved using a single line.

Have a look at https://docs.djangoproject.com/en/1.9/topics/serialization/
In this case, you would do something like:
qs = Order.objects.select_related('details').get(pk=1)
data = serializers.serialize("json", qs)

Related

My django models are returning serialised data in json format for my view but i also want a string representation for my admin. How do i do that

My django models are returning serialised data in json format for my view but i also want a string representation for my admin. How do i do that
class Perfumes(models.Model):
brandsection = models.CharField(max_length=50)
brand = models.CharField(max_length=50)
trending = models.BooleanField(default=False)
price = models.IntegerField()
color = models.CharField(max_length=64)
description = models.TextField(max_length=1000)
def serialize(self):
return {
"id": self.id, "brandsection": self.brandsection,"brand": self.brand, "price": self.price,"color": self.color,"description": self.description}
class PerfumesImages(models.Model):
entry = models.ForeignKey(Perfumes, default=None, on_delete=models.CASCADE, related_name="perfumesphoto")
images = models.ImageField(upload_to='Perfumes', verbose_name='Image')
def serialize(self):
return {
"id": self.id,
"entry": {"entryid" : self.entry.id, "brandsection" : self.entry.brandsection, "brand" : self.entry.brand, "price" : self.entry.price, "color" : self.entry.color,"description" : self.entry.description},
"images": self.images.url
}

Django rest Framework - Custom Json Response

i'm new into Python and Django Rest Framework. I'm trying to return a "custom" json response but i can't figure it out how to achieve the result i want.
I'm building an Ecommerce api where i have "boxes" with "products", this BoxProduct model was created because i need a relation between Products and Boxes, but the same product can be in different boxes, ex: Product.id=1 is in box_id=2 and box_id=4. That's why i created this middle model.
BoxProduct Model
class BoxProduct(models.Model):
product = models.ForeignKey(Product, on_delete=models.DO_NOTHING, null=True, related_name='box_product')
box = models.ForeignKey(Box, on_delete=models.DO_NOTHING, null=True, related_name='box_box')
product_price = models.DecimalField(max_digits=8, decimal_places=0, null=True, blank=True)
I tried to link the serializers of Product and Box but i didn't get wat i want.
BoxProduct Serializer
class BoxProductSerializer(serializers.ModelSerializer):
product = ProductSerializer(many=True, read_only=True)
box = BoxSerializer()
class Meta:
model = BoxProduct
fields=['box', 'product']
The idea is to have a returned json like this:
{
"box_id": 232323,
"box_name": "Box name Test",
"products": [
{
"name": "product name 1",
"type": "product_type"
},
{
"name": "product name 2",
"type": "product_type"
},
{
"name": "product name 3",
"type": "product_type"
}
]
}
What would be the best approach to do this?
Thanks for your help!
It seems like you want to get a box and products inside this box. For that you should use BoxSerializer, not BoxProductSerializer:
# 1. Add 'products' method to Box model:
class Box(models.Model):
...
def products(self):
return Product.objects.filter(boxproduct_set__pk__in=self.boxproduct_set)
# 2. Your BoxSerializer should look like this:
class BoxSerializer(serializers.ModelSerializer):
products = ProductSerializer(many=True, read_only=True)
class Meta:
model = Box
fields = (..., 'products')

Can you optimize this code? (Django, python)

I'm adding 'added' field to check which categories User's Post(Outfit) is added to. It sounds horrible, so let's dive in to the code.
I want to optimize get_categories(self, obj) function.
class CategorySerializer(serializers.ModelSerializer):
added = serializers.BooleanField()
class Meta:
model = Category
fields = (
'id',
'name',
'added'
)
class OutfitDetailSerializer(serializers.ModelSerializer):
def get_categories(self, obj):
user = self.context['request'].user
categories = Category.objects.filter(owner=user)
added = categories.extra(select={'added': '1'}).filter(outfits__pk=obj.pk)
added = list(added.values('added', 'name', 'id'))
added_f = categories.extra(select={'added': '0'}).exclude(outfits__pk=obj.pk)
added_f = list(added_f.values('added', 'name', 'id'))
categories = added + added_f
return CategorySerializer(categories, many=True).data
The output is below!
"categories": [{
"id": 1,
"name": "Gym",
"added": true
}, {
"id": 2,
"name": "School",
"added": false
}, {
"id": 3,
"name": "hollymo",
"added": true
}, {
"id": 4,
"name": "Normal",
"added": false
}, {
"id": 6,
"name": "New Category",
"added": false
}
]
Here is models.py
class Outfit(models.Model):
...
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
content = models.CharField(max_length=30)
...
class Category(models.Model):
name = models.CharField(max_length=20)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True)
outfits = models.ManyToManyField(Outfit, related_name="categories", blank=True)
main_img = models.ImageField(
upload_to=upload_location_category,
null=True,
blank=True)
...
here the repo for test
If i get you right, you can get necessary data with django raw sql:
q = """\
SELECT yourappname_category.id,
yourappname_category.name,
COUNT(outfit_id) > 0 as added
FROM yourappname_category
LEFT JOIN yourappname_category_outfits
ON yourappname_category.id = yourappname_category_outfits.category_id
AND yourappname_category_outfits.outfit_id=%s
WHERE yourappname_category.owner_id=%s
GROUP BY yourappname_category.id, yourappname_category.name"""
categories = Category.objects.raw(q, [obj.id, user.id])
results = [{'id': c.id, 'name': c.name, 'added': c.added} for c in categories]
If I understand your use case correctly you just want "to check which categories User's Post(Outfit) is added to". For that you would only need to return the ones with added = true right? and then you could leave the added key out.
as in:
"categories": [{
"id": 1,
"name": "Gym"
}, {
"id": 3,
"name": "hollymo"
}
]
If so, you could just use:
import Category from category.models
class CategoriesSerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id', 'name')
class OutfitDetailSerializer(serializers.ModelSerializer):
categories = CategoriesSerializer(many=True)
If instead your use case is to show a list of all categories and then do something with just the ones that the current outfit is added to, I'd suggest doing 2 API calls instead of your current logic; One with the answer I supplied above and one to get all categories. Then do that 'added' logic in your front-end as its presentation layer logic imo.
I'd certainly try to avoid doing raw SQL queries in Django, it cuts the purpose of migrations and is rarely necessary.

django timeseries postgres beginner

I'm writing small application in django in order to learn databases and web etc.
The application should display players data and record statistics over time.
To answer questions such as:
How many random battles palyer has played in last month/week/day? - graph
What players left/entered clan? - etc.
I've been searching and reading and I found these suggestions:
What is a good combination of technology to use?
MongoDB, InfluxDB, PostgreSQL, RedisDB, or from packages django-timeseries, django-reversion.
I did not find my approach to be good and I probably, can anybody suggest me which database to use and how models should look like then a bit?
Critics or advice with database design is very appreciated.
Data is being downloaded from 3rd party API as jsons.
Structures which are downloaded:
Player.json
{
"501435906": { # this is PlayerID
"last_battle_time": 1484160229,
"statistics": {
"all": {
"battles": 70555
},
"random": {
"battles": 67361
}
}
}, # then next players continue
}
clan.json
{
"500004323": { # clan ID
"members": [
{
"account_id": 501435906, # PlayerID same as in Player.json
"account_name": "Player1",
"joined_at": 1447589992,
"role": "private",
"role_i18n": "Private"
},]
"name": "Full Clan Name",
"tag": "TAG",
}
stronghold.json
{
"500323931": { # PlayerID
"stronghold_skirmish": null,
"total_resources_earned": 0,
"week_resources_earned": 0
}, # next player follows
}
My approach:
Merge data together
{
"500004323": {
'name': 'Full Clan Name',
'tag': 'TAG'
"members": {
"500012979": {
"account_id": "500012979",
"account_name": "Player1",
"joined_clan_date": 1415990768,
"last_battle_time": 1484160229,
"role": "Commander",
"statistics": {
"all": {
"battles": 70555
},
"random": {
"battles": 67361
}
},
"stronghold": {
"stronghold_skirmish": {
"battles": 2223
},
"total_resources_earned": 32582,
"week_resources_earned": 80
}
}, # next members
}, # next clan
}
And import this data into following models:
class Clan(models.Model):
"""Clan model"""
clan_id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
tag = models.CharField(max_length=5)
#property
def members(self):
return Player.objects.filter(clan=self)
def kick_player(self, player):
player.leave_clan()
class PlayerLeaversManager(models.Manager):
def leave_clan(self, players):
"""Take list of players and remove them from their clan
:param players:
"""
for player in players:
player.leave_clan()
class Player(models.Model):
"""Player model"""
account_id = models.IntegerField(primary_key=True)
access_token = models.TextField(blank=True,
null=True)
access_token_expires_at = models.CharField(max_length=10,
blank=True,
null=True)
account_name = models.CharField(max_length=250)
clan = models.ForeignKey('Clan',
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='current_clan')
previous_clan = models.ForeignKey('Clan',
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='previous_clan')
# objects = models.Manager()
objects = PlayerLeaversManager()
def __str__(self):
return '{0} - {1}'.format(self.account_name, self.account_id)
def get_absolute_url(self):
return reverse('wot:player_detail',
args=[self.account_name])
def leave_clan(self):
self.previous_clan = self.clan
self.clan = None
self.save()
class PlayerData(models.Model):
"""Players data daily tracked"""
created = models.DateTimeField(auto_now_add=True)
player = models.ForeignKey('Player',
on_delete=models.CASCADE,
null=True,
blank=True
)
joined_clan_date = models.DateTimeField(blank=True,
null=True)
role_in_clan = models.CharField(max_length=250,
blank=True,
null=True)
battles_on_random = models.IntegerField(blank=True,
null=True)
battles_all = models.IntegerField(blank=True,
null=True)
battles_stronghold = models.IntegerField(blank=True,
null=True)
tank = models.ManyToManyField('Vehicle',
related_name='tanks',
blank=True,)
last_battle_time = models.DateTimeField(blank=True,
null=True)
# stronghold stats
total_resources_earned = models.IntegerField(blank=True, null=True)
week_resources_earned = models.IntegerField(blank=True, null=True)
Whole code can be found on my github https://github.com/1oglop1/anv_wot
Thank you for all suggestions.
After some more research and asking at python FB community I will try following:
1) Normalize the models
2) Use PostgreSQL as backend.

Django saving in a model with User field

I have token auth implemented in django and my models looks like-
class Portfolio(models.Model):
owner = models.ForeignKey(User, verbose_name='User', null=True)
company = models.TextField(null=True)
volume = models.IntegerField(blank=True)
date = models.DateField(null=True)
And to save in this model, I have the following in views-
arr = []
contents = request.data
user = User.objects.filter(username=request.user)
user_is = User(username=user)
for i in range(0, len(portfolio_contents)):
line = portfolio_contents[i].split(",")
get_isin = Endday.objects.get(company=line[0])
datestuff = line[2]
datestuff = datestuff[0:10]
arr.append(Portfolio(owner=user_is, company=line[0], volume=line[1], date=datestuff))
Portfolio.objects.bulk_create(arr)
This code saves the data but when I try to see the data, I get this-
[
{
"company": "BAL",
"volume": 1425,
"date": "2014-02-19",
"owner": null
},
{
"company": "RLD",
"volume": 2245,
"date": "2014-02-19",
"owner": null
},
Owner should not be null because if I try to print(user.username), it prints <QuerySet [<User: ku>]>.
What seems to be the problem?
It's because you didn't save your user e.g. it doesn't have an id in database.
Also you need a User instance and not QuerySet which you'll get from calling User.objects.filter(username=request.user).
Try to:
user_is = User.objects.get(username=request.user.username)
Your user_is is a User model instance which is not saved in the database:
user_is = User(username=user) # ??? username != user
Why not do:
user_is = User.objects.get(username=request.user.username)
Or make owner=request.user in the ForeignKey field in your loop.

Categories