How to group ManyToMany in template - django

Here is my model:
class Teacher(models.Model):
name = models.CharField(max_length=50)
subjects = models.ManyToManyField(Subject)
class Subject(models.Model):
name = models.CharField(max_length=50)
type = models.ForeignKey(SubjectType)
class SubjectType(models.Model):
name = models.CharField(max_length=50)
I want to do something like that in template:
{regroup subjects by subject.type}
{foreach subject_type}
#display all teachers for subject_type
Each subject has its teacher_set.
How can i union all teachers for a particular subject_type?

I think you can't get this functionality from the template. However, you could do it in your view:
subject_type = # Some SubjectType object
my_teachers = []
for subject in subject_type.subject_set:
my_teachers += subject.teacher_set
# What we do with the duplicates?
my_teachers = list(set(my_teachers))
Now, you have a list of unique teachers in my_teachers for a particular SubjectType.
EDIT: You could do this for every SubjectType object and pass the resulting list (of lists) to the template.

Related

Django query complex query in one to one field model

I have two models of Student and Parent
Student models.py:
class StudentInfo(models.Model):
admissionNumber = models.BigIntegerField(primary_key=True,default=0)
firstName = models.CharField(max_length=20)
lastName = models.CharField(max_length=20)
fullName = models.CharField(max_length=50)
gender = models.CharField(max_length=20)
dob = models.DateField(null=True)
classSection = models.CharField(max_length=20)
Parent models.py
class ParentInfo(models.Model):
student = models.OneToOneField(StudentInfo,primary_key=True, on_delete=models.CASCADE)
fatherName = models.CharField(max_length=20)
motherName = models.CharField(max_length=20)
I have a form to search students through their fatherName.
So, what I want is to filter those students whose father's name contains 'some name'.
I tried this but it resultes in query set of ParentInfo:
parentInfo = ParentInfo.objects.all()
studentsInfo = parentInfo.filter(parent__fName = fName).select_related('student')
You should filter the opposite way, like:
StudentInfo.objects.filter(parentinfo__fatherName='name of father')
You here thus obtain a QuerySet of StudentInfos which contains zero, one, or more StudentInfos where there is a related ParentInfo object where the fatherName field is, in this case 'Name of father'.
Note: It might be better to implement a ForeignKey in the opposite order, such that multiple students can refer to the same ParentInfo object. Right now, a ParentInfo object can refer to exactly one StudentInfo. If there are students with the same parents (so siblings), then you introduce data duplication in the database.
# You can use contains attribute on the field of model and your query can be like this
student = models.ParentInfo.objects.values('student__firstName', 'student__lastName').filter(fatherName__contains='your value')
print(student[0]['student__firstName'])
print(student[0]['student__lastName'])

I am trying to create a graphql mutation , where i cannot add the categoryNode as a input feild to AddEquipment mutation

category model
this my category model
class Category(models.Model):
_id = models.ObjectIdField(primary_key=True)
name = models.CharField(max_length=100)
Category node
I've created a category node using relay
class CategoryNode(DjangoObjectType):
class Meta:
model = Category
filter_fields = ['name', 'equipments']
interfaces = (relay.Node,)
add equipmemt mutation
while mutation i need to add a category object to equipment object in mutation inputs
class AddEquipment(relay.ClientIDMutation):
class Input:
name = graphene.String(required=True)
category = graphene.Field(CategoryNode)
equipment = graphene.Field(EquipmentNode)
#classmethod
def mutate_and_get_payload(cls, root, info, **inputs):
equipment_instance = Equipment(
name=inputs.get('name'),
category=inputs.get('category')
)
equipment_instance.save()
return AddEquipment(equipment=equipment_instance)
by this code iam getting error like this
"AssertionError: AddEquipmentInput.category field type must be Input Type but got: CategoryNode."
Unfortunately you can't do that as an ObjectType cannot be an InputObjectType. The only way for you to make it work is to create a new class which derived from the InputObjectType.
class CategoryInput(graphene.InputObjectType):
id = graphene.ID(required=True)
name = graphene.String()
and use it.
class AddEquipment(relay.ClientIDMutation):
class Input:
name = graphene.String(required=True)
category = graphene.Field(CategoryInput, required=True)
...
UPDATE
I think in your case, If you only want to get the category instance there would be no point to input a whole detail of category in your mutation so I suggest to only input the name and the category id in your inner class Input and get query a category instance see example inside your mutate_and_get_payload.
So to be precise you should refactor your code into:
class AddEquipment(relay.ClientIDMutation):
class Input:
name = graphene.String(required=True)
category_id = graphene.ID(required=True)
equipment = graphene.Field(EquipmentNode)
#classmethod
def mutate_and_get_payload(cls, root, info, **inputs):
# if ID is global make sure to extract the int type id.
# but in this case we assume that you pass an int.
category_instance = Category.objects.get(id=inputs.get('category_id'))
equipment_instance = Equipment(
name=inputs.get('name'),
category=category_instance
)
equipment_instance.save()
return AddEquipment(equipment=equipment_instance)

Django: way of getting objects?

I have following structure of models
For the model of 'Campaigns' I'm going to write down functions that would be called in a template: ads_count
My solution was:
class Campaigns(AlphaModel):
Project = models.ForeignKey('Projects', on_delete=models.CASCADE, related_name='projects')
......
def ads_count(self):
c = 0
gr = AdGroups.objects.filter(Campaign=self).all()
for g in gr:
c += g.ads_count()
return c
......
class AdGroups(AlphaModel):
Campaign = models.ForeignKey('Campaigns', on_delete=models.CASCADE, related_name='campaigns')
server_id = models.PositiveIntegerField()
......
def ads_count(self):
return Ads.objects.filter(AdGroup=self).count()
......
class Ads(AlphaModel):
AdGroup = models.ForeignKey('AdGroups', on_delete=models.CASCADE, related_name='adgroups_a')
server_id = models.PositiveIntegerField()
......
However this was throws an error "Cannot resolve keyword into field"
Is there any simple and direct way of counting objects of 'ads' that belongs to particular object of 'campaigns' ?
Thanks in advance!
First of all, it is general convention to use CamelCase only for class definitions, and lower case in all your field names. This makes it much easier to follow the code and distinguish between classes and objects. I would rewrite your models as follows:
class Campaigns(AlphaModel):
project = models.ForeignKey('Projects', on_delete=models.CASCADE, related_name='projects')
class AdGroups(AlphaModel):
campaign = models.ForeignKey('Campaigns', on_delete=models.CASCADE, related_name='campaigns')
server_id = models.PositiveIntegerField()
class Ads(AlphaModel):
ad_group = models.ForeignKey('AdGroups', on_delete=models.CASCADE, related_name='adgroups_a')
server_id = models.PositiveIntegerField()
Now, to get the count of Ads associated with a Campaign, you can do this query:
class Campaigns(AlphaModel):
...
def ads_count(self):
return Ads.objects.filter(ad_group__campaign=self).count(distinct=True)
(using your existing field names this would be):
Ads.objects.filter(AdGroup__Campaign=self).count(distinct=True)

How to get specific key for manytomany and foreignkey

I have three models:
class Section(models.Model):
name = models.CharField()
class ParamText(models.Model):
text = models.TextField()
class Param(models.Model):
name = models.CharField()
value = models.IntegerField()
texts = models.ManyToManyField(ParamText)
section = models.ForeignField(Section)
This is simple example. Now I want to create class with concrete datas:
class ObjectTemplate(models.Model):
params = models.ManyToManyField(Param)
but I want put this model concrete ParamText in specyfic Param. My ObjectTemplate should contain many params[Param] (unique would be great) with only one selected ParamText for each Param.
How to realize this?
first of all to create a unique parmas[parm] use the OneToOneField instead of manytomany .
and to access a specific key : every object has an id so you can use that
let p be an Param's object
so to get the section id from the param you have to use
p.section.id
this would return a long int containing the id (primarykey) of the object.
I think the following will solve your one parmatext for each parma problem
class Section(models.Model):
name = models.CharField()
class ParamText(models.Model):
text = models.TextField()
class Param(models.Model):
name = models.CharField()
value = models.IntegerField()
texts = models.OneToOneField(ParamText)
section = models.ForeignField(Section)

Model (Product) attributes used in product, alert, predefined search.. is it right with DRY concept?

First of all I would like to mention that I am not an experienced programmer.
Say there's a model Product, and there are some types of products with different attributes (well, 2 types for example).
I have one BaseProduct model with User, creation_date, creation_ip and some more attributes and subclassed child models with specified for this type of product attributes.
Class BaseProduct(models.Model):
name = models.CharField()
type = models.CharField()
creation_date = models.DateField()
creation_ip = models.IpAddressfield()
class ProductTypeX(BaseProduct):
attribute_1 = models.ForeignKey(some_other_model)
attribute_2 = models.ForeignKey(some_other_model2)
class ProductTypeY(BaseProduct):
attribute_1 = models.ForeignKey(some_other_model)
attribute_2 = models.ForeignKey(some_other_model2)
There's an option creating email alert on creation of new product based on some criteria, and there's also a "quick predefined search" based on some criteria too. For these I've created (again...) models.
class BaseAlert(models.Model):
name = models.CharField()
email = models.BooleanField()
sms = models.BooleanField()
ProductTypeXAlert(BaseAlert):
attribute_1 = models.ForeignKey(some_other_model)
attribute_2 = models.ForeignKey(some_other_model2)
ProductTypeYAlert(BaseAlert):
attribute_1 = models.ForeignKey(some_other_model1)
attribute_2 = models.ForeignKey(some_other_model2)
class BasePredefinedSearch(models.Model):
name = models.CharField()
ProductTypeXPredefinedSearch(BasePredefinedSearch):
attribute_1 = models.ForeignKey(some_other_model1)
Is this the right solution or should I create some universal Attribute model for alert, predefinedsearch ??.. I am repeating attributes fields here many times. What is your opinion on that ?
Thanks
I would make an AttributesBase abstract model and use multiple inheritance:
class AttributesBase(models.Model):
class Meta:
abstract = True
attribute1 = models.ForeignKey(SomeOtherModel1)
attribute2 = models.ForeignKey(SomeOtherModel2)
class ProductTypeX(BaseProduct, AttributesBase):
"""Defines product type X"""
Hope that helps you out.