Django - Getting an object from an object - python

I'm trying to get the object "Book" from prommotion. Book is a ForeignKey in "prommotion", and I filtered all the prommotions that are active. I need to get the "Book" object from the Prommotion if its active and return it.
(And I know promotion is spelled wrong)
Views:
class Book_PrommotionViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Prommotion.objects.filter(active=True)
serializer = PrommotionSerializer(queryset, many=True)
return Response(serializer.data, HTTP_200_OK)
Prommotion Model:
class Prommotion(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
precent = models.DecimalField(decimal_places=2, max_digits=255, null=True, blank=True)
active = models.BooleanField(default=False)
date_from = models.DateField()
date_to = models.DateField()
book = models.ForeignKey(Book, on_delete=models.SET_NULL, null=True, blank=True)
country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'Prommotion'
verbose_name_plural = 'Prommotions'
Book Model:
class Book(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
title = models.CharField(max_length=255, null=True, blank=True)
author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True, blank=True)
price = models.DecimalField(decimal_places=2, max_digits=255)
published = models.DateField()
edition = models.CharField(max_length=255)
isbn_code = models.CharField(max_length=255)
pages = models.IntegerField(blank=True, null=True, default=0)
description = models.TextField(null=True, blank=True)
cover = models.CharField(max_length=30, choices=Cover.choices(), default=None, null=True, blank=True)
genre = models.CharField(max_length=30, choices=Genre.choices(), default=None, null=True, blank=True)
language = models.CharField(max_length=30, choices=Language.choices(), default=None, null=True, blank=True)
format = models.CharField(max_length=30, choices=Format.choices(), default=None, null=True, blank=True)
publisher = models.CharField(max_length=30, choices=Publisher.choices(), default=None, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
class Meta:
verbose_name = 'Book'
verbose_name_plural = 'Books'

The first way to get all Books that are related to your active promotions is to extract the book ids from the queryset and pass it to a Book filter
active_promotions = Prommotion.objects.filter(active=True)
Book.objects.filter(id__in=active_promotions.values('book_id'))
Or simply filter books with active promotions by using the double underscore syntax to follow relationships
Book.objects.filter(prommotion__active=True).distinct()

Related

Django Relational managers

I was trying to delete my Apllication model:
class Application(models.Model):
app_type = models.ForeignKey(ApplicationCategory, on_delete=models.CASCADE, related_name='applications')
fio = models.CharField(max_length=40)
phone_number = models.CharField(max_length=90)
organisation_name = models.CharField(max_length=100, null=True, blank=True)
aid_amount = models.PositiveIntegerField()
pay_type = models.CharField(max_length=1, choices=PAY_CHOICES, default=PAY_CHOICES[0][0])
status = models.ForeignKey(AppStatus, on_delete=models.CASCADE, related_name='applications', null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
benefactor = models.ForeignKey(Benefactor, on_delete=models.CASCADE, related_name='applications', null=True)
def __str__(self):
return f"id={self.id} li {self.fio} ning mablag\'i!"
and this was my Benefactor model:
class Benefactor(models.Model):
fio = models.CharField(max_length=255)
phone_number = models.CharField(max_length=9)
image = models.ImageField(upload_to='media/')
sponsory_money = models.IntegerField()
organisation_name = models.CharField(max_length=55, null=True, blank=True)
def __str__(self):
return f"{self.fio}"
But I got the below message on superAdmin Panel:
TypeError at /admin/api/benefactor/
create_reverse_many_to_one_manager.\<locals\>.RelatedManager.__call__() missing 1 required keyword-only argument: 'manager'
I would expect delete smoothly!!
Your Benefactor model has several ForeignKey relationships that share the related_name. Give each a unique name and rerun your migrations.

Cannot assign "'Sample Category'": "Product.category" must be a "Category" instance

While creating new products I'm getting such kind of error. Can someone help me?
class Product(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name_geo = models.CharField(max_length=200, null=True, blank=True)
image = models.ImageField(null=True, blank=True, default='/placeholder.png')
brand = models.CharField(max_length=200, null=True, blank=True)
category = models.ForeignKey(Category, null=False, default=0, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
countInStock = models.IntegerField(null=True, blank=True, default=0)
createdAt = models.DateTimeField(auto_now_add=True)
_id = models.AutoField(primary_key=True, editable=False)
def __str__(self):
return self.name_geo
class Category(models.Model):
_id = models.AutoField(primary_key=True, editable=False)
name = models.CharField(max_length=200, null=True, blank=True)
createdAt = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
#api_view(['POST'])
def createProduct(request):
user = request.user
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category="Sample Category",
price=0,
brand='Sample Brand',
countInStock=0,
)
serializer = ProductSerializer(product, many=False)
return Response(serializer.data)
Without separating category class in models.py everything works fine. I mean If i didn't use ForeignKey in Products class for category
It just has to be a Category Instance/Object
product = Product.objects.create(
user=user,
name_geo="Sample Name",
category=Category.objects.get_or_create(name="Sample Category"),
price=0,
brand='Sample Brand',
countInStock=0,
)
Notes:
You could just do a .get() or a .filter().first() if you don't want to create
If you use a form, you can get away with just the Category's PK/_id in the POST
this type of thing: f = form(request.POST) f.is_valid() f.save()
At the end that field will hold the PK/_id/Row# of the Category Obj

Django filterset and Django rest framework not working as expected

I have created a Django filter set to filter data, some fields are filtered with relationships.
When I never filter with the endpoint, it just returns all data instead of filtered data, what could be wrong here?
This is my endpoint filterer :
http://127.0.0.1:5000/api/v1/qb/questions/?paper=26149c3b-c3e3-416e-94c4-b7609b94182d&section=59bdfd06-02d4-4541-9478-bf495dafbee1&topic=df8c2152-389a-442f-a1ce-b56d04d39aa1&country=KE
Below is my sample :
from django_filters import rest_framework as filters
class QuestionFilter(filters.FilterSet):
topic = django_filters.UUIDFilter(label='topic',
field_name='topic__uuid',
lookup_expr='icontains')
sub_topic = django_filters.UUIDFilter(label='sub_topic',
field_name='topic__sub_topic__uuid',
lookup_expr='icontains')
paper = django_filters.UUIDFilter(label='paper',
field_name='paper__uuid',
lookup_expr='icontains')
section = django_filters.UUIDFilter(label='section',
field_name='section__uuid',
lookup_expr='icontains')
subject = django_filters.UUIDFilter(label='subject',
field_name="paper__subject__id",
lookup_expr='icontains'
)
year = django_filters.UUIDFilter(label='year',
field_name='paper__year__year',
lookup_expr="icontains")
country = django_filters.CharFilter(label='country',
field_name="paper__exam_body__country",
lookup_expr='icontains')
class Meta:
model = Question
fields = ['topic', 'section', 'paper', 'sub_topic', 'subject', 'year',
'country']
Then my view is like this :
class QuestionView(generics.ListCreateAPIView):
"""Question view."""
queryset = Question.objects.all()
serializer_class = serializers.QuestionSerializer
authentication_classes = (JWTAuthentication,)
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = QuestionFilter
Then the models attached to the filter are as below :
class Question(SoftDeletionModel, TimeStampedModel, models.Model):
"""Questions for a particular paper model."""
uuid = models.UUIDField(unique=True, max_length=500,
default=uuid.uuid4,
editable=False,
db_index=True, blank=False, null=False)
mentor = models.ForeignKey(User, related_name='question_mentor', null=True,
on_delete=models.SET_NULL)
paper = models.ForeignKey(Paper, max_length=25, null=True,
blank=True, on_delete=models.CASCADE)
question = models.TextField(
_('Question'), null=False, blank=False)
section = models.ForeignKey(QuestionSection,
related_name='section_question',
null=True, on_delete=models.SET_NULL)
topic = models.ForeignKey(Course, related_name='topic_question',
null=True, on_delete=models.SET_NULL)
question_number = models.IntegerField(_('Question Number'), default=0,
blank=False, null=False)
image_question = models.ImageField(_('Image question'),
upload_to='image_question',
null=True, max_length=900)
answer_locked = models.BooleanField(_('Is Answer locked'), default=True)
status = models.CharField(max_length=50, choices=QUESTION_STATUSES,
default=ESSAY)
address_views = models.ManyToManyField(CustomIPAddress,
related_name='question_views',
default=None, blank=True)
bookmarks = models.ManyToManyField(User, related_name='qb_bookmarks',
default=None, blank=True)
def __str__(self):
return f'{self.question}'
Paper Model
class Paper(SoftDeletionModel, TimeStampedModel, models.Model):
"""Paper model."""
uuid = models.UUIDField(unique=True, max_length=500,
default=uuid.uuid4,
editable=False,
db_index=True, blank=False, null=False)
subject = models.ForeignKey(Subject, related_name='subject',
null=True, on_delete=models.SET_NULL)
mentor = models.ForeignKey(User, related_name='paper_mentor', null=True,
on_delete=models.SET_NULL)
year = models.DateField(_('Year'), blank=False, null=False)
grade_level = models.ForeignKey(ClassGrade, related_name='grade_paper',
null=True, on_delete=models.SET_NULL)
exam_body = models.ForeignKey(ExamBody, related_name='exam_body_paper',
null=True, on_delete=models.SET_NULL)
number_of_questions = models.IntegerField(_('No of questions'),
blank=False, null=False)
number_of_sections = models.IntegerField(_('No of sections'),
blank=False, null=False)
color_code = ColorField(format='hexa', default='#33AFFF', null=True)
class Meta:
ordering = ['created']
def __str__(self):
return f'{self.subject.name} ({self.year})'
QuestionSection Model :
class QuestionSection(SoftDeletionModel, TimeStampedModel, models.Model):
"""Question paper sections e.g Section A, B, C etc."""
uuid = models.UUIDField(unique=True, max_length=500,
default=uuid.uuid4,
editable=False,
db_index=True, blank=False, null=False)
section = models.CharField(
_('Question Section'), max_length=100, null=False, blank=False)
def __str__(self):
return f'{self.section}'
class Course(SoftDeletionModel, TimeStampedModel, models.Model):
"""
Topic model responsible for all topics.
"""
uuid = models.UUIDField(unique=True, max_length=500,
default=uuid.uuid4,
editable=False,
db_index=True, blank=False, null=False)
title = models.CharField(
_('Title'), max_length=100, null=False, blank=False)
overview = models.CharField(
_('Overview'), max_length=100, null=True, blank=True)
description = models.CharField(
_('Description'), max_length=200, null=False, blank=False
)
country = CountryField()
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
topic_cover = models.ImageField(
_('Topic Cover'), upload_to='courses_images',
null=True, blank=True, max_length=900)
grade_level = models.ForeignKey(
ClassGrade, max_length=25, null=True,
blank=True, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
ranking = models.IntegerField(
_('Ranking of a Topic'), default=0, help_text=_('Ranking of a Topic')
)
def __str__(self):
return self.title
class Meta:
verbose_name_plural = "Topics"
ordering = ['ranking']

How to access other model fields through foreign key in Django Views

I want to query from OrderItem Model like
total_orders = OrderItem.objects.filter(product.user == request.user.id).count()
but i am getting error
**
NameError at /home
name 'product' is not defined
**
MY MODELS:
Product Model:
class Product(models.Model):
title = models.CharField(max_length=150)
user = models.ForeignKey(
User, blank=True, null=True, on_delete=models.SET_DEFAULT, default=None)
description = models.TextField()
price = models.FloatField()
quantity = models.IntegerField(default=False, null=True, blank=False)
minorder = models.CharField(
max_length=150, help_text='Minum Products that want to sell on per order', null=True, default=None, blank=True)
image = models.ImageField()
category = models.ForeignKey(
Categories, default=1, on_delete=models.CASCADE)
slug = models.SlugField(blank=True, unique=True)
def __str__(self):
return self.title
Order Item Model
class OrderItem(models.Model):
product = models.ForeignKey(
Product, on_delete=models.SET_NULL, blank=True, null=True)
order = models.ForeignKey(
Order, on_delete=models.SET_NULL, blank=True, null=True)
quantity = models.FloatField(default=0, null=True, blank=True)
date_orderd = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(
User, on_delete=models.SET_NULL, blank=True, null=True)
price = models.FloatField(blank=True, null=True)
def __str__(self):
return str(self.product)
My View:
def home(request):
total_orders = OrderItem.objects.filter(
product.user == request.user.id).count()
return render(request, "sellerprofile/home.html", {'total_orders': total_orders})
Do:
total_orders = OrderItem.objects.filter(product__user=request.user).count()
You can look at the documentation here about field lookups on more detail.

Django: get the max count of a foreign key based on other foreign key

I have this Model:
class Complaint(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
name = models.CharField(max_length=255, unique=True)
definition = models.TextField(blank=False, default="")
is_violent = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
class Meta:
ordering = ['name']
def get_absolute_url(self):
return reverse('complaint-details', kwargs={'pk': self.pk})
class Service(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
name = models.CharField(max_length=255, unique=True)
definition = models.TextField(blank=True, default="")
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('service-details', kwargs={'pk': self.pk})
class Location(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
location_name = models.CharField(max_length=255, unique=True)
loc_lat = models.DecimalField(max_digits=9, decimal_places=6)
loc_long = models.DecimalField(max_digits=9, decimal_places=6)
pop = models.PositiveIntegerField(default=500)
is_AOR = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.location_name
class Blotter(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)#default=timezone.now().date()
date = models.DateField(blank=True)
time = models.TimeField(blank=True)
entry_number = models.CharField(max_length=255, unique=True,validators=[RegexValidator(r'^\d{1,255}$')])
complaints = models.ForeignKey(Complaint, on_delete=models.CASCADE, null=True, blank=True)
service = models.ForeignKey(Service, on_delete=models.CASCADE, null=True, blank=True)
information = models.TextField(blank=False, default="")
location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True, blank=True)
is_active = models.BooleanField(default=True)
class Meta:
ordering = ("date_created",)
def __str__(self):
return (self.entry_number)
def get_absolute_url(self):
return reverse('details-blotter', kwargs={'pk': self.pk})
And I have this serializer:
class APILocationListSerializer(serializers.Serializer):
address = serializers.CharField()
latitude = serializers.DecimalField(max_digits=9, decimal_places=5)
longitude = serializers.DecimalField(max_digits=9, decimal_places=5)
population= serializers.IntegerField()
crime_count=serializers.IntegerField()
crime_rate=serializers.DecimalField(max_digits=4, decimal_places=3)
is_aor = serializers.BooleanField()
class Meta:
model = Blotter
fields= [
'address',
'latitude',
'longitude',
'population',
'crime_count',
'crime_rate'
'is_aor',
]
def to_representation(self, value):
context = {
value['address']:
{
'coordinates':[value['latitude'],value['longitude']],
'Population': value['population'],
'Crime-Count': value['crime_count'],
'Crime-Rate': value['crime_rate'],
'Area-Of-Responsibility': value['is_aor'],
}
}
return context
And ListApiView:
class APILocationList(generics.ListAPIView):
serializer_class = APILocationListSerializer
def get_queryset(self):
q=Blotter.objects.values('location__location_name').annotate(
address=F('location__location_name'),
latitude=F('location__loc_lat'),
longitude=F('location__loc_long'),
population=F('location__pop'),
crime_count=Count('complaints', filter=Q(complaints__is_active=True) and Q(complaints__isnull=False)),
crime_rate=(Cast(F('crime_count'), FloatField())/Cast(F('population'), FloatField()))*100000,
is_aor=F('location__is_AOR')
)
q1 = q.filter(location__is_AOR=True).order_by('address')
query_search = self.request.GET.get("q")
if query_search:
q1 = q.filter(Q(location__is_AOR=True) and Q(location__location_name__icontains=query_search)).order_by('address')
return q1
I'm new to django and DRF. I want to achieve a result like this in my API Not Achieved
but this is the result that i've achieved so far Achieved
As you can see in the picture, I want to count the crime trend (highest count of a crime and the crime itself) in every location.
My questions are:
Is this even achievable/possible to get these results using just one query?
If yes, how?
If no, is there any other way to achieve these kind of results?
Thank you in advance!

Categories