My view currently accepts a username and if the user exists it sends back a queryset of all entries in a Model, where the corresponding userid fits.
The Model UserProject consists of a UserID and a ProjectID, both are references to their own tables.
I would like to add the Project Model to the queryset.
my view:
class GetUserDataByNameView(
APIView,
):
def get(self, request, username):
if User.objects.filter(username = username).exists():
uid = User.objects.get(username = username).id
queryset = Userproject.objects.filter(user_id = uid)
readSerializer = UserprojectSerializer(queryset, many = True)
return Response(readSerializer.data)
else:
return Response({"status": "error", "data":"no user with this username"}, status = 200)
the Response currently looks like this:
[
{
"id": 16,
"created_at": "2021-10-20T16:05:03.757807Z",
"updated_at": "2021-10-20T16:05:03.762307Z",
"user": 3,
"project": 50
},
{
"id": 17,
"created_at": "2021-10-20T16:27:59.938422Z",
"updated_at": "2021-10-20T16:27:59.945439Z",
"user": 3,
"project": 51
#"projectname": (from ProjectID 51)
#"projectDescriptor":
#" other stuff from ProjectModel":
}
]
So how would I insert the fields for the current Project ?
If I did some useless stuff in the code, please tell me. Newbie in Django
serializer:
from rest_framework import serializers
from .models import Project
from .models import Userproject
class ProjectSerializer(serializers.ModelSerializer):
name = serializers.CharField(max_length = 500, required = True)
descriptor = serializers.CharField(max_length = 1000, default = None)
class Meta:
model = Project
fields = '__all__'
class UserprojectSerializer(serializers.ModelSerializer):
class Meta:
model = Userproject
fields = '__all__'
models:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Project(models.Model):
id = models.AutoField(db_column = 'db_ID', primary_key = True)
name = models.CharField(max_length=500, default = None)
descriptor = models.CharField(max_length = 1000, null = True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'projects'
def __str__(self):
return self.name
class Userproject(models.Model):
id = models.AutoField(db_column = 'db_ID', primary_key = True)
user = models.ForeignKey(User, on_delete= models.SET_NULL, null = True)
project = models.ForeignKey('Project', on_delete = models.SET_NULL, null = True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
updated_at = models.DateTimeField(auto_now=True, null = True)
class Meta:
db_table = 'UserProjects'
def __str__(self):
return self.id
class UserprojectSerializer(serializers.ModelSerializer):
projects = ProjectSerializer(many=True, read_only=True)
class Meta:
model = Userproject
fields = ['projects','id','user',]
You need to pass the Project data to your UserProject Serializer, also I have mentioned many=True because User is connected to ForeignKey so a user can have multiple projects.
class ProjectSerializer(serializers.ModelSerializer):
name = serializers.CharField(max_length = 500, required = True)
descriptor = serializers.CharField(max_length = 1000, default = None)
class Meta:
model = Project
fields = ['name','descriptor']
Related
models.py
#
from django.db import models
from user.models import User
from chat.models import TradeChatRoom, AuctionChatRoom
class Goods(models.Model):
class Meta:
db_table = 'Goods'
ordering = ['-created_at'] # 일단 추가해뒀습니다
seller = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sell_goods')
buyer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='buy_goods', null=True)
trade_room = models.ForeignKey(TradeChatRoom, on_delete=models.CASCADE)
auction_room = models.ForeignKey(AuctionChatRoom, on_delete=models.CASCADE)
title = models.CharField(max_length=256)
content = models.TextField()
category = models.CharField(max_length=32)
status = models.BooleanField(null=True)
predict_price = models.IntegerField()
start_price = models.IntegerField()
high_price = models.IntegerField(null=True)
start_date = models.DateField(null = True)
start_time = models.DateTimeField(null=True)
created_at = models.DateTimeField(auto_now_add=True)
like = models.ManyToManyField(User, related_name='like_goods', null=True)
class GoodsImage(models.Model):
class Meta:
db_table = "GoodsImage"
goods = models.ForeignKey(Goods, on_delete=models.CASCADE)
image = models.ImageField(upload_to='goods/')
serializer.py
from rest_framework import serializers
from .models import Goods,GoodsImage
class GoodImageSerializer(serializers.ModelSerializer):
image = serializers.ImageField(use_url=True)
def get_image(self, obj):
image = obj.goods_set.all()
return GoodsPostSerializer(instance=image, many = True, context = self.context)
class Meta:
model = GoodsImage
field =('image',)
class GoodsPostSerializer(serializers.ModelSerializer):
image = GoodImageSerializer(many=True, read_only = True)
class Meta:
model = Goods
fields = (
'seller', 'buyer','auction_room','title','content',
'category','status','predict_price','start_price','high_price',
'trade_room','start_date','start_time','created_at','like','image',
)
read_only_fields = ("seller",)
def create(self, validated_data):
goods = Goods.objects.create(**validated_data)
images_data = self.context['request'].FILES
for image_date in images_data.getlist('image'):
GoodsImage.objects.create(goods = goods, image = image_date)
return goods
error
images_data = self.context['request'].FILES
KeyError: 'request'
I want to save multiple images, but I keep getting an error. I don't know what to do anymore.
I searched for a method and followed it, but it seems that I am the only one who gets an error.
Please help if you know how to solve this problem.
And I want to know if it is correct to put it in a list like "image":["12.jpeg,"13.jpeg] when inserting multiple images through postman.
It's hard not being able to solve this problem. please help me if you know the answer
Change GoodImageSerializer calling this:
GoodImageSerializer(instance=images, many = True, context={'request': request})
Then change your GoodsPostSerializer's create method like this:
def get_image(self, obj):
image = obj.goods_set.all()
request = self.context['request']
return GoodsPostSerializer(instance=image, many = True, context={'request': request})
I'm using Django REST Framework to create the following endpoints:
/tenants/ ➞ lists all tenants and includes in the json response the attributes of the Building model they live in.
/buildings/ ➞ lists all buildings and includes in the json response the attributes of the Tenants that live in them.
My models are:
class Building(models.Model):
address = models.CharField(max_length = 200)
zipcode = models.IntegerField()
city = models.CharField(max_length = 100)
class Tenant(models.Model):
fname = models.CharField(max_length = 200)
lname = models.CharField(max_length = 200)
building = models.ForeignKey(Building, related_name = 'tenants', on_delete = models.CASCADE)
My serializers look like so:
class BuildingSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
fields = ['id', 'address', 'zipcode', 'city']
class TenantSerializer(serializers.HyperlinkedModelSerializer):
building = BuildingSerializer()
class Meta:
model = Tenant
fields = ['id', 'fname', 'lname', 'building']
The /tenants/ endpoint works just fine, but I have no idea on how to include the tenants' data in the /buildings/ response.
Could anyone give me a clue on this?
class Building(models.Model):
address = models.CharField(max_length = 200)
zipcode = models.IntegerField()
city = models.CharField(max_length = 100)
def __str__(self):
return self.address+self.city
class Tenant(models.Model):
fname = models.CharField(max_length = 200)
lname = models.CharField(max_length = 200)
building = models.ForeignKey(Building, related_name = 'tenantsRN', on_delete = models.CASCADE)
def __str__(self):
return self.fname+self.lname+" tenant"
**#in serializers.py**
*#if you have not used related name u need to use _set*
class BuildingSerializer(serializers.HyperlinkedModelSerializer):
tenantsRN=serializers.StringRelatedField(many=True)# gets self.fname+self.lname+" tenant"
tenantsRN = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='fname')
class Meta:
model=Building
fields = ('id', 'address', 'zipcode', 'city','tenantsRN')
#you can use string related field or slug related field based on requirement
#or you can use HyperlinkedIdentityField for customize
**in views.py**
class allview(ListAPIView):
serializer_class=BuildingSerializer
def get_queryset(self):
return Building.objects.all()```
In my django app, i'm having difficulties whenever i want to add a new object that uses the table paymentInvoice.
The error i'm getting from my api looks like this
IntegrityError at /api/clients/invoice/
null value in column "invoiceOwner_id" violates not-null constraint
DETAIL: Failing row contains (10, INV-0006, Lix, 2020-08-04, 1, Pending, 3000, null).
NB: I haven't created the field invoiceOwner_id, postgres automatically added it or rather is using it as a representation for my invoiceOwner field
class Purchaser(models.Model):
name = models.CharField(max_length=50)
phone = models.CharField(max_length=20, unique=True)
email = models.EmailField(max_length=255, unique=True, blank=True)
image = models.ImageField(default='default.png', upload_to='customer_photos/%Y/%m/%d/')
data_added = models.DateField(default=datetime.date.today)
def __str__(self):
return self.name
class paymentInvoice(models.Model):
invoiceNo = models.CharField(max_length=50, unique=True, default=increment_invoice_number)
invoiceOwner = models.ForeignKey(Purchaser, on_delete=models.CASCADE, related_name="invoice_detail")
product = models.CharField(max_length=50, blank=True)
date = models.DateField(default=datetime.date.today)
quantity = models.PositiveSmallIntegerField(blank=True, default=1)
payment_made = models.IntegerField(default=0)
def __str__(self):
return self.invoiceOwner.name
serilizers file
class paymentInvoiceSerializer(serializers.ModelSerializer):
invoiceOwner = serializers.SerializerMethodField()
class Meta:
model = paymentInvoice
fields = '__all__'
def get_invoiceOwner(self, instance):
return instance.invoiceOwner.name
views file
class paymentInvoiceListCreateView(ListCreateAPIView):
serializer_class = paymentInvoiceSerializer
queryset = paymentInvoice.objects.all().order_by('-date')
GET result from api call.
{
"id": 1,
"invoiceOwner": "Martin",
"invoiceNo": "INV-0001",
"product": "",
"date": "2020-08-04",
"quantity": 1,
"payment_made": 0
}
Tried passing below as POST but got the main error
{
"invoiceOwner": "Becky",
"product": "Lix",
"quantity": 1,
"payment_made": 3000
}
"invoiceOwner" in your serializers.py is a SerializerMethodField which is readonly
that's why you get an error, you have to define the create method yourself
As I said in comment: You need to explicitly override the create method in your serializer since your model has foreign key invoiceOwner, just to create that instance first as a Purchaser instance.
You can try the code below:
class paymentInvoiceSerializer(serializers.ModelSerializer):
invoiceOwner = serializers.SerializerMethodField()
class Meta:
model = paymentInvoice
fields = '__all__'
def get_invoiceOwner(self, instance):
return instance.invoiceOwner.name
def create(self, validated_data):
purchaser_name = validated_data.get("invoiceOwner")
purchaser = Purchaser(name=purchaser_name,
# you need to have phone, email, since these fields are unique,
# they can't remain null
)
purchaser.save()
return paymentInvoice.objects.create(invoiceOwner = purchaser, **validated_data)
Here's what I currently have:
models.py:
class Team(models.Model):
label = models.CharField(max_length=128, unique=True)
def __str__(self) -> str:
return self.label
class AppName(models.Model):
label = models.CharField(max_length=128, unique=True)
def __str__(self) -> str:
return self.label
serializers.py
class TeamSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Team
fields = [
'id',
'label'
]
class AppNameSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = AppName
fields = [
'id',
'label'
]
This is my function:
appname = AppNameSerializer(data={'label': request.POST.get('appname')})
if appname.is_valid():
appname = appname.save()
team = TeamSerializer(data={'label': request.POST.get('team')})
if team.is_valid():
team = team.save()
where request.POST.get('appname') is 'foo-name' and request.POST.get('team') is 'Chocobo Knights'
Why is appname.is_valid() throwing invalid? whereas team.is_valid() passes? They're effectively the same code, I'm so confused.
TeamSerializer(data={'label': 'Chocobo Knights'}):
id = IntegerField(label='ID', read_only=True)
label = CharField(max_length=128, validators=[<UniqueValidator(queryset=Team.objects.all())>]) True
AppNameSerializer(data={'label': 'foo-app'}):
id = IntegerField(label='ID', read_only=True)
label = CharField(max_length=128, validators=[<UniqueValidator(queryset=AppName.objects.all())>]) False
Is this the right approach given the DB uniquevalidator?
appname = AppNameSerializer(data={'label': request.POST.get('appname')})
if appname.is_valid():
appname = appname.save()
else:
appname = AppName.objects.get(**appname.data)
team = TeamSerializer(data={'label': request.POST.get('team')})
if team.is_valid():
team = team.save()
else:
team = Team.objects.get(**team.data)
Your serializers validation depends on the state of the database.
The code might be the same, but if the Team table already has a "Chocobo Knights" while AppName does not have any "foo-app"... don't expect the same results for both!
So i am trying to serialize multiple joined tables with django serializers. I cant find a way to do this. The query being executed is raw sql.
The models are as below
class UserDetail(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
mobile_number = models.IntegerField()
national_id = models.CharField(max_length = 30)
date_created = models.DateTimeField(auto_now_add = True)
address = models.CharField(max_length = 250)
merchant_name = models.CharField(null = True, max_length = 30)
class Account(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
account_number = models.BigIntegerField()
balance = models.FloatField()
account_type = models.ForeignKey(AccountType, on_delete = models.CASCADE)
The json for the expected result should as below
{
"userdetail": {
"mobile_number":""
},
"account": {
"account_number":""
},
"user": {
"first_name": "",
"last_name": "",
"email":""
}
}
The raw sql query is as below
queryset = Account.objects.raw('''SELECT auth_user.first_name,
auth_user.id,
auth_user.last_name,
auth_user.email,
authentication_userdetail.mobile_number,
authentication_account.account_number
FROM
public.auth_user,
public.authentication_account,
public.authentication_userdetail
WHERE
auth_user.id = authentication_userdetail.user_id
AND
auth_user.id = authentication_account.user_id
''')
If there is an alternative way to do this without using raw sql i would greatly appreciate it as im not a fan of executing raw sql queries with django ORM
Tried working with this solution but i cant seem to understand the way the queryset was serialized
Cross-table serialization Django REST Framework
Edited
class UserDetailSerializer(serializers.ModelSerializer):
class Meta:
model = UserDetail
fields = ('mobile_number',)
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('account_number',)
class AccountInfoSerializer(serializers.ModelSerializer):
user_detail = UserDetailSerializer()
account = AccountSerializer()
user = serializers.SerializerMethodField()
class Meta:
model = User
fields = ('user_detail', 'account', 'user')
def get_user(self, obj):
return {
'first_name': 'obj.first_name',
'last_name': 'obj.last_name',
'email': 'obj.email',
}
Code for the view
serializer_class = AccountInfoSerializer
def get_queryset(self, *args, ** kwargs):
user_id = self.request.query_params.get('user_id', None)
queryset = None
if user_id is not '':
queryset = UserDetail.objects.raw()
return queryset
you can try such solution:
from rest_framework import serializers
class UserDetailSerializer(serializers.ModelSerializer):
class Meta:
model = UserDetail
fields = ('mobile_number',)
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('account_number',)
class UserSerializer(serializers.ModelSerializer):
userdetail = UserDetailSerializer()
account = AccountSerializer()
user = serializers.SerializerMethodField()
class Meta:
model = User
fields = ('userdetail', 'account', 'user')
def get_user(self, obj):
return {
'first_name': 'obj.first_name',
'last_name': 'obj.last_name',
'email': 'obj.email',
}