I am stuck on how to fetch the data child model which has a foreignkey of parent model.
this is how my model looks like
class Projects(models.Model):
project_name = models.CharField(max_length=100,null=False)
class ProjectTask(models.Model):
project_id = models.ForeignKey(Projects,on_delete=models.CASCADE,null=False)
class TaskBlockers(models.Model):
task_id = models.ForeignKey(ProjectTask,on_delete=models.CASCADE,null=False,related_name='task_id_related')
blocker = models.CharField(max_length=100,null=False)
now what I want is to get all the blockers under a projectTask which has a projectid = something.
ProjectTask.objects.filter(project_id=1) this will give a queryset right? and for each element in a queryset i want the blocker from TaskBlockers table.
How can I achieve this?
data = TaskBlockers.objects.filter(task_id__project_id_id=1).values("blocker")
Related
I have Django models that looks like this
class Customer(models.Model):
name = models.CharField(_("Name"))
class Feature(models.Model):
label = models.CharField(_("Name"))
class AddOn(models.Model):
customer = models.ForeignKey(Customer)
feature = models.ForeignKey(Feature)
Given that I have an instance of Customer e.g
customer = Customer.objects.get(pk=1)
How do I get all the labels in feature in one query to avoid N+1 query?
For now what I've done is:
[addon.feature.label for addon in self.addon_set.all()]
But I think for each addon.feature will create a query that is not very optimized if there is a lot of addon
You can use values/values_list to get all labels in a single query
self.addon_set.values_list('feature__label', flat=True)
EDIT: Example of the ManyToManyField
class Customer(models.Model):
name = models.CharField(_("Name"))
features = ManyToManyField('Feature', through='AddOn')
class Feature(models.Model):
label = models.CharField(_("Name"))
class AddOn(models.Model):
customer = models.ForeignKey(Customer)
feature = models.ForeignKey(Feature)
You can then perform queries like customer_obj.features.all() or feature_obj.customers.all() and it won't affect your ability to still query the AddOn model
class Blog():
likes = models.ManyToManyField(User, through="myapp.Like")
class Like():
user = models.ForeignKey(Like)
blog = models.ForeignKey(Blog)
liked_at = models.DateTimeField(auto_now_add=True)
some_bool_field = models.BooleanField(default=False)
Now in views:
def like_blog(request, id):
blog = Blog.objects.get(id=id)
blog.users.add(request.user)
# now how can I update some_bool_field and How can I make use of this field
In future I can use some query like blog.users.filter(some_bool_field=False) so for that case I want to update this field.
OR AM I MISSING THE USES OF THROUGH MODEL ?
If you want to update the through model objects you can do like so:
def like_blog(request, id):
blog = Blog.objects.get(id=id)
blog.users.add(request.user)
# query your through model
Like.objects.filter(user=request.user, blog=blog).update(some_bool_field=True)
Getting all blogs filtered likes with some_bool_field=True:
true_boolean_likes = Blog.objects.filter(likes__some_bool_field=True)
for through model update you can use bellow method to update
like = Blog.objects.get(id=id)
for like in Likes.objects.filter(likes__some_bool_field =False): #or true by what you want to filter
like.the_field_want_to_update.update(id=like.id)
here .update update the value by which you are filtering here with id so it will update what data passed to it.
I wanna change all fields of a json object except 'pk' in DRF. I just need to keep one json data. When adding a new data ,this one should override existing data. Is there a way to do it with django ?
my models.py
class ClientUser2(models.Model):
phone_number = models.CharField(max_length=20,unique=True)
name = models.CharField(max_length=100,blank=True)
status = models.IntegerField(default=1)
class ClientNameSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ClientUser2
fields = ('url','phone_number','name','status','pk')
my views.py
class ClientViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows messages to be viewed or edited.
"""
queryset = ClientUser2.objects.all()
serializer_class = ClientNameSerializer
and it's my api root
api_root
If you want to be able to only retrieve and update models you can use RetrieveUpdateApiView
Reference : https://www.django-rest-framework.org/api-guide/generic-views/#retrieveupdateapiview
I am stuck on trying to solve an issue with the Serializers and related fields using the django-rest-framework. Currently I have a model that looks like this:
class DataSetModel(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
class DataPointModel(models.Model):
dataSet = models.ForeignKey(DataSetModel, related_name='dataPoints')
label = models.CharField(max_length=200)
My serializers look like this:
class DataPointSerializer(serializers.ModelSerializer):
class Meta:
model = DataPointModel
fields = ('pk','label')
class DataSetSerializer(serializers.ModelSerializer):
dataPoints = DataPointSerializer(many=True, read_only=True)
class Meta:
model = DataSetModel
fields = ('pk','title')
The problem I am having is when I try to change the "many=False" in the serializer produces this error:
Got AttributeError when attempting to get a value for field label on
serializer DataPointSerializer. The serializer field might be named
incorrectly and not match any attribute or key on the RelatedManager
instance. Original exception text was: 'RelatedManager' object has no
attribute 'label'.
Since this is only ever one model object (one-to-many relationship), I want to get the result as a single object vs a list of one object.
Am I doing this the right way? I thought that turning the "many=False" it would fetch the first record in an nested query.
Any insight would be greatly appreciated.
You can't set many=False, because dataPoints is a related field that returns a queryset containing a list of instances, not just an instance.
When you do DataPointModel.dataPoints that returns a queryset, it can't returns just an instance. So setting many=False, it wouldn't get the first element of the list.
So the solve I came to was refactoring my models with where the Foreign Keys are attached.
Here is the fix I implemented:
class DataSetModel(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
dataPoint = models.ForeignKey(DataPointModel)
class DataPointModel(models.Model):
label = models.CharField(max_length=200)
Moving it to the DataSetModel automatically joins the data model if you set 'many=False' in the Serializer object.
Write your DataPointModel as below. It should work then
class DataPointModel(models.Model):
dataSet = models.OneToOneField(DataSetModel, related_name='dataPoints')
label = models.CharField(max_length=200)
I'm new in using GenericForeignKey, and I couldn't make it to work in a query statement. The tables are roughly like the following:
class Ticket(models.Model):
issue_ct = models.ForeignKey(ContentType, related_name='issue_content_type')
issue_id = models.PositiveIntegerField(null=True, blank=True)
issue = generic.GenericForeignKey('issue_ct', 'issue_id')
class Issue(models.Model):
scan = models.ForeignKey(Scan)
A scan creates one issue, an issue generates some tickets, and I made Issue as a foreign key to Ticket table. Now I have a Scan object, and I want to query for all the tickets that related to this scan. I tried this first:
tickets = Tickets.objects.filter(issue__scan=scan_obj)
which doesn't work. Then I tried this:
issue = Issue.objects.get(scan=scan_obj)
content_type = ContentType.objects.get_for_model(Issue)
tickets = Tickets.objects.filter(content_type=content_type, issue=issue)
Still doesn't work. I need to know how to do these kind of queries in django? Thanks.
The Ticket.issue field you've defined will help you go from a Ticket instance to the Issue it's attached to, but it won't let you go backwards. You're close with your second example, but you need to use the issue_id field - you can't query on the GenericForeignKey (it just helps you retrieve the object when you have a Ticket instance). Try this:
from django.contrib.contenttypes.models import ContentType
issue = Issue.objects.get(scan=scan_obj)
tickets = Ticket.objects.filter(
issue_id=issue.id,
issue_ct=ContentType.objects.get_for_model(issue).id
)
Filtering across a GenericForeignKey can by creating a second model that shares the db_table with Ticket. First split up Ticket into an abstract model and concrete model.
class TicketBase(models.Model):
issue_ct = models.ForeignKey(ContentType, related_name='issue_content_type')
issue_id = models.PositiveIntegerField(null=True, blank=True)
class Meta:
abstract = True
class Ticket(TicketBase):
issue = generic.GenericForeignKey('issue_ct', 'issue_id')
Then create a model that also subclasses TicketBase. This subclass will have all the same fields except issue which is instead defined as a ForeignKey. Adding a custom Manager allows it to be filtered to just a single ContentType.
Since this subclass does not need to be synced or migrated it can be created dynamically using type().
def subclass_for_content_type(content_type):
class Meta:
db_table = Ticket._meta.db_table
class Manager(models.Manager):
""" constrain queries to a single content type """
def get_query_set(self):
return super(Manager, self).get_query_set().filter(issue_ct=content_type)
attrs = {
'related_to': models.ForeignKey(content_type.model_class()),
'__module__': 'myapp.models',
'Meta': Meta,
'objects': Manager()
}
return type("Ticket_%s" % content_type.name, (TicketBase,), attrs)