In The Models.py file (I have this codebase)
class Person(models.Model):
sex_choices = (
('Male', 'Male'),
('Female', 'Female')
)
martial_choices = (
('Single', 'Single'),
('Married', 'Married'),
('Divorce', 'Divorce'),
('Widowed', 'Widowed')
)
name = models.CharField(max_length=200)
sex = models.CharField(choices=sex_choices, max_length=50)
martial_status = models.CharField(choices=martial_choices, max_length=50)
age = models.IntegerField()
def __str__(self):
return self.name
class DetailsOfEducationQualification(models.Model):
type_choice = (
("Government", "Government"),
("Private", "Private"),
("Anganwadi Center", "Anganwadi Center"),
)
education_proximity_choice = (
("0-5", '0-5km'),
('5-10', '5-10km'),
('10+', 'Above 10km'),
('Outside the state', 'Outside the state'),
)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
course_class = models.CharField(max_length=50, blank=True)
type_of_education_sector = models.CharField(choices=type_choice, max_length=50, blank=True)
education_facility_proximity = models.CharField(choices=education_proximity_choice, max_length=50, blank=True)
In The Admin.py file (I have this)
from .models import (
Person, DetailsOfEducationQualification
)
class DetailsOfEducationQualificationInline(admin.TabularInline):
model = DetailsOfEducationQualification
extra = 0
class PersonAdmin(admin.ModelAdmin):
fieldsets = [
(
'Personal Information', {
'fields':[
'name', 'sex', 'age', 'martial_status'
]
}
),
]
inlines = [
DetailsOfEducationQualificationInline
]
In query shell, I want to get the person 'course_class' since the DetailsOfEducationQualification model is related to Person:
like in he query:
person = Person.objects.get(id=1)
person.course_class
this code gets an error, saying person does not have the attribute...
How do I access the DetailsOfEducationQualification date from the Person model?
course_class is an attribute of DetailsOfEducationQualification class, and not an attribute of Person class,
so you won't be able to access it from a person object.
detail = DetailsOfEducationQualification.objects.get(id=1)
detail.course_class
the above code will return the course_class of DetailsOfEducationQualification with id 1.
if you want to access course_class from a Person object,
then you can use
person = Person.objects.get(id=1)
person.detailsofeducationqualification_set.first().course_class
person.detailsofeducationqualification_set is the Queryset of all DetailsOfEducationQualification objects that has person with id 1 as foreign key.
and, person.detailsofeducationqualification_set.first() will be the first element of the queryset.
hope it helps.
Related
I encounter a really weird bug. When annotating 3 values (AVG, COUNT and SUM) I notice that COUNT and SUM are multiplying each other.
For instance:
The duration should be half the time and there are only 2 ratings (number_of_ratings - COUNT, album_duration - SUM).
I have these annotations in queryset in ViewSet class
class AlbumViewSet(ModelViewSet):
queryset = Album.objects \
.prefetch_related("tracks", "album_genres", "album_genres__genre_id", "album_links", "reviews") \
.select_related("aoty", "artist_id") \
.annotate(overall_score=Avg("reviews__rating", output_field=IntegerField()),
number_of_ratings=Count("reviews__rating", output_field=IntegerField()),
album_duration=Sum("tracks__duration", output_field=DurationField()))
Here are other files
models.py
class Album(models.Model):
RELEASE_TYPE_ALBUM_CHOICES = [
("LP", "LP"),
("EP", "EP"),
("Single", "Single"),
("Live", "Live"),
]
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
release_date = models.DateField()
artist_id = models.ForeignKey(
Artist, on_delete=models.PROTECT, related_name="albums"
)
art_cover = ResizedImageField(
size=[750, 750], null=True, blank=True, upload_to=rename_album_art_cover)
release_type = models.CharField(max_length=10,
choices=RELEASE_TYPE_ALBUM_CHOICES, default="LP")
created_at = models.DateTimeField(auto_now_add=True)
class Track(models.Model):
title = models.CharField(max_length=255)
position = models.PositiveIntegerField()
album_id = models.ForeignKey(
Album, on_delete=models.PROTECT, related_name="tracks")
duration = models.DurationField(null=True)
class Review(models.Model):
reviewer_id = models.ForeignKey(Reviewer, on_delete=models.PROTECT)
rating = models.IntegerField(
validators=[MaxValueValidator(100), MinValueValidator(0)]
)
review_text = models.TextField(null=True, blank=True)
album_id = models.ForeignKey(
Album, on_delete=models.PROTECT, related_name="reviews")
created_at = models.DateTimeField(auto_now_add=True)
serializer.py
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True)
genres = StringRelatedField(
source="album_genres", many=True)
aoty = StringRelatedField(read_only=True)
links = AlbumLinkSerializer(
source="album_links", many=True, read_only=True)
artist = SimpleArtistSerializer(source="artist_id", read_only=True)
overall_score = serializers.IntegerField(read_only=True)
number_of_ratings = serializers.IntegerField(read_only=True)
album_duration = serializers.DurationField(read_only=True)
class Meta:
model = Album
fields = [
"id",
"title",
"slug",
"created_at",
"artist",
"art_cover",
"genres",
"overall_score",
"number_of_ratings",
"release_date",
"release_type",
"tracks",
"album_duration",
"links",
"aoty"
]
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ["position", "title", "duration", "album_id"]
class ReviewSerializer(serializers.ModelSerializer):
reviewer = SimpleReviewerSerializer(source="reviewer_id", read_only=True)
album = ReviewAlbumSerializer(source="album_id", read_only=True)
class Meta:
model = Review
fields = [
"id",
"reviewer_id",
"reviewer",
"rating",
"review_text",
"album_id",
"album",
"created_at"
]
For anyone that would encounter the same problem, here's how I worked it out.
There should be distinct property set in every annotate function.
.annotate(overall_score=Avg("reviews__rating", output_field=IntegerField()),
number_of_ratings=Count("reviews__rating", output_field=IntegerField(), distinct=True),
album_duration=Sum("tracks__duration", output_field=DurationField(), distinct=True))
How to serialize data from many-to-many field with through parameter?
I have 3 models:
class Ingredient(models.Model):
name = models.CharField(
max_length=200,
)
measurement_unit = models.CharField(
max_length=200,
)
class Recipe(models.Model):
name = models.CharField(
max_length=200,
)
ingredients = models.ManyToManyField(
Ingredient,
through='RecipeIngredientsDetails',
)
class RecipeIngredientsDetails(models.Model):
recipe = models.ForeignKey(
Recipe,
on_delete=models.CASCADE,
)
ingredient = models.ForeignKey(
Ingredient,
on_delete=models.CASCADE,
)
amount = models.FloatField()
My serializers:
class IngredientSerializer(ModelSerializer):
# amount = ???
class Meta:
model = Ingredient
fields = ["id", "name", "amount", "measurement_unit"]
class RecipeSerializer(ModelSerializer):
class Meta:
model = Recipe
fields = ["name", "ingredients"]
depth = 1
Now, I get:
{
"name": "Nice title",
"ingredients": [
{
"id": 1,
"name": "salt",
"measurement_unit": "g"
},
{
"id": 2,
"name": "sugar",
"measurement_unit": "g"
}
]
}
I need amount-value in every ingredient. How can I implement it?
You need to change IngredientSerializer to use the RecipeIngredientsDetails model, and also explicitly set the related serializer inside the RecipeSerializer:
from rest_framework.serializers import ReadOnlyField
class IngredientDetailSerializer(ModelSerializer):
id = ReadOnlyField(source='ingredient.id')
ingredient = ReadOnlyField(source='ingredient.name')
measurement_unit = ReadOnlyField(source='ingredient.measurement_unit')
class Meta:
model = RecipeIngredientsDetails
fields = ["id", "ingredient", "measurement_unit", "amount",]
class RecipeSerializer(ModelSerializer):
ingredients = IngredientDetailSerializer(source="recipeingredientsdetails_set", many=True)
class Meta:
model = Recipe
fields = ["name", "ingredients"]
depth = 1
I'm attempting to get a JSON output similar to this:
{
name: John Doe,
best_buy_price: 420,
best_sell_price: 69,
player_profile: {
tsn_link: https://a_link.com
}
playerlistingadvanced: { # This is where I'm having the issue
sales_minute: 7,
}
}
I have three models. playerProfile being the "main" model and playerListing and playerListingAdvanced are connected to playerProfile via a one-to-one relationship. playerPfofile will have its own endpoint, but I'd also like to create an endpoint that is primarily the listings and advanced listing data (as seen above).
Here is a stripped down version of the model.py file:
class PlayerProfile(models.Model):
card_id = models.CharField(max_length=120, unique=True, primary_key=True)
name = models.CharField(max_length=420, null=True)
tsn_link = models.CharField(max_length=420, null=True)
class PlayerListing(models.Model):
player_profile = models.OneToOneField(
PlayerProfile,
on_delete=models.CASCADE,
null=True)
name = models.CharField(max_length=420, null=True)
best_sell_price = models.IntegerField(null=True)
best_buy_price = models.IntegerField(null=True)
class PlayerListingAdvanced(models.Model):
player_profile = models.OneToOneField(
PlayerProfile,
on_delete=models.CASCADE,
null=True)
sales_minute = models.DecimalField(max_digits=1000, decimal_places=2, null=True)
Here is the serializer.py I have tried, but haven't gotten to work.
class PlayerListingAdvancedForNestingSerializer(serializers.ModelSerializer):
class Meta:
model = PlayerListingAdvanced
fields = (
'sales_minute',
'last_week_average_buy',
'last_week_average_sell',
)
class PlayerListingSerializer(serializers.ModelSerializer):
player_profile = PlayerProfileForListingSerializer() # works
playerlistingadvanced = PlayerListingAdvancedForNestingSerializer() #doesn't work
class Meta:
model = PlayerListing
fields = (
'name',
'best_sell_price',
'best_buy_price',
'playerlistingadvanced',
'player_profile'
)
I'm assuming because playerListing and playerListingAdvanced are not directly related, that I'll need to do something else to make this work. Can someone point me in the right direction?
You can use SerializerMethodField. Your assuming is correct. Try this:
class PlayerListingSerializer(serializers.ModelSerializer):
player_profile = PlayerProfileForListingSerializer()
playerlistingadvanced = serializers.SerializerMethodField()
class Meta:
model = PlayerListing
fields = (
'name',
'best_sell_price',
'best_buy_price',
'playerlistingadvanced',
'player_profile'
)
def get_playerlistingadvanced(self, obj: PlayerListing):
player_profile = obj.player_profile
if hasattr(player_profile, 'playerlistingadvanced'):
serializer = PlayerListingAdvancedForNestingSerializer(instance=player_profile.playerlistingadvanced)
return serializer.data
return None
how use limit_choices_to in django
class Category(models.Model):
"""
商品类别
"""
CATEGORY_TYPE = (
(1, "一级类目"),
(2, "二级类目"),
(3, "三级类目"),
)
def limit_category_type_choice(self):
obj = Category.objects.get(category_type=self.category_type)
field_object = Category._meta.get_field('category_type')
field_value = field_object.value_from_object(obj)
return {'category_type__lte': field_value}
category_id = models.AutoField(primary_key=True, verbose_name='category_id')
category_title = models.CharField(default='', max_length=50, verbose_name='目录标题', help_text='目录标题')
category_name = models.ForeignKey(LinkDesignate,blank=True, null=True, to_field='link_des_text_id', related_name='category', on_delete=models.CASCADE)
category_type = models.IntegerField(choices=CATEGORY_TYPE, verbose_name="类目级别", help_text="类目级别")
parent_category = models.ForeignKey("self", limit_choices_to=self.limit_category_type_choice, null=True, blank=True, verbose_name="父类目级别", help_text="父目录",
related_name="sub_cat", on_delete=models.CASCADE)
class Meta:
verbose_name = "产品目录"
verbose_name_plural = verbose_name
i know this
limit_choices_to=self.limit_category_type_choice,
this is wrong , because name 'self' is not defined
how can to use the function limit_category_type_choice
the document is:
def limit_pub_date_choices():
return {'pub_date__lte': datetime.date.utcnow()}
limit_choices_to = limit_pub_date_choices
how can i change my Function limit_category_type_choice without self
but can use the self instance
Put the def out of the class ;-)
This was my solution, it is similar.
It limits the films which can be choosen for an event.
Films with status '2' in class Film over ForeignKey OR
over reverse ForeignKey: Films with an Event with date in the future
the model:
def limit_film_choices():
date = str(datetime.datetime.now())
result = Q( status = '2') | Q( event_film__date__gte = date)
return result
class Film(models.Model):
STATUS_COICES = [
('1' , 'a'),
('2' , 'b'),
]
status = models.CharField( max_length=16, choices=STATUS_COICES, default='1')
class Event(models.Model):
film = models.ForeignKey('filme.Film', on_delete=models.CASCADE, related_query_name='event_film',
related_name='event_film', blank = True, null=True, limit_choices_to = limit_film_choices)
date = models.DateTimeField(auto_now=False, null=True)
I am trying to Update A Employee. I am able to update also. But the problem is coming a while updating when i am not sending data in body. It is giving error of Required Field.
This error is one of kind - where i was not sending excempt in json body
serializer2 {'excempt': [ErrorDetail(string='This field is required.', code='required')]}
Even i tried to put required=False and it is working but i am not understanding if we are passing instance of that EmployeeProfileSerializer(userprofile, data=request.data). Example userprofile but why it is still it is giving error. And how should i tackle it. I don't think this is the solution required=False?.
When i am not sending data in body then the previous data should be used but this is not happening instead it is giving error of required field
APIView
class EmployeeUpdateApiV2(APIView):
def post(self, request, *args, **kwrgs):
try:
accesstoken=AccessToken.objects.get(
token=self.request.META.get('HTTP_AUTHORIZATION').replace('Bearer ', '')
)
except ObjectDoesNotExist:
return Response (
{
"status" : False,
"error" : "Wrong Access Token",
"error_message":"You have provided wrong access token.",
}
)
user_id = request.data['user_id']
user = get_object_or_404(User, id=user_id)
print(user)
userprofile = get_object_or_404(UserProfile, user=user_id)
print(userprofile)
serializer1 = EmployeeRegisterSerializer(user, data=request.data)
serializer2 = EmployeeProfileSerializer(userprofile, data=request.data)
if serializer1.is_valid() and serializer2.is_valid():
serializer1.save()
serializer2.save()
print('Inside Valid')
return Response (
{
"status" : True,
"message":"Employee Updated Successfully.",
"api_name" : "EmployeeUpdateApiV2",
"result": serializer1.data,
"result1": serializer2.data,
}
)
print('Out Valid')
print('serializer1 ', serializer1.errors)
print('serializer2', serializer2.errors)
return Response(status=status.HTTP_404_NOT_FOUND)
Serializers.py
class EmployeeProfileSerializer(serializers.ModelSerializer):
employee_id = serializers.CharField(source='user_employee_id')
payroll_id = serializers.CharField(source='user_payroll_id')
hire_date = serializers.CharField(source='user_hire_date')
pay_rate = serializers.CharField(source='user_pay_rate')
salaried = serializers.CharField(source='user_salaried')
excempt = serializers.CharField(source='user_excempt')
groups = serializers.CharField(source='user_groups_id', required=False)
state = serializers.CharField(source='user_state')
city = serializers.CharField(source='user_city')
zipcode = serializers.CharField(source='user_zipcode')
status = serializers.CharField(source='user_status')
phone = serializers.CharField(source='user_phone')
class Meta:
model = UserProfile
fields = [
'employee_id',
'phone',
'payroll_id',
'hire_date',
'pay_rate',
'salaried',
'excempt',
'groups',
'state',
'city',
'zipcode',
'status',
]
class EmployeeRegisterSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['first_name','last_name', 'email',]
Userprofile Model
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
user_company = models.ForeignKey(Company, on_delete=models.CASCADE)
user_role = models.ForeignKey(ACLRoles, on_delete=models.CASCADE)
user_dob = models.DateField(null=True, blank=True)
user_phone = models.CharField(max_length=30, blank=True, null=True)
user_image = models.ImageField(upload_to='user_profiles/', default='default_user.png',blank=True, null=True)
user_created = models.DateTimeField(auto_now_add=True)
user_is_deleted = models.BooleanField(default=False)
user_deleted_at = models.DateTimeField(blank=True, null=True)
user_groups = models.ManyToManyField(Groups,related_name='user_groups')
MALE = 'Male'
FEMALE = 'Female'
GENDER_CHOICES = (
(MALE, 'Male'),
(FEMALE, 'Female'),
)
user_gender = models.CharField(
max_length=8,
choices=GENDER_CHOICES,
)
ACTIVE = 'Active'
INACTIVE = 'Inactive'
PENDING = 'Pending'
USER_ACTIVE_CHOICES = (
(ACTIVE, 'Active'),
(INACTIVE, 'Inactive'),
(PENDING, 'Pending'),
)
user_status = models.CharField(
max_length=8,
choices=USER_ACTIVE_CHOICES,
default=ACTIVE,
)
please add user in your Model Serializer field section
class EmployeeProfileSerializer(serializers.ModelSerializer):
employee_id = serializers.CharField(source='user_employee_id')
payroll_id = serializers.CharField(source='user_payroll_id')
hire_date = serializers.CharField(source='user_hire_date')
pay_rate = serializers.CharField(source='user_pay_rate')
salaried = serializers.CharField(source='user_salaried')
excempt = serializers.CharField(source='user_excempt')
groups = serializers.CharField(source='user_groups_id', required=False)
state = serializers.CharField(source='user_state')
city = serializers.CharField(source='user_city')
zipcode = serializers.CharField(source='user_zipcode')
status = serializers.CharField(source='user_status')
phone = serializers.CharField(source='user_phone')
class Meta:
model = UserProfile
fields = [
'employee_id',
'phone',
'payroll_id',
'hire_date',
'pay_rate',
'salaried',
'excempt',
'groups',
'state',
'city',
'zipcode',
'status',
'user',
]