Django use only some fields in ForeignKey - django

I have three classes
Class Company(models.Model):
name = CharField( max_length = 26 , blank = True)
#(...)
class Person(models.Model):
name = CharField( max_length = 26 , blank = True)
function = CharField( max_length = 50 , blank = True)
company = ForeignKey ( Company , related_name = 'persons' )
# All the company table inside the data base is loaded in order to make the query,
# This make a HUGE amount of data and takes too many time...
# (...)
def __unicode__(self):
# caption uses both name and company__name fields but no other fields
return self.name + '(' + self.company.name + ')'
class Contact(models.Model):
person = ForeignKey ( Person )
In order to optimise performances, I would like the latest person field to use
Person.objects.all().only('name', 'company__name')
as queryset. Is it possible?

You can use values method, which return a subclass of QuerySet called ValuesQuerySet.
Person.objects.all().values('name', 'company__name')
For more information Django Doc

Use proxy models :
class Person_short_manager(Manager):
def get_query_set(self):
return super(self, Person_short_manager).get_query_set().only('name','company__name')
class Person_short(Person):
objects = Person_short_manager(Manager)
class Meta:
proxy = True
then replace
person = ForeignKey ( Person )
by
person = ForeignKey ( Person_short )

Related

Django Rest Framework many to many with extra fields serialization

class Item(models.Model):
name = models.CharField(max_length=20)
class Meals(models.Model):
name = models.CharField(max_length=50)
ingredients = models.ManyToManyField(Item, through='MealRecipe')
class Menu(models.Model):
name = models.CharField(max_length=50)
meals = models.ManyToManyField(Meals,through='CompMenu')
class CompMenu(models.Model):
TYPE_COMP = (
('B', 'Breakfast'),
('L', 'Lunch'),
('D', 'Dinner')
)
menu = models.ForeignKey(Menu)
meal = models.ForeignKey(Meals)
type = models.CharField(max_length=1, choices=TYPE_COMP)
class MealRecipe(models.Model):
meal = models.ForeignKey(Meal)
item = models.ForeignKey(Item)
qty = models.IntegerField()
If i need to serialze queryset how can i do it, there is no documentation about it, i need a JSON with Item_id, Item_name, MealRecipe_qty. Do i have to serialze all models ? I need this to manipualte the recipe quantities on the front end based on the selected menu.
receipes = MealRecipe.objects.filter(meal__in=meals_of_menu)
for receipe in receipes:
name = receipe.item.name
qty = receipe.qty
OR
MealRecipe.objects.filter(meal__menu=some_menu_instance).distinct()
I cannot figure out how to pass the result o this query to the front end
For your requirements of Item_id, Item_name, MealRecipe_qty, you will need to serialize the MealRecipe model and the Item model.
Also give a related name to item in MealRecipe model
class MealRecipe(models.Model):
meal = models.ForeignKey(Meal)
item = models.ForeignKey(Item,related_name='qty')
qty = models.IntegerField()
And your serializers will be
class MealRecipeSerializer(serializers.ModelSerializer):
class Meta:
model = MealRecipe
fields = ('qty')
class ItemSerializer(serializers.ModelSerializer):
qty = MealRecipeSerializer()
class Meta:
model = Item
fields = ('id','name','qty')
Also if you are passing a queryset to a serializer do it as, MealRecipeSerializer(many=True)

django get_queryset get() returns more than one object error

For these models:
class Product(models.Model):
code = models.IntegerField()
class Failure1(models.Model):
FAILURE_CHOICES = (
('SC', 'Screen'),
('BA', 'Battery'),
('BX', 'Box'),
# etc, with 10+ choices
)
name = models.CharField(max_length=2, choices=FAILURE_CHOICES)
class Failure2(models.Model):
FAILURE_CHOICES = (
('SZ', 'Blah'),
('BB', 'Basdasd'),
('BD', 'etc'),
# etc, with 10+ choices
)
name = models.CharField(max_length=2, choices=FAILURE_CHOICES)
class Market(models.Model):
MARKET_CHOICES = (
('ED', 'Education'),
('CO', 'Commercial'),
# etc, with 10 choices
)
product = models.ForeignKey(Product)
market = models.CharField(max_length=2,choices=MARKET_CHOICES)
failure1 = models.ManyToManyField(Failure1, blank=True)
failure2 = models.ManyToManyField(Failure2, blank=True)
class Failure_MarketManager(models.Manager):
def get_queryset(self):
return super(Failure_MarketManager, self).get_queryset().filter(Q(failure2__name__isnull=False) | Q(failure1__name__isnull=False))
class Failure_Market(Market):
class Meta:
proxy = True
objects = Failure_MarketManager()
What I'm after is an admin changelist that shows only those Markets with any Failures (from either the Failure1 or Failure2 list).
With the proxy model above, if there is more than one Failure, I get a 'get() returns more than one object' error.
If I change it to get_queryset().exclude(Q(failure2__name__isnull=True) | Q(failure1__name__isnull=True)) I get zero results - why is this ?
If I change it to get_queryset().filter(~Q(failure2__name__isnull=False) | ~Q(failure1__name__isnull=False)) it works - why does this work but the filter Q doesn't ?

Django admin: list not correct (duplicate rows)

My admin.py is like this:
class ResizableAdmin(admin.ModelAdmin):
class Media:
css = {
}
js = ('js/vendor/jquery-1.11.2.min.js',)
class GroupeMotsForm(django.forms.ModelForm):
mots = django.forms.ModelMultipleChoiceField(
queryset=Mot.objects.all().order_by('groupes__description', 'texte'),
widget=django.forms.SelectMultiple(attrs={'class': 'resize_dst'})
)
class Meta:
model = GroupeMots
fields = ['description', 'admin_taille_fenetre', 'mots', ]
widgets = {
'admin_taille_fenetre': django.forms.NumberInput(
attrs={'class': 'resize_src'}
)
}
class GroupeMotsAdmin(ResizableAdmin):
form = GroupeMotsForm
In my database I have only one row in GroupeMots:
It's displayed 3 times in the list of the admin interface:
Any idea where to look? Where could Django look to have 3 results? They all point to the same record. I'm stuck.
My model is like that:
class GroupeMots(models.Model):
description = models.CharField(max_length=150)
mots = models.ManyToManyField(Mot, blank=True)
class Meta:
ordering = ['mots__texte']
def __str__(self):
return u'{0}'.format(
self.description
)
And the problem came from ordering = ['mots__texte'] because there seems to be 3 results, so "ordering" generates dupes... I changed it to description and now it's ok

Relation in Django REST Framework?

I am using serializers.GeoFeatureModelSerializer to serialize Model. I have a queryset
that is creating Left Outer Join. I want to serialize related Model fields
Here is my Model
class LookupTiming(models.Model):
day = models.CharField(max_length=7)
time_1 = models.TimeField()
time_2 = models.TimeField()
class Meta:
db_table = u'lookup_timing'
class Streets(models.Model):
name = models.CharField(max_length=50)
geometry = models.GeometryField(null=True, blank=True)
objects = models.GeoManager()
class Meta:
db_table = u'streets'
def __unicode__(self):
return '%s' % self.name
class StreetTimings(models.Model):
street= models.ForeignKey(Streets)
lookuptiming = models.ForeignKey(LookupTiming)
class Meta:
db_table = u'street_timings'
queryset =
Streets.objects.filter(streettimings_lookuptiming_isnull=True)
Serializer Class
class StreetSerializer(gis_serializer.GeoFeatureModelSerializer):
class Meta:
model = Streets
geo_field = "geometry"
id_field = False
fields = ('id', 'streettimings__lookuptiming__day', other fields)
Updated
I want to show following fields on response
Streets (id)
LookupTiming (day)
I want output like this query simple is that
SELECT "streets"."id", "lookuptiming"."day" FROM "streets"
LEFT OUTER JOIN "streettimings" ON ( "streets"."id" = "streettimings"."street_id" )
LEFT OUTER JOIN "lookuptiming" ON ( "streettimings"."lookuptiming_id" = "lookuptiming"."id" )
How can i do this?
Thank you

django accessing foreign key in model

i have the following models
class SchoolClass(models.Model):
id = models.AutoField(primary_key = True)
class_name = models.TextField()
level = models.IntegerField()
taught_by = models.ManyToManyField(User,related_name="teacher_teaching",through='TeachSubject')
attended_by = models.ManyToManyField(User,related_name='student_attending')
def __unicode__(self):
return self.class_name
class Meta:
db_table = 'classes'
class Relationship(models.Model):
rChoices = (
(1,'Mother'),
(2,'Father'),
(3,'Guardian'),
)
parent = models.ForeignKey(User,related_name='parent')
student = models.ForeignKey(User,related_name='child')
relationship = models.IntegerField(choices= rChoices)
#add in __unicode__ for admin name
class Meta:
unique_together = ('parent','student')
db_table = 'relationship
I have the the pk of the class, and I want to find out who are the parents of the students in the selected class.
My feeble attempt is:
selected_class = SchoolClass.objects.get(pk=class_id)
studs = selected_class.attended_by.all().select_related()
r = Relationship.objects.filter(student__in=students)
parents = [.parent for p in r]
Now, I am just curious if there is a shorter or more efficient way of doing this(i'm sure missed something in the docs) ?
This should work
parents = Relationship.objects.filter(student__schoolclass__id=class_id).values_list('parent', flat=True)
"To refer to a "reverse" relationship, just use the lowercase name of the model". (docs)