MongoDB ObjectId "Instantiation" and saving - python-3.x

I use Django + MongoDB /Djongo for backend on Windows10/VSCode. How is it to instantiate document’s “ObjectId” like it is for other fields using Python? I have been struggling for a several days. Please help. Code example, below:
from djongo import models
class Blog(models.Model):
id= models.AutoField(
auto_created = True,
unique=True,
primary_key = True,
serialize = False,
verbose_name ='ID_nama: ')
name = models.CharField(max_length=100)
tagline = models.TextField()
def __str__(self):
return self.name, self.id
# return self.tagline
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
def __str__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField(default=date.today)
authors = models.ManyToManyField(Author)
number_of_comments = models.IntegerField(default=0)
number_of_pingbacks = models.IntegerField(default=0)
rating = models.IntegerField(default=5)
def __str__(self):
return self.headline
Here is the document JSON from MongodDB:
{
“_id”: {
“$oid”: “626b6627f0d91c65e9f78cc6”
},
“id”: 5,
“name”: “Beatles Blog”,
“tagline”: “Beatles tour of the Americas.”
}
My target is to be able to capture the “ObjectId” => “_id”: {
“$oid”: “626b6627f0d91c65e9f78cc6”, and save it to another new field for other use/purpose.

Related

how to post data in a nested serializer in Django rest framework

I am working on an app and need help I want to authenticate LinkedIn and save the access token in a table and then collect the LinkedIn user details in another table below is my model.py
class LinkedInUserCode(models.Model):
"""
Credentials for the user to give access to LinkedIn.
"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
token = models.CharField(max_length=1024)
expires_in = models.IntegerField()
def __str__(self):
return f'{self.token}'
class Meta:
db_table = 'linkedin_user_code'
verbose_name_plural = "LinkedIn User Codes"
class LinkedInProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
linkedin_id = models.CharField(max_length=1024, blank=True, null=True)
first_name = models.CharField(max_length=1024, blank=True, null=True)
last_name = models.CharField(max_length=1024, blank=True, null=True)
profile_image_url = models.CharField(max_length=1024, blank=True, null=True)
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.linkedin_id}'
class Meta:
db_table = 'linkedin_profile'
verbose_name_plural = "LinkedIn Profiles"
I am using a nested serializer and this is my serialiser
class LinkedInProfileSerializer(ModelSerializer):
"""
Serializer for the LinkedInProfile model.
"""
id = IntegerField(required=False)
user = ReadOnlyField(source='user.email')
linkedin_access = ReadOnlyField(source='linkedin_access.token')
class Meta:
model = LinkedInProfile
fields = '__all__'
def create(self, validated_data):
"""
Create a new LinkedInProfile instance.
"""
return LinkedInProfile.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.linkedin_id = validated_data.get('linkedin_id')
instance.first_name = validated_data.get('first_name')
instance.last_name = validated_data.get('last_name')
instance.profile_image_url = validated_data.get('profile_image_url')
instance.linkedin_access = validated_data.get('linkedin_access')
instance.save()
return instance
class LinkedInUserCodeSerializer(ModelSerializer):
user = ReadOnlyField(source='user.email')
profiles = LinkedInProfileSerializer(many=True, read_only=True)
class Meta:
model = LinkedInUserCode
fields = ['user', 'token', 'expires_in', 'profiles']
def create(self, validated_data):
""" Create and return necessary credentials for linkedin."""
profile = validated_data.pop('profiles')
access_token = LinkedInUserCode.objects.create(**validated_data)
for profile_data in profile:
LinkedInProfile.objects.create(linkedin_access=access_token, **profile_data)
return access_token
def update(self, instance, validated_data):
profiles = validated_data.pop('profiles')
instance.token = validated_data.get('token', instance.token)
instance.expires_in = validated_data.get('expires_in', instance.expires_in)
instance.save()
temp_profile = []
existing_ids = [profiles.get('linkedin_id') for profile in instance.profiles.all()]
for profile_data in profile:
if profile_data.get('linkedin_id') in existing_ids:
temp_profile.append(LinkedInProfile.objects.get(linkedin_id=profile_data.get('linkedin_id')))
else:
temp_profile.append(LinkedInProfile.objects.create(linkedin_access=instance, **profile_data))
instance.profiles.set(temp_profile)
for profile in instance.profiles.all():
if profile not in temp_profile:
profile.delete()
return instance
I have written a script that I am using to make requests to the LinkedIn api and here is my view I want to populate it at once any idea how I can go about it I keep having issues with the foreign key of LinkedIn_access
class LinkedInCallbackAPIView(APIView):
"""
This View is used to get and save the Access Token from LinkedIn authorization page.
"""
def get(self, request, *args, **kwargs):
response = request.GET
if response is not None and state != response.get('state'):
return Response({'error': "Invalid state"}, status=status.HTTP_401_UNAUTHORIZED)
else:
queryset = LinkedInUserCode.objects.filter(user=request.user)
code = response.get('code')
access_token = linkedin.get_access_token(code)
profile = linkedin.get_user_profile(access_token.get('access_token'))
profile = {
'linkedin_id': profile.get('id'),
'first_name': profile.get('firstName').get('localized').get('en_US'),
'last_name': profile.get('lastName').get('localized').get('en_US'),
'profile_image_url': profile.get('profilePicture').get('displayImage'),
}
data = {
'token': access_token.get('access_token'),
'expires_in': access_token.get('expires_in'),
'user': request.user,
'profiles': profile,
}
serializer = LinkedInUserCodeSerializer(data=data)
if queryset.exists():
serializer.update(queryset.first(), data)
return Response({'message': 'Your LinkedIn user Access Token was Updated'},status=status.HTTP_200_OK)
if serializer.is_valid():
serializer.save(**data)
# there will be a return response here
I need help passing this table and not using a single table for it
thank you

Django rest framework: how can I serialize multiple table to get combine JSON output

I am very new to django, any help highly appreciated. thanks in advance!
Here is my code 'model.py'
class Stocks(models.Model):
ticker = models.CharField(max_length=30, primary_key=True, unique=True)
company_name = models.CharField(max_length=100, blank=True, null=True)
sector = models.CharField(max_length=50, blank=True, null=True)
class Meta:
db_table = 'stocks'
def __str__(self):
return "%s %s %s" % (self.ticker, self.company_name, self.sector)
class QuarterlyFinance(models.Model):
ticker = models.ForeignKey(Stocks, db_column='ticker',on_delete=models.CASCADE,
related_name='quarter_result', blank=True, null=True)
quarter_end = models.DateTimeField(blank=True, null=True)
total_revenue = models.FloatField(blank=True, null=True)
net_income = models.FloatField(blank=True, null=True)
class Meta:
db_table = 'quarterly_finance'
unique_together = (('ticker', 'quarter_end'),)
def __str__(self):
return "%s %s %s %s" % (self.ticker, self.quarter_end, self.total_revenue,
self.net_income)
serialize.py
class StocksSerialize(serializers.ModelSerializer):
class Meta:
model=Stocks
fields="__all__"
depth=1
class QuarterlyFinanceSerialize(serializers.ModelSerializer):
class Meta:
model=QuarterlyFinance
fields=['quarter_end', 'total_revenue','net_income']
depth=1
view.py
class DataClassView(APIView):
def get(self, request, format=None):
max_day = Advice.objects.latest('advice_date').advice_date
max_day=max_day.strftime("%Y-%m-%d")
qfinance = QuarterlyFinance.objects.filter(ticker='TCS')
stk = Stocks.objects.filter(ticker='TCS')
qfin_ser_obj = QuarterlyFinanceSerialize(qfinance, many=True)
stock_ser_obj = StocksSerialize(stk, many=True)
result = stock_ser_obj.data +qfin_ser_obj.data
return Response(result)
I want to return JSON output like this:
{
"ticker": "TCS",
"company_name": "Tata Consultancy Services Ltd",
"sector": "IT",
"qtr_result": [
{
"quarter_end": "2021-06-30T04:00:00",
"total_revenue": 454110000000,
"net_income": 90080000000
},
{
"quarter_end": "2021-03-31T04:00:00",
"total_revenue": 437050000000,
"net_income": 92460000000
},
{
"quarter_end": "2020-12-31T05:00:00",
"total_revenue": 420150000000,
"net_income": 87010000000
},
{
"quarter_end": "2020-09-30T04:00:00",
"total_revenue": 401350000000,
"net_income": 74750000000
}
]
}
my code is working but I am getting data from both table in separate array within JSON. I want QuarterlyFinance data should be inside Stock table data as an array.
class StocksSerialize(serializers.ModelSerializer):
quarter_result = QuarterlyFinanceSerialize(read_only=True, many=True)
class Meta:
model=Stocks
fields="__all__"
depth=1

How to overwrite data from a model that is linked to the main model through a o-t-m relationship?

I have three models that are related to each other, namely:
models.py
class Shop(models.Model):
number = models.PositiveSmallIntegerField()
name = models.CharField(db_index=True)
city = models.ForeignKey(ShopCity, on_delete=models.CASCADE)
class Product(models.Model):
name = models.CharField(db_index=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
class ProductQuantity(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
shop = models.ForeignKey(Shop, on_delete=models.CASCADE)
quantity = models.PositiveSmallIntegerField(default=None)
In the admin panel they are linked in this way:
admin.py
class ProductQuantityInline(admin.TabularInline):
model = ProductQuantity
extra = 0
#admin.register(Product)
class ProductAdmin(ImportExportActionModelAdmin):
fields = ['name', 'price']
list_display = ['name', 'price']
inlines = [ProductQuantityInline]
There is a need to overwrite data with REST API
serializers.py
class QuantitySerializer(serializers.ModelSerializer):
class Meta:
model = ProductQuantity
fields = ('shop', 'quantity')
class ProductSerializer(serializers.ModelSerializer):
productquantity = serializers.SerializerMethodField(read_only=False)
class Meta:
model = Product
fields = ('name', 'price', 'productquantity')
def get_productquantity(self, obj):
return [QuantitySerializer(s).data for s in obj.productquantity_set.all()]
And finally my handler for REST API:
views.py
#api_view(['GET', 'PATCH', 'PUT', 'DELETE'])
def api_product_detail(request, pk):
product = Product.objects.get(pk=pk)
if request.method == 'GET':
serializer = ProductSerializer(product)
return Response(serializer.data)
elif request.method == 'PUT' or request.method == 'PATCH':
serializer = ProductSerializer(product, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
product.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
As a result, data such as the name and price are overwritten, and the productquantity is not overwritten.
What am I doing wrong? Thanks for any help.

How do I get my Django serializer to save my foreign key objects?

I'm using Python 3.8 and Django 3. I have the following models. Notice the second has foreign keys to the first ...
class ContactMethod(models.Model):
class ContactTypes(models.TextChoices):
EMAIL = 'EMAIL', _('Email')
PHONE = 'PHONE', _('Phone')
type = models.CharField(
null=False,
max_length=5,
choices=ContactTypes.choices,
)
phone = PhoneNumberField(null=True)
email = models.EmailField(null=True)
class Meta:
unique_together = ('phone', 'email',)
class Coop(models.Model):
objects = CoopManager()
name = models.CharField(max_length=250, null=False)
types = models.ManyToManyField(CoopType, blank=False)
addresses = models.ManyToManyField(Address)
enabled = models.BooleanField(default=True, null=False)
phone = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_phone')
email = models.ForeignKey(ContactMethod, on_delete=models.CASCADE, null=True, related_name='contact_email')
web_site = models.TextField()
Using the Django rest framework, I have crated the following serializers to help save data ...
class ContactMethodPhoneSerializer(serializers.ModelSerializer):
class Meta:
model = ContactMethod
fields = ['type', 'phone']
read_only_fields = ['type']
extra_kwargs = {'type': {'default': 'PHONE'}}
class CoopSerializer(serializers.ModelSerializer):
types = CoopTypeSerializer(many=True, allow_empty=False)
addresses = AddressTypeField(many=True)
phone = ContactMethodPhoneSerializer()
email = ContactMethodEmailSerializer()
class Meta:
model = Coop
fields = '__all__'
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['types'] = CoopTypeSerializer(instance.types.all(), many=True).data
rep['addresses'] = AddressSerializer(instance.addresses.all(), many=True).data
return rep
def create(self, validated_data):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
coop_types = validated_data.pop('types', {})
phone = validated_data.pop('phone', {})
email = validated_data.pop('email', {})
instance = super().create(validated_data)
for item in coop_types:
coop_type, _ = CoopType.objects.get_or_create(name=item['name'])
instance.types.add(coop_type)
instance.phone = ContactMethod.objects.create(type=ContactMethod.ContactTypes.PHONE, **phone)
instance.email = ContactMethod.objects.create(type=ContactMethod.ContactTypes.EMAIL, **email)
return instance
However, in unit testing (and actual), when I attempt to save data like so
serializer_data = {
"name": name,
"types": [
{"name": coop_type_name}
],
"addresses": [{
"formatted": street,
"locality": {
"name": city,
"postal_code": postal_code,
"state": state.id
}
}],
"enabled": enabled,
"phone": {
"phone": phone
},
"email": {
"email": email
},
"web_site": web_site
}
serializer = CoopSerializer(data=serializer_data)
assert serializer.is_valid(), serializer.errors
coop_saved = serializer.save()
coop = Coop.objects.get(pk=coop_saved.id)
...
assert coop.phone.phone == phone
The foreign key fields (email and phone) are not saving (they are null). All the other fields save properly. What else am I missing in order to save my foreign key fields successfully?
Because you did not call save in the end:
def create(self, validated_data):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
coop_types = validated_data.pop('types', {})
phone = validated_data.pop('phone', {})
email = validated_data.pop('email', {})
instance = super().create(validated_data)
for item in coop_types:
coop_type, _ = CoopType.objects.get_or_create(name=item['name'])
instance.types.add(coop_type)
instance.phone = ContactMethod.objects.create(type=ContactMethod.ContactTypes.PHONE, **phone)
instance.email = ContactMethod.objects.create(type=ContactMethod.ContactTypes.EMAIL, **email)
# call save here
instance.save()
return instance

Django AttributeError 'Tag' object has no attribute 'summary'

I run into this error whenever I tried to add a new Tag. I tried to google and read some SO posts, but nothing work for me.
Here are my 2 models :
Summary :
class Summary(models.Model):
question_text = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
url = models.URLField(null=False)
cover_image = models.CharField(max_length=255)
tags = models.ManyToManyField('Tag', related_name='summaries', blank=True)
userProfileSummary = models.ManyToManyField('UserProfile', through='UserProfileSummary')
def __str__(self):
return self.question_text
class Meta:
verbose_name_plural = "Summaries"
Tag :
class Tag(models.Model):
name = models.CharField(max_length=255)
description = models.TextField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
models/init.py:
...
from .tag import Tag
from .summary import Summary
__all__ = (
...
'Tag',
'Summary',
)
Error :
Please, what did I miss ?

Resources