Posting Foreign key to DRF Api using React - python

I want to Post the Company object using React. However, the Foreign key seems to be failing. I'm not sure how so I pass the data for address and invoice address.
Below is my code
models.py
class Address(models.Model):
id = models.UUIDField()
city = models.CharField(max_length=20, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Company(models.Model):
id = models.UUIDField()
address = models.ForeignKey(Address, on_delete=models.CASCADE,
related_name='address')
invoice_address = models.ForeignKey(Address, on_delete=models.CASCADE,
related_name='invoice_address')
serializers.py
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
exclude = ('id', 'created', 'modified')
class CompanySerializer(serializers.ModelSerializer):
address = AddressSerializer()
invoice_address = AddressSerializer()
class Meta:
model = Company
def create(self, data):
#create address if it does not exist

Related

Django error while serializing image model of child field

I am new to this tech, while working on django project i got some issues when i try to serialize Ticket's account.profile_pic
models.py
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE
profile_pic = models.ImageField(upload_to='images/profile_pics/', blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
class Ticket(models.Model):
author = models.ForeignKey(Account, on_delete=models.CASCADE)
descr = models.TextField(blank=False, null=False)
likes = models.ManyToManyField(User)
serializers.py
class DetailedTicketSerializer(serializers.ModelSerializer):
# Error occurs on below line: No file associated with ImageField
author_profile_pic = serializers.ReadOnlyField(source='author.profile_pic')
author_username = serializers.ReadOnlyField(source='author.user.username')
class Meta:
model = Ticket
fields = ['id', 'author_profile_pic', 'author_username', 'likes', 'descr']
Anyone knows how do i serialize Account.profile_pic's url???
serialize the account class. in your ticketserializer call the account serializer.
Here an example:
class
HobbySerializer(serializers.ModelSerializer):
class Meta:
model = Hobby
fields = '__all__'
class ProfileSerializer(serializers.ModelSerializer):
user_hobby = HobbySerializer(many=True)
class Meta:
model = Profile
fields = '__all__'

save() prohibited to prevent data loss due to unsaved related object 'user' with Foreign Keys

I am trying to POST a new User in User table and assign attribute to this user in the next related table UserAttribute. UserAttribute table contains 'user' field, which is foreign key to the User table.
User.id = UserAttribute.user
My POST method creates a new record in User table, hovewer I can not create relation in UserAttribute table. I am getting:
save() prohibited to prevent data loss due to unsaved related object 'user'.
It is strange because the User is successfully created in User table.
I tried to save record in two ways. You can find the code on belove.
What is more, I tried transactions too.
models.py
class User(models.Model):
id = models.IntegerField(primary_key = True)
email = models.CharField(unique=True, max_length=180)
roles = models.JSONField(default=dict)
password = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, null=True)
firebase_id = models.CharField(max_length=255, blank=True, null=True)
created_at = models.DateTimeField(default=now)
progress_sub_step = models.IntegerField(blank=True, null=True)
step_available_date = models.DateTimeField(blank=True, null=True)
progress_step = models.IntegerField(blank=True, null=True)
active = models.IntegerField(default=1)
last_login_at = models.DateTimeField(blank=True, null=True)
class Meta:
managed = False
db_table = 'user'
class Attribute(models.Model):
name = models.CharField(max_length=255)
value = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'attribute'
class UserAttribute(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name = 'attribute')
attribute = models.ForeignKey(Attribute, on_delete=models.CASCADE)
class Meta:
managed = False
db_table = 'user_attribute'
serializers.py
class UserAttributeSerializer(serializers.ModelSerializer):
class Meta:
model = UserAttribute
fields = ('attribute',)
class UserSerializer(serializers.ModelSerializer):
attribute = UserAttributeSerializer(many = True)
class Meta:
model = User
fields = ('email', 'name', 'firebase_id', 'attribute')
#transaction.atomic()
def create(self, validated_data):
attributes = validated_data["attribute"]
del validated_data["attribute"]
firebase_id_v = validated_data.get('firebase_id')
user_save = User.objects.create(**validated_data)
# Second method
# user_save = User(**validated_data)
# user_save.save()
for attribute in attributes:
a = UserAttribute.objects.create(user = user_save, **attribute)
return user
views.py
class UserAttViewSet(viewsets.ModelViewSet):
queryset = UserAttribute.objects.all()
serializer_class = UserAttributeSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer

How to save three related models in one DRF endpoint?

I have 4 related models and I need to implement the functionality to consistently create instances of these models in a database in one post query. For this I use override of the APIView class post method.
models
class VendorContacts(models.Model):
contact_id = models.AutoField(primary_key=True)
vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE)
contact_name = models.CharField(max_length=45, blank=True)
phone = models.CharField(max_length=45, blank=True)
email = models.CharField(max_length=80, blank=True, unique=True)
class Meta:
db_table = 'vendor_contacts'
class VendorModuleNames(models.Model):
vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE, primary_key=True)
module = models.ForeignKey(Modules, models.DO_NOTHING)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'vendor_module_names'
unique_together = (('vendor', 'module'),)
class Vendors(models.Model):
COUNTRY_CHOICES = tuple(COUNTRIES)
vendorid = models.AutoField(primary_key=True)
vendor_name = models.CharField(max_length=45, unique=True)
country = models.CharField(max_length=45, choices=COUNTRY_CHOICES)
nda = models.DateField(blank=True, null=True)
user_id = models.ForeignKey('c_users.CustomUser', on_delete=models.PROTECT)
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'vendors'
unique_together = (('vendorid', 'timestamp'),)
class Modules(models.Model):
MODULES_NAME =tuple(MODULES)
mid = models.AutoField(primary_key=True)
module_name = models.CharField(max_length=50, choices=MODULES_NAME)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'modules'
unique_together = (('mid', 'timestamp'),)
serializer.py
class VendorsSerializer(serializers.ModelSerializer):
class Meta:
model = Vendors
fields = ('vendor_name',
'country',
'nda',)
class VendorContactSerializer(serializers.ModelSerializer):
class Meta:
model = VendorContacts
fields = (
'contact_name',
'phone',
'email',)
class VendorModulSerializer(serializers.ModelSerializer):
class Meta:
model = VendorModuleNames
fields = ('module',)
class ModulesSerializer(serializers.ModelSerializer):
class Meta:
model = Modules
fields = ('module_name', )
views.py
class VendorsCreateView(APIView):
"""Create new vendor instances from form"""
def post(self, request, *args, **kwargs):
vendor_serializer = VendorsSerializer(data=request.data)
vendor_contact_serializer = VendorContactSerializer(data=request.data)
vendor_modules_serializer = VendorModulSerializer(data=request.data)
module_serializer = ModulesSerializer(data=request.data)
try:
vendor_serializer.is_valid(raise_exception=True) \
and vendor_contact_serializer.is_valid(raise_exception=True) \
and vendor_modules_serializer.is_valid(raise_exception=True) \
and module_serializer.is_valid(raise_exception=True)
vendor_serializer.save(user_id=request.user)
# ....
# Some new logic here ????
# ...
except ValidationError:
return Response({"errors": (vendor_serializer.errors,
vendor_contact_serializer.errors,
vendor_modules_serializer.errors
)},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(request.data, status=status.HTTP_200_OK)
There is no problem saving one Vendor model, but I can't imagine how to save cascading all related models in a single request.
save returns the newly saved object, which you can then pass into the subsequent save() methods:
vendor = vendor_serializer.save(user_id=request.user)
module = module_serializer.save()
vendor_module = vendor_modules_serializer.save(module=module, vendor=vendor)
vendor_contact = vendor_contact_serializer.save(vendor=vendor)

Django Rest Framework requieres as not null look up field

I have two models:
class Album(models.Model):
code = models.CharField(max_length=10, primary_key=True, default=_create_access_code, verbose_name=_("Id"))
name = models.CharField(max_length=200, verbose_name=_("Name"))
description = models.TextField(null=True, blank=True, verbose_name=_("Description"))
company = models.ForeignKey(Company, on_delete=models.PROTECT, related_name='albums', verbose_name=_("Company"))
access_code = models.CharField(max_length=10, default=_create_access_code, verbose_name=_("Internal Use"))
class Meta:
verbose_name = _("Album")
verbose_name_plural = _("Albums")
def __str__(self):
return "[{}] {} ({})".format(self.pk, self.name, self.company.id)
class Photo(models.Model):
name = models.CharField(max_length=100, null=True, blank=True, verbose_name=_("Name"))
album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name='photos', verbose_name=_("Album"))
photo = models.ImageField(verbose_name=_("Photo"))
class Meta:
verbose_name = _("Photo")
verbose_name_plural =_("Photos")
def __str__(self):
return "[{}] {}".format(self.pk, self.name)
I am trying to make a post to the ModelViewSet for model Albums, but I get an error indicating that field photos is required. Even the OPTIONS method indicates it es required.
How can I instruct DRF for not considering look up fields as required? Is it some serializer setting?
You can add required=False to fields in the serializer.
photos = PhotoSerializer(many=True, required=False)
Something like this. Can you post you serializers?

Many to Many model with a dropdown in Django Rest Framework?

I am trying to create a Many to Many relation with a model in between, I have a Client model, and a Zone model, each client may have access to different zones, and each zone may have multiple clients.
Therefore I created a model called Access Permission, that stores said relation, and I want to show a dropdown selector in the post form that shows the existing clients and zones, or to ask for the Id of an existing object, instead of showing the form to create new ones.
These are my models:
class Zone(models.Model):
name = models.TextField()
created = models.DateTimeField(auto_now=True)
def __str__(self):
return '%s' % (self.name)
class Client(models.Model):
name = models.TextField()
birthDate = models.DateField()
created = models.DateTimeField(auto_now=True)
def __str__(self):
return '%s' % (self.name)
class AccessPermission(models.Model):
idClient = models.ForeignKey(Client, on_delete=models.CASCADE, null=False)
idZone = models.ForeignKey(Zone, on_delete=models.CASCADE, null=False)
And these my current serializers:
class ZoneSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Zone
fields = ('name',)
class ClientSerializer(serializers.HyperlinkedModelSerializer):
zones = ZonesSerializer(source='accesspermission_set', many=True, read_only=True)
class Meta:
model = Client
fields = ('name', 'birthDate', 'zones')
class AccessPermissionSerializer(serializers.ManyRelatedField):
idClient = ClientSerializer(many=False)
idZone = ZoneSerializer(many=False)
class Meta:
model = AccessPermission
fields = ('idClient', 'idZone')
Is there any way to ask for the Id of an existing object, or show the existing ones, instead of the fields to create new ones?
You can do it like:
models
class AccessPermission(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE, null=False)
zone = models.ForeignKey(Zone, on_delete=models.CASCADE, null=False)
serializers
class AccessPermissionSerializer(serializers.ManyRelatedField):
id = serializers.IntegerField(read_only=True)
client_id = serializers.PrimaryKeyRelatedField(
queryset=Client.objects.all(), source='client', allow_null=False, required=True
)
zone_id = serializers.PrimaryKeyRelatedField(
queryset=Zone.objects.all(), source='zone', allow_null=False, required=True
)
class Meta:
model = AccessPermission
fields = (
'id', 'client_id', 'zone_id'
)

Categories

Resources