If the models are as follows,
class Subject(BaseModel):
name = models.CharField(db_column='name', max_length=200, blank=False, null=False, unique=True)
class Meta:
managed = True
db_table = 'Subject'
class Topic(BaseModel):
name = models.CharField(db_column='name', max_length=200, blank=False, null=False, unique=True)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, null=False, related_name='subject_topic')
class Meta:
managed = True
db_table = 'Topic'
class Question(BaseModel):
topic = models.ForeignKey(Topic, on_delete=models.CASCADE, null=False, related_name='question_topic')
class Meta:
managed = True
db_table = 'Question'
How can I make a query Question for a subject.
questions = Question.objects.filter(topic_in=Topic.objects.get(subject=subject).only('id').all())
but it's not working. Any help would be really great help.
Your current "inner queryset" won't give you multiple values, it only returns 1.
Topic.objects.get(subject=subject).only('id').all()
You are using .objects.get() which returns a model instance, so for example .only() or .all() on that won't work unless your model has such a defined function.
Furthermore you don't really need 2 querysets, you can get your result with only one:
my_subject_ids = [...] # these are the ids of Subject models you want
Question.objects.filter(topic__subject_id__in=my_subject_ids)
You can also query for Subject.name, just use the following for this: topic__subject__name__in=my_list.
If you want to query for a specific Subject-instance you can use topic__subject=my_obj.
You also might wanna take a look at the docs for more information on that.
Related
I have a model for applications, which among many attributes have a category. This category is in fact a key to another model that has the category ID, its name, and so on.
class Application(models.Model):
title = models.CharField(max_length=50)
vendor = models.CharField(max_length=50, default="Unknown", null=False)
.
.
.
category = models.ForeignKey('ApplicationCategory', related_name='applications', null=False, default=1, on_delete=models.SET_DEFAULT)
class ApplicationCategory(models.Model):
name = models.CharField(max_length=20, null=False)
description = models.CharField(max_length=200, null=False)
Then, on the Django REST serializers side I have the serializer for the applications:
class SoftwareSerializer(serializers.ModelSerializer):
category = serializers.PrimaryKeyRelatedField(queryset=ApplicationCategory.objects.all())
class Meta:
model = Application
fields = ['id', 'title', ... 'category']
Which is generating the expected API view, with a dropdown for the categories, but showing them as the ApplicationCategory objects and not giving me their name.
API showing Category dropdown with objects instead of names
Is there a way to access attributes of those objects to show the name in the dropdown, for usability sake?
I have also tried creating a CategorySerializer object (class CategorySerializer(serializers.ModelSerializer)) and then using it as category = CategorySerializer(many=False) but instead of dropdowns, I get open text fields for the attributes of the category.
Am I trying to do something that is not expected to work?
try to define the desired text in str method for your ApplicationCategory class:
class ApplicationCategory(models.Model):
name = models.CharField(max_length=20, null=False)
description = models.CharField(max_length=200, null=False)
#example
def __str__(self):
return '%s: %s' % (self.name , self.description)
I am facing a strange situation, Following is my code for models.
class Sector(models.Model):
sector_name = models.CharField(max_length=255, null=False)
sector_desc = models.CharField(max_length=1024, null=False)
def __set__(self):
return "{} - {}".format(self.sector_name, self.sector_desc)
class TrailCompany(models.Model):
sector = models.ForeignKey(Sector, on_delete=models.CASCADE, related_name="sector_id")
comp_name = models.CharField(max_length=255, null=False)
comp_desc = models.CharField(max_length=1024, null=False)
def __set__(self):
return "{} - {}".format(self.sector, self.comp_name, self.comp_desc)
class Trail(models.Model):
company = models.ForeignKey(TrailCompany, on_delete=models.CASCADE, related_name="company_id")
trail_id = models.CharField(max_length=255, null=False)
tri = models.CharField(max_length=255, null=False)
exp_pdufa = models.CharField(max_length=255, null=False)
def __set__(self):
return "{} - {}".format(self.company, self.exp_pdufa, self.trail_id, self.tri, self.exp_pdufa)
Following is my code for the serializer,
class SectorSerializer(serializers.ModelSerializer):
class Meta:
model = Sector
fields = '__all__'
class TrailCompanySerializer(serializers.ModelSerializer):
sectors = SectorSerializer(source="sector_id", many=True)
class Meta:
model = TrailCompany
fields = '__all__'
class TrailSerializer(serializers.ModelSerializer):
companies = TrailCompanySerializer(source="company_id", many=True)
class Meta:
model = Trail
fields = '__all__'
When I try to serilize object I am getting the stated error,
trail_query = Trail.objects.all()
trails = TrailSerializer(trail_query, many=True)
return Response({"success": True, 'trails': trails.data})
Please help me to figure out and resolve the problem. Thanks.
Looks like your error is in the following line:
companies = TrailCompanySerializer(source="company_id", many=True)
Trail<>TrailCompany is a one to one relationship from the perspective of Trail. E.g. the Trail only knows of one TrailCompany it is related to. Therefore you do not need the many=True attribute.
I also think the source should be company rather than company_id. company_id is a primary key, whereas company is the related object
Selected answer doesn't work for me. However following way worked:
company = TrailCompanySerializer(many=True)
Also remember to put company in related_name field like this:
company = models.ForeignKey(TrailCompany, on_delete=models.CASCADE, related_name="company")
I have the following models:
class Color(models.Model):
name = models.CharField(max_length=50, null=False, blank=False)
def __str__(self):
return self.name
class Flower(models.Model):
flower_number = models.PositiveSmallIntegerField(
default=1,blank=True, null=True)
petal_color = models.ManyToManyField(Color,blank=True, related_name="%(app_label)s_%(class)s_petal",
related_query_name="%(app_label)s_%(class)s")
petal_outer_color = models.ManyToManyField(Color,blank=True, related_name="%(app_label)s_%(class)s_petal_outer",
related_query_name="%(app_label)s_%(class)s")
class Meta:
abstract = True
class Plant(Flower):
name = models.CharField(max_length=50, null=False, blank=False, unique=True)
On the Admin I just have:
admin.site.register(Plant)
When I go into the Django admin and fill out either of the manytomany petal_color or petal_outer_color with data the other manytomany field automatically gets filled when it saves. How do I stop this from happening? Nothing shows up as an error and I tried going back and deleting and re-entering data but it still happens
Try using symmetrical=False in the ManyToManyField, that might be causing the issue here as you have two M2M fields going to the same model.
Read up on symmetrical in the Django docs.
Do something like this
class Flower(models.Model):
flower_number = models.PositiveSmallIntegerField(
default=1,blank=True, null=True)
petal_color = models.ManyToManyField(Color,blank=True, symmetrical=False related_name="%(app_label)s_%(class)s_petal",
related_query_name="%(app_label)s_%(class)s")
petal_outer_color = models.ManyToManyField(Color,blank=True, symmetrical=False, related_name="%(app_label)s_%(class)s_petal_outer",
related_query_name="%(app_label)s_%(class)s")
class Meta:
abstract = True
By default, the value of symmetrical is True for Many to Many Field which is a bi-directional relationship.
The ManyToManyField is assumed to be symmetrical – that is, if I am your friend, then you are my friend.
I have three models
class Venue(models.Model):
property_values = models.ManyToManyField('feature.PropertyValue')
class Feature(models.Model):
name = models.CharField(max_length=255, null=False, blank=False)
class PropertyValue(models.Model):
name = models.CharField(max_length=255, null=False, blank=False)
feature = models.ForeignKey('Feature', null=False, blank=False)
In this I want to be able to configure 'feature' in venue model saying that belongs to it via property value.
Like
class Venue(models.Model):
property_values = models.ManyToManyField('feature.PropertyValue')
feature = models.ManyToManyField(via property_value something)
You already have access to feature through property_values
one = Venue.objects.first()
one.property_vaues.all()[0].feature
You can use add methods of Django objects:
https://docs.djangoproject.com/en/1.11/topics/db/examples/many_to_many/
venue = Venue.objects.get(id=1) # example
feature = Feature.objects.get(id=1) # example
venue.property_values.add(feature)
You can remove using remove function also
i've migrated an existing database that i would like to work with django. i have the following models:
class Device(models.Model):
class Meta:
db_table = u'DEVICES'
managed=False
id = models.CharField(primary_key=True, max_length=22, db_column='DEVICE_ID')
name = models.CharField(max_length=40, db_column='DEVICE_NAME')
status = models.CharField(max_length=10, db_column='STATUS')
class DevicePort(models.Model):
class Meta:
db_table = u'DEVICE_PORT'
managed=False
id = models.CharField( primary_key=True, max_length=22, db_column='DEVICE_PORT_ID')
device = models.OneToOneField(Device, db_column='DEVICE_ID')
type = models.CharField( max_length=22, db_column='PORT_TYPE_ID')
port_num = models.CharField( max_length=30, db_column='DEVICE_PORT_NUM')
class IP(models.Model):
class Meta:
db_table = u'IP_NODE'
managed=False
ip_address = models.CharField(primary_key=True, max_length=15, db_column='IP_NODE_NO')
hostname = models.CharField(max_length=40, db_column='IP_HOST')
port = models.OneToOneField(DevicePort, db_column='DEVICE_PORT_ID')
status = models.CharField(max_length=50, db_column='IP_NODE_STATUS')
i want a list of Devices and their relational IP.ip_address and IP.hostnames. In SQL, i would do something like:
SELECT UNIQUE
d.device_name device
FROM
IP_NODE c,
DEVICES d,
DEVICE_PORT e
WHERE
c.ip_node_no = b.ip_node_no
AND c.device_port_id = e.device_port_id
AND e.device_id = d.device_id
AND d.device_name LIKE 'something';
How do i do this with my django models?
So instead of an inner join you want...and implicit join? Is there something I'm missing here because an implicit join is slower than an explicit one most all cases.
[http://postgresql.1045698.n5.nabble.com/explicit-JOIN-faster-than-implicit-td1920335.html][1]
I can't see any reason you would want to do this, but as stated above you can certainty get this by writing your own queries with raw, or even connection.cursor. Maybe even could pull it off with extra(tables=[...]), though I'm not positive as I've never used tables like this.