Linear sum of foreign key count django - python

I have a profile class in my model like follow:
class UserProfile(models.Model):
first_name = ....
....
I two other classes that has foreign key to profile model:
class A(models.Model):
profile = models.ForeignKey(UserProfile)
....
class B(models.Model):
profile = models.ForeignKey(UserProfile)
Now I want to filter active users. I want something like follows. But I don't know how to do it in django!
UserProfile.objects.filter((2*count(A) + count(B))__gte=10).all()

You need to use annotate on the queryset first to run the calculation, then you can filter by it.
from django.db.models import Count
UserProfile.objects.annotate(
score=2*Count('a') + Count('b')
).filter(score__gte=10)

Related

Factory_boy not creating RelatedFactory in Trait

I've got a Purchase model and a PurchaseInfo model. PurchaseInfo has a foreign key to Purchase. I'm trying to modify an existing Factory for Purchase that will create PurchaseInfo at the same time using RelatedFactory since it's a reverse foreign key relationship. The only thing is that I wanted to use a Taint so that I could control the value of fields within PurchaseInfo. Normally when I create a Purchase like p = PurchaseFactory() the PurchaseInfo is created with null fields inside of it. If I create a Purchase like p = PurchaseFactory(info=True), so I can get the field modifications via the Taint, the PurchaseInfo is not created at all.
I have a feeling that putting the RelatedFactory in a Taint is not the way to go. What is the correct way to do this?
Models:
class Purchase(Model):
...
class PurchaseInfo(Model):
purchase = models.ForeignKey(Purchase, on_delete=models.CASCADE, unique=True, db_index=True)
lock = DateTimeField(null=True)
lock_by = ForeignKey(...
class PurchaseInfoFactory(DjangoModelFactory):
class Meta:
model = PurchaseInfoField
lock = None
lock_by = None
class PurchaseFactory(DjangoModelFactory):
class Meta:
model = Purchase
info = RelatedFactory(PurchaseInfoFactory,
factory_related_name='purchase')
class Params:
info = Trait(internalfield=RelatedFactory(PurchaseInfoFactory,
factory_related_name='purchase',
lock=timezone.now() - relativedelta(months=1),
lock_by=SubFactory(UserFactory, user_id=1)))
I don't like my solution, but here's what I did. I derived a secondary factory with an alternate RelatedFactory. That works.
class PurchaseFactory(DjangoModelFactory):
class Meta:
model = Purchase
info = RelatedFactory(PurchaseInfoFactory,
factory_related_name='purchase')
class InfoPurchaseFactory(DjangoModelFactory):
class Meta:
model = Purchase
info = Trait(internalfield=RelatedFactory(PurchaseInfoFactory,
factory_related_name='purchase',
lock=timezone.now() - relativedelta(months=1),
lock_by=SubFactory(UserFactory, user_id=1)))

Django model unique together both ways

Many questions already on this topic, but not what i'm searching for.
I have this Model:
class Options(TimeStampedModel)
option_1 = models.CharField(max_length=64)
option_2 = models.CharField(max_length=64)
class Meta:
unique_together = ('option_1', 'option_2')
Now I have a unique constraint on the fields.
Is there a way to also define this the other way around so that it doesn't matter what was option_1 and what was option_2
As example:
Options.create('spam', 'eggs') # Allowed
Options.create('spam', 'eggs') # Not allowed
Options.create('eggs', 'spam') # Is allowed but should not be
Thanks in advance!
I think a ManyToMany relation with a custom through table and an unique_together constraint on that table should do what you want.
Example code:
from django.db.models import Model, ForeignKey, ManyToManyField, CharField
class Option(Model):
name = CharField()
class Thing(TimeStampedModel):
options = ManyToManyField("Option", through="ThingOption")
class ThingOption(Model):
thing = ForeignKey(Thing)
option = ForeignKey(Option)
value = CharField()
class Meta:
unique_together = ('thing', 'option')
For Django 2.2+ it is recommended to use UniqueConstraint. In the docs there is a note stating unique_together may be deprecated in the future. See this post for its usage.
You can override create method, do something like
from django.db import models
class MyModelManager(models.Manager):
def create(self, *obj_data):
# Do some extra stuff here on the submitted data before saving...
# Ex- If obj_data[0]=="eggs" and obj_data[1]=="spam" is True don't allow it for your blah reason
# Call the super method which does the actual creation
return super().create(*obj_data) # Python 3 syntax!!
class MyModel(models.model):
option_1 = models.CharField(max_length=64)
option_2 = models.CharField(max_length=64)
objects = MyModelManager()

How to add multiple foreign key in Django

I am beginner in Django.
I am having two models
class Employee(models.Model):
full_name = models.CharField(max_length=120,default=None)
designation = models.CharField(max_length=80,default=None)
class Leave(models.Model):
employee = models.ForeignKey(Employee, related_name='employee')
number_of_days = models.IntegerField(default=0)
Now I have inline Leave Model with Employee in admin.py
so that I can add as many leaves I want in employees
But when I retrieve this model in views new Leaves are created, all I want is one employee should show total = number of days, but it creates new leaves, not able to build any logic here I am stuck, please ask if u don't understand what I am asking.
Not exactly sure what you are asking, but my guess is you want to display the total number of absent days of an employee in the admin. You can use aggregation and Sum in particular and a custom method on your model:
# models
from django.db.models import Sum
class Employee(models.Model):
def absent_days(self):
return self.leaves.aggregate(s=Sum('number_of_days'))['s'] or 0
absent_days.short_description = 'Absent days' # used as column header/field label
class Leave(models.Model):
# note the changed related name!
employee = models.ForeignKey(Employee, related_name='leaves')
# admin
class EmployeeAdmin(admin.ModelAdmin):
readonly_fields = [..., 'absent_days', ...]
fields = [..., 'absent_days', ...]
list_display = [..., 'absent_days', ...]

How to add conditional fields to ModelAdmin in Django?

I have model classes:
class Product(models.Model):
category = models.ForeignKey(Category)
name = models.CharField(max_length=90)
...
class Category(models.Model):
name = models.CharField(max_length=90)
description = models.CharField(max_length=2000)
properies = models.ManyToManyField(Property)
...
#property type, ex: 'weight', 'length'
class Property(models.Model):
...
#value for every product
class PropertyValue(models.Model):
product = models.ForeignKey(Product)
property = models.ForeignKey(Property)
...
and I need custom product/add/ page, having PropertyValue forms set depends on chosen category.
I've made a method getting PropertyValue list by category_id in ModelAdmin class, but how can I call it in runtime when chosen category changes? Is it possible in django?
What do you mean when you said in runtime. If those categories change, the new records will apear every time you load the add pages.
Did you do yor form class? Kind of:
class PropertyValueForm(forms.Form):
product = forms.ModelChoiceField(queryset=Product.objects.all())
property = forms.ModelChoiceField(queryset=Property.objects.all())
Or:
def getProduct():
# DO YOUR STUFF
return product_list
class PropertyValueForm(forms.Form):
product = forms.ChoiceField(choices=get_my_choices())

Searching by related fields in django admin

I've been looking at the docs for search_fields in django admin in the attempt to allow searching of related fields.
So, here are some of my models.
# models.py
class Team(models.Model):
name = models.CharField(max_length=255)
class AgeGroup(models.Model):
group = models.CharField(max_length=255)
class Runner(models.Model):
"""
Model for the runner holding a course record.
"""
name = models.CharField(max_length=100)
agegroup = models.ForeignKey(AgeGroup)
team = models.ForeignKey(Team, blank=True, null=True)
class Result(models.Model):
"""
Model for the results of records.
"""
runner = models.ForeignKey(Runner)
year = models.IntegerField(_("Year"))
time = models.CharField(_("Time"), max_length=8)
class YearRecord(models.Model):
"""
Model for storing the course records of a year.
"""
result = models.ForeignKey(Result)
year = models.IntegerField()
What I'd like is for the YearRecord admin to be able to search for the team which a runner belongs to. However as soon as I attempt to add the Runner FK relationship to the search fields I get an error on searches; TypeError: Related Field got invalid lookup: icontains
So, here is the admin setup where I'd like to be able to search through the relationships. I'm sure this matches the docs, but am I misunderstanding something here? Can this be resolved & the result__runner be extended to the team field of the Runner model?
# admin.py
class YearRecordAdmin(admin.ModelAdmin):
model = YearRecord
list_display = ('result', 'get_agegroup', 'get_team', 'year')
search_fields = ['result__runner', 'year']
def get_team(self, obj):
return obj.result.runner.team
get_team.short_description = _("Team")
def get_agegroup(self, obj):
return obj.result.runner.agegroup
get_agegroup.short_description = _("Age group")
The documentation reads:
These fields should be some kind of text field, such as CharField or TextField.
so you should use 'result__runner__team__name'.

Categories