Restrict queryset sent to django form - django

I'm trying to restrict the selectable values of a 'persons' field in a particular form.
I have a TaskPerson model that has two foreign keys: one for 'task' one for 'person'.
In my form, the persons field should allow the user to select one or more persons, but only those persons which match a certain task.
I've attempted this:
persons = [tp.person for tp in TaskPerson.objects.filter(task=thistask)]
form.fields["persons"].queryset = persons
This list comprehension gives me the correct person objects I require, but my form doesn't display at all, presumably because it gives me only a standard python list.
I had a look over the docs, but I'm not quite sure how to progress. Could someone please advise how I can correctly display my form?
Many thanks

You can easily get a QuerySet of Person objects by following the reverse relationship to TaskPerson
http://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward
form.fields['field'].queryset = Person.objects.filter(taskperson__task=thistask)

Related

Django - Using single list objects from a model class

So Create_Watchlist is a model with a Foreignkey to the User Model and 'ticker' is a CharField of Create_Watchlist. Here is my views.py function for the approach
def watchlist_one(request, pk):
Create_Watchlist.objects.get(id=pk)
list_ticker = list(Create_Watchlist.objects.all().values_list('ticker', flat=True))
At the moment list_ticker equals ['AAPL, BTC']
I want to access in this case 'AAPL' and 'BTC' as different list objects, because I want to make an API request with each list item. The list_ticker variable changes with the users input from a form . So there could be smt like ['AAPL, BTC'], but as well smt like ['FB'] (etc.)
If I've made a mistake here, an explanation of how to deal with query sets and data types would also help me!
Thanks a lot :)

Fine tuning Django queryset retrieval

In a Django app of mine, I need to display, for a list of users (called user_ids), their:
username, avatar and score.
The username is retrieved from the User model, whereas avatar and score are present in the UserProfile model (that has a one-to-one field point to the User model, called user).
Currently my approach is to fetch the full objects (see below), even though I just need 3 attributes from the two models.
What's the most efficient way for me to just retrieve just the required fields, nothing else? Now I know i can do:
usernames = User.objects.filter(id__in=user_ids).values_list('username',flat=True)
scores_and_avatars = UserProfile.objects.filter(user_id__in=user_ids).values_list('score','avatar')
However, these give me separate querysets, so I can't iterate over them as a unified object_list and show each user's username, score and avatar in a Django template. So what would be the most efficient, light-weight way to retrieve and put this information together?
Currently, I'm doing the following to retrieve these three fields: queryset = User.objects.select_related('userprofile').filter(id__in=user_ids)
The most efficient way it's use values, your query will look like this:
usernames = User.objects.filter(id__in=user_ids).values('username', 'userprofile__score', 'userprofile__avatar')
This solution will return dictionary, but you can try to use only instead of values, it'll create django model object with specified fields, but if you will try to access not specified field it'll generate additional query.
usernames = User.objects.filter(id__in=user_ids).select_related('userprofile').only('username', 'userprofile__score', 'userprofile__avatar')

Get distinct objects for foreign key in existing Django query

Consider the following many-to-one relationship. Users can own many widgets:
class Widget(models.Model):
owner = models.ForeignKey('User')
class User(models.Model):
pass
I have a fairly complicated query that returns me a queryset of Widgets. From that I want to list the distinct values of User.
I know I could loop my Widgets and pull out users with .values('owner') or {% regroup ... %} but the dataset is huge and I'd like to do this at the database so it actually returns Users not Widgets first time around.
My best idea to date is pulling out a .values_list('owner', flat=True) and then doing a User.objects.filter(pk__in=...) using that. That pulls it back to two queries but that still seems like more than it should need to be.
Any ideas?
Use backward relationship:
User.objects.distinct().filter(widget__in=your_widget_queryset)

Django get row count by date

I have been mulling over this for a while looking at many stackoverflow questions and going through aggregation docs
I'm needing to get a dataset of PropertyImpressions grouped by date. Here is the PropertyImpression model:
#models.py
class PropertyImpression(models.Model):
'''
Impression data for Property Items
'''
property = models.ForeignKey(Property, db_index=True)
imp_date = models.DateField(auto_now_add=True)
I have tried so many variations of the view code, but I'm posting this code because I consider to be the most logical, simple code, which according to documentation and examples should do what I'm trying to do.
#views.py
def admin_home(request):
'''
this is the home dashboard for admins, which currently just means staff.
Other users that try to access this page will be redirected to login.
'''
prop_imps = PropertyImpression.objects.values('imp_date').annotate(count=Count('id'))
return render(request, 'reportcontent/admin_home.html', {'prop_imps':prop_imps})
Then in the template when using the {{ prop_imps }} variable, it gives me a list of the PropertyImpressions, but are grouped by both imp_date and property. I need this to only group by imp_date, and by adding the .values('imp_date') according to values docs it would just be grouping by that field?
When leaving off the .annotate in the prop_imps variable, it gives me a list of all the imp_dates, which is really close, but when I group by the date field it for some reason groups by both imp_date and property.
Maybe you have defined a default ordering in your PropertyImpression model?
In this case, you should add order_by() before annotate to reset it :
prop_imps = PropertyImpression.objects.values('imp_date').order_by() \
.annotate(count=Count('id'))
It's explained in Django documentation here:
Fields that are mentioned in the order_by() part of a queryset (or which are used in the default ordering on a model) are used when selecting the output data, even if they are not otherwise specified in the values() call. These extra fields are used to group “like” results together and they can make otherwise identical result rows appear to be separate. This shows up, particularly, when counting things.

Beginner Django Forms Question: Adding an Item to a User's Categories

I have in my models Item with a many-to-many connection with Categories, and Categories have a Foreign Key to User.
What I'm hitting a road block figuring out is how to create a view with the intent to import an Item object to one or more of a User's Categories.
In it's most basic implementation I would like the view to display only the list of Categories that the User owns, and have the view process the form so that the Item is added to the appropriate Categories.
I've been struggling trying to figure out how to start this, including how to pass a User's categories to the form.
Thanks.
in the form class (ItemForm) do this
def __init__(self,user,*args,**kwargs):
super(ItemForm,self).__init__(*args,**kwargs)
self.fields['categories'] = forms.ModelMultipleChoiceField(
queryset=Categories.objects.filter(user=user))
then in your view call the form with :
form = ItemForm(request.user)
or
form = ItemForm(request.user, request.POST)
this should get you started. hopefully you can work out what you need to do from there. your question didn't leave much else to go by.