Django ImageField issue - python

I have a similar model
Class Student(models.Model):
"""A simple class which holds the basic info
of a student."""
name = models.CharField(max_length=50)
age = models.PositiveIntegerField()
photo = models.ImageField(upload_to='foobar', blank=True, null=True)
As we can see photo field is optional. I wanted all the students who have their images saved in the college DB. For that i did this
>>> Student.objects.exclude(photo__name=None)
But i am getting this error :
FieldError: Join on field 'photo' not permitted.
So, How can i extract all those students having their photos?
Any sort of help regarding this would be appreciated.
Thanks in advance.

It doesn't work because field lookups only work on other models. Here, name is an attribute on the return value of your photo field.
Try this instead:
Student.objects.exclude(photo__isnull=True)
It is preferred to use isnull instead of comparing equality to None.
EDIT:
Jeff Ober's suggestion:
Student.objects.exclude(photo='')
He says filtering is performed on the actual values stored in DB. In a file field's case the path to the file.

Related

Django many-to-many query matching all related fields

I have two models connected by a many-to-many relationship in django.
class BuildingMapping(models.Model):
name = models.CharField(max_length=1000, null=False)
buildings = models.ManyToManyField(
Building, related_name="mapping"
)
class Building(models.Model):
function = models.CharField(
max_length=1000, blank=True, null=True
)
Function is a string containing one or more identifier divieded by a "/" e. g. "1300", "1300/2200", "1300/2230/7500", ...
I now want to perform a query that gets only BuildingMapping instances where the function for all Buildings is identical. I tried the following, but this will also return BuildingMapping instances where only one Building has "1300" as function.
BuildingMapping.objects.filter(buildings__function="1300")
Thanks!
If I understood correct, you want to get function field contains "1300". If it is right:
BuildingMapping.objects.filter(buildings__function__contains="1300")
I see that you are trying to fetch all the results which are matching 1300. What you are doing is exact match
strong text
You need to use icontains(case insensitive) or contains(case sensitive) for getting all matched data

Django models' best solution for this reverse ForeignKey

I'm making a personal project to manage restaurants.
Two of my models are facing a problem, these models are DiningRoom and Table.
DiningRoom is the representation of any area that the restaurant could have (e.g. we could have one area inside and other area in the terrace of the building).
And in every DiningRoom we can set a layout of Tables.
So, the more object-oriented way I find to map this is by many-to-one relationship (ForeignKey). Since one DiningRoom can have many Tables, and one Table can be only in one DiningRoom. Right?
So my models are:
class DiningRoom(models.Model):
account = models.ForeignKey(Account, on_delete=models.CASCADE, null=False)
name = models.CharField(max_length=50, null=False, blank=False)
rows = models.IntegerField(max=15, null=False)
cols = models.IntegerField(max=15, null=False) # rows and columns are for the room's grid layout.
class Table(models.Model):
row = models.IntegerField(max=15, null=False) # The row in the room's grid where the table is at.
col = models.IntegerField(max=15, null=False) # the column in the room's grid where the table is at.
dining_room = models.ForeignKey(DiningRoom, on_delete=models.CASCADE, null=False) # Here is the problem.
The problem is that when I am querying DiningRooms of the account in the view, I need to fetch also the Tables that are related to each DiningRoom in the queryset result.
def dining_rooms(request):
try:
account = Account.objects.get(id=request.session['account_id'])
except Account.DoesNotExists:
return response(request, "error.html", {'error': 'Account.DoesNotExists'})
dining_rooms = DiningRoom.objects.filter(account=account)
But also I need the Tables of the results in dining_rooms!
I found two possible solutions but none seem to be "correct" to me. One is to make a Many-to-many relationship and validate that any Table is only in one DiningRoom in the view. And the second and worse one could be fetching the Tables once for each DiningRoom obtained in the queryset (but imagine a restaurant with 5 or 6 different areas (DiningRooms), it would be needed to fetch the database six times for every time).
Doing it in vice-versa and fetching all the Tables and select_related DiningRooms is not possible since it's possible to have a DiningRoom with no Tables in it (and in this case we will have missing DiningRooms).
What could be the best way to handle this? Thanks!
You can use the related_name or relationships backwards, an acceptable solution would be to create a method in the DiningRoom model that is called associated_tables() and return using the related_name (modelname_set, in this case it would be table_set). It is the name of the lowercase child model followed by the suffix _set
class DiningRoom(models.Model):
#your fields
def associated_tables(self):
return self.table_set.all()
In addition, this video tutorial could clear your days and give you a better idea about reverse relationships:
https://youtu.be/7tAZdYRA8Sw

How to compare Specific value of two different tables in django?

I have two tables 'Contact' and other is "Subscriber".. I want to Compare Contact_id of both and want to show only those Contact_id which is present in Contact but not in Subscriber.These two tables are in two different Models.
Something like this should work:
Contact.objects.exclude(
id__in=Subscriber.objects.all()
).values_list('id', flat=True)
Note that these are actually two SQL queries. I'm sure there are ways to optimize it, but this will usually work fine.
Also, the values_list has nothing to do with selecting the objects, it just modifies "format" of what is returned (list of IDs instead of queryset of objects - but same database records in both cases).
If you are excluding by some field other then Subscriber.id (e.g: Subscriber.quasy_id):
Contact.objects.exclude(
id__in=Subscriber.objects.all().values_list('quasy_id', flat=True)
).values_list('id', flat=True)
Edit:
This answer assumes you don't have a relationship between your Contact and Subscriber models. If you do, then see #navit's answer, it is a better choice.
Edit 2:
That flat=True inside exclude is actually not needed.
I assume you have your model like this:
class Subscriber(models.Model):
contact = models.ForeignKey(Contact)
You can do what you want like this:
my_list = Subscriber.objects.filter(contact=None)
This retrieves Subscribers which don't have a Contact. Retrieveing a list of Contacts is straightforward.
If you want to compare value of fields in two different tables(which have connection with ForeignKey) you can use something like this:
I assume model is like below:
class Contact(models.Model):
name = models.TextField()
family = models.TextField()
class Subscriber(models.Model):
subscriber_name = models.ForeignKey(Contact, on_delete=models.CASCADE)
subscriber_family = models.TextField()
this would be the query:
query = Subscriber.objects.filter(subscriber_name =F(Contact__name))
return query

How can I order a queryset by many to many related objects value?

I have a queryset containing Book objects.
Book has a m2m relationship to Author.
I want to order the books that are in the queryset by the name of the first author (authors would be sorted alphabetically so the first one would be the one whose last name comes first in the alphabet).
I guess it would be something about aggregation but I cannot seem to find what would be the right solution.
I have tried
books_qs.annotate(first_author=Min('author__lastname')).order_by('first_author')
but of course it is not the right type so I get faced with ValueError: could not convert string to float: Folland.
How should I go about this?
edit: Django 1.4.2 + MySQL
Of course you'll get a ValueError because you're passing a string to Min whereas it takes float.
That is, if your Author model has, say, age = models.FloatField(), you can pass age as an argument to Min, like: Min('age') but you can't pass a string, in your case, lastname.
I don't exactly understand your question. But if you want to order anything in your Django models, I guess easiest way would be by doing this with class Meta
class Author(models.Model):
lastname = models.CharField(max_length=100)
# other fields ...
class Meta:
ordering = ['lastname']
class Book(models.Model):
author = models.ManyToManyField(Author)
book_name = models.CharField(max_length=100)
# other fields ...
class Meta:
ordering = ['book_name']
All the authors will be sorted alphabetically as per their last name and all the books will be sorted alphabetically as per their name.

Retrieve the subset of fields by querying the embedded field

Is it possible to retrieve the subset of fields using Django mongodb nonrel. I am totally new to python, but have good knowledge in mongo.
My requirement is very straight forward, I wanted to query the collection by its embedded field and return only some specific fields
I could do that in mongodb by
db.Contract.find({'owner.name':'Ram'},{'address':1})
and I tried this in django
Contract.objects.filter(owner__name='Ram')
but it throws an error
raise FieldError("Join on field %r not permitted. Did you misspell %r
for the lookup type?" % (name, names[pos + 1])) FieldError: Join on
field 'owner' not permitted. Did you misspell 'name' for the
lookup type?
am totally struck here. I believe i have my models as specified in the documentation.
class SimplePerson(models.Model):
name = models.CharField(max_length=255)
user_key = models.CharField(max_length=255)
class Contract(models.Model):
owner = EmbeddedModelField('SimplePerson')
title = models.CharField(max_length=120, )
This is really weird. I could't find any reference in the documentation site about how to query the embedded field & retrieve the subset of fields.
Finally I used raw_query to query the embedded field
Contract.objects.raw_query({'owner.name':'Ram'})
But still not able to figure out how to retrieve the subset of fields. Can someone help me out?
Subobject filters aren't possible yet so you need to drop down to raw_query (which you already figured out). To retrive a subset of fields, use .values('field1', 'field2', ...).
Filtering by EmbeddedField is now possible with the following syntax:
Contract.objects.filter(owner={'name': 'Ram'})

Categories

Resources