Adding a value to a queryset in Django - python

In my Django form I have a ModelChoiceField for employees, but I want a choice in the dropdown for 'all' employees. What would be the best way to accomplish this?
employees = forms.ModelChoiceField(queryset=Employees.objects.all())
First attemptI tried
employees = forms.ChoiceField(choices = Employees.objects.values())
but I get a 'too many objects to unpack' error
Thanks

Try this:
employees = forms.ChoiceField(choices = [(emp['id'], emp['full_name'])
for emp in Employees.objects.values('id', 'full_name')])
The too many objects to unpack error raised because every cell of chioces must only contains two value similar below:
[(1, 'Eric Manson'), (2, 'Julia Rose'), (3, 'Saadi Khorshid'), ...]
But Employees.objects.values() unpacking all fields in dictionary form.

Related

Complex annotation to get all statuses for each user counted

In my leads table I need to count the number of leads for each status for each user. Is there any way to do that by arm annotate? Right now I have something like this:
leads.objects.values("created_by","status").annotate(total=Count("status")).order_by("created_by")
and output is like:
[{'created_by':"Andrew Ray', "status":'ACTIVE", 'total':4}, {'created_by':Andrew Ray', "status":'LOST", 'total':2}, {'created_by':Andrew Ray', "status":'WON", 'total':1}]
is there a way to get it like this:
[{'created_by':"Andrew Ray', "ACTIVE" : 4, "LOST": 2, "WON":1}]
Active, Won, and Lost are values of STATUS field in leads model. There is also another there and I would like to make key and value pair for each of them for each user (CharField)
Without knowing your model, something like the following should work.
Create a values queryset on the unique field (created_by) and order by that field. Then you annotate the queryset with counts that are filtered by the status you want to count per the unique field. We can construct the annotations dynamically by using the values from the choices enum, creating and then unpacking a dict with all the choices to pass the counts as keywords
from django.db.models import Count, Q
Leads.objects.order_by(
'created_by'
).values(
'created_by'
).annotate(
total=Count('pk'),
**{choice: Count('pk', filter=Q(status=choice)) for choice in Leads.StatusEnum.values}
)

Django filter many to many model's JSON field with the given

I have Movies and Participants model and it is like this,
class Movie(models.Model):
something something
participants = models.ManyToManyField(Participant)
class Participant(models.Model):
something something
type = models.CharField(max_length=127, null=True, blank=True)
What I would like to do is, check the Participants type field with the given list and according to it list the Movies or not.
For example, I have type_list=["Adults", "Children", "Senior"] but Movie object has 2 Participant objects and one of them is type="Adults" and the other one is type="Children"
In example I would expect not to show that Movies since it doesn't have all the required Participants type.
What have I tried so far;
movie.participants.filter(type__in=["Adults", "Children", "Senior"])
however, this returns a two participants object
movie.participants.filter(Q(type="Adults") | Q(type="Children") | Q(type="Senior")):
this one also returns the two participant object.
I also cant use the & operator.
The only idea I left with is to check the count of the participants. Query returned two but I have three participant so I can't show this movie but the problem is in here list is variable that coming from front end. So my both query and if statement should be generic and I don't know how to do both and also I am %100 sure that there should be a best practice rather than this.
I would appreciate every tiny help, thank you!
You can fetch all particiant's types using values_list with distinct and compare returned value with provided type_list by iterating over provided list:
types_from_db = movie.participants.values_list("type", flat=True).distinct()
for movie_type in ["Adults", "Children", "Senior"]:
if movie_type not in types_from_db:
return False
return True

"ValueError: need more than 0 values to unpack"

I have looked at the questions on here and none of them seem to help my cause. Essentially what I am doing is calling getAllOpenChoices to try and return a the value of the Radio button so when one is selected it saves.
forms.py
def getAllOpenChoices():
listOpenChoice = [('All', 'All'), ('No One', 'No One'), ('Test','Test')]
all_choices = Requisition.objects.distinct()
for choices in all_choices:
temp = (Requisition.objects.filter(open_to=choices))
listOpenChoice.append(temp)
return tuple(listOpenChoice)
This error that I am getting is:
ValueError: need more than 0 values to unpack
getAllOpenChoices is being called:
self.fields['open_to'] = forms.ChoiceField( choices = getAllOpenChoices, widget = forms.RadioSelect())
The choices should be a list of 2-tuples, like your initial value listOpenChoice
listOpenChoice = [('All', 'All'), ('No One', 'No One'), ('Test','Test')]`
If you extend that list, you should only add 2-tuples. For example:
listOpenChoice.append(('new', 'New'))
However, you are appending querysets, e.g. Requisition.objects.filter(open_to=choices). This doesn't make sense. One of your querysets is empty, which is why you get the zero in the error message "need more than 0 values to unpack".
It's not clear to me what you're trying to append to the list, so I can't tell you how to fix your code. As long as you only append 2-tuples, you should be ok.

Python + making a function more generic

I wanted some guidance if possible on how to make this more generic:
def get_industry_choices(self):
industries = Industry.objects.all().order_by('name')
ind_arr = [(ind.id, ind.name) for ind in industries]
return ind_arr
Basically this function will return choices as expected for the forms.ChoiceField. I need to do this in a few places, and wanted to make the function above more generic. I know how to get the industries = Industry.objects.all().order_by('name') to be generic, but the 2nd part is what I'm not sure about. When creating the tuples, it has (ind.id, ind.name). the ind.name can be any value depending on the model passed in (it may not always have name in the model).
I tried to read up on this in a few places including:
Passing functions with arguments to another function in Python?
The above resource shows how to do it using a function passed in, but that seems a bit overkill? If I have to pass a function as an argument anyway, whats the point of making it more generic with one more function?
[EDIT]
Basically I want to produce something similar to this:
TITLE_CHOICES=(
(1, 'Mr.'),
(2, 'Ms.'),
(3, 'Mrs.'),
(4, 'Dr.'),
(5, 'Prof.'),
(6, 'Rev.'),
(7, 'Other'),
)
So when doing forms.ChoiceField I can pass in TITLE_CHOICES for example as the possible choices. The first value is the value I get when the form is submitted, the second value is what the user sees on form. I want to be able to programmatically create this with any model, I pass in the model name and one field in the above example, name. I want to create the tuple such that it is (id, name). But name could be replaced with anything in a different model...
It is hard to tell from your question, but I think the bit you are missing is getattr(). For example
ind = something()
for field in ['id', 'name']:
print getattr(ind, field)
Actually, Django already has a shortcut for this: values_list.
Industry.objects.all().values_list('id', 'name')
or
fields = ['id', 'name']
Industry.objects.all().values_list(*fields)
Maybe this helps:
from some_app.models import SomeModel
def generate_choices(model, order=None *args):
choices = model.objects
if order:
choices = choices.order_by(order)
return choices.values_list('pk', *args)
class MyForm(forms.Form):
my_choice_field = CharField(max_length=1,
choices=generate_choices(SomeModel, 'name'))
other_choice_field = CharField(max_length=1,
choices=generate_choices(SomeModel, 'city', 'state'))

django error 'too many values to unpack'

I'm learning Django by building a simple recipes app. I have a 1 table model using the 'choices' field option for recipe categories rather than using a 2nd 'categories' table and a foreign key relationship. So i created db table via syncdb and then loaded table with test data. When i go to admin and click on the 'Recipes' link in an attempt to view recipes i get the following error:
Template error
In template /var/lib/python-support/python2.6/django/contrib/admin/templates/admin/change_list.html, error at line 34
Caught an exception while rendering: too many values to unpack
If anyone can shed light on this cryptic error that would be great. Db is Sqlite. Django version is 1.0. The model is listed below:
from django.db import models
class Recipe(models.Model):
CATEGORY_CHOICES = (
(1, u'Appetizer'),
(2, u'Bread'),
(3, u'Dessert'),
(4, u'Drinks'),
(5, u'Main Course'),
(6, u'Salad'),
(7, u'Side Dish'),
(8, u'Soup'),
(9, u'Sauce/Marinade'),
(10, u'Other'),
)
name = models.CharField(max_length=255)
submitter = models.CharField(max_length=40)
date = models.DateTimeField()
category = models.SmallIntegerField(choices=CATEGORY_CHOICES)
ingredients = models.TextField()
directions = models.TextField()
comments = models.TextField(null=True, blank=True)
Edit: Updated in light of kibibu's correction.
I have encountered what I believe is this same error, producing the message:
Caught ValueError while rendering: too many values to unpack
My form class was as follows:
class CalcForm(forms.Form):
item = forms.ChoiceField(choices=(('17815', '17816')))
Note that my choices type here a tuple. Django official documentation reads as follows for the choices arg:
An iterable (e.g., a list or tuple) of 2-tuples to use as choices for
this field. This argument accepts the same formats as the choices
argument to a model field.
src: https://docs.djangoproject.com/en/1.3/ref/forms/fields/#django.forms.ChoiceField.choices
This problem was solved by my observing the documentation and using a list of tuples:
class CalcForm(forms.Form):
item = forms.ChoiceField(choices=[('17815', '17816')])
Do note that while the docs state any iterable of the correct form can be used, a tuple of 2-tuples did not work:
item = forms.ChoiceField(choices=(('17815', '17816'), ('123', '456')))
This produced the same error as before.
Lesson: bugs happen.
You should use a ChoiceField instead of SmallIntegerField
If I had to guess, it's because whatever is in the administrative template expects a list of tuples, but you've instead supplied a tuple of tuples (hence the "too many values"). Try replacing with a list instead:
CATEGORY_CHOICES = [ # Note square brackets.
(1, u'Appetizer'),
(2, u'Bread'),
(3, u'Dessert'),
(4, u'Drinks'),
(5, u'Main Course'),
(6, u'Salad'),
(7, u'Side Dish'),
(8, u'Soup'),
(9, u'Sauce/Marinade'),
(10, u'Other'),
]
Per http://code.djangoproject.com/ticket/972 , you need to move the assignment CATEGORY_CHOICES = ... outside the class statement.
I got it working. Most of the 'too many values to unpack' errors that i came across while googling were Value Error types. My error was a Template Syntax type. To load my recipe table i had imported a csv file. I was thinking maybe there was a problem somewhere in the data that sqlite allowed on import. So i deleted all data and then added 2 recipes manually via django admin form. The list of recipes loaded after that.
thanks.
I just had the same problem... my cvs file came from ms excel and the date fields gotten the wrong format at saving time. I change the format to something like '2010-05-04 13:05:46.790454' (excel gave me 5/5/2010 10:05:47) and voilaaaa no more 'too many values to unpack’
kibibu's comment to Kreychek's answer is correct. This isn't a Django issue but rather an interesting aspect of Python. To summarize:
In Python, round parentheses are used for both order of operations and tuples. So:
foo = (2+2)
will result in foo being 4, not a tuple who's first and only element is 4: 4
foo = (2+2, 3+3)
will result in foo being a two-dimensional tuple: (4,6)
To tell Python that you want to create a one-dimensional tuple instead of just denoting the order of operations, use a trailing comma:
foo = (2+2,)
will result in foo being a one-dimensional tuple who's first and only element is 4: (4,)
So for your scenario:
class CalcForm(forms.Form):
item = forms.ChoiceField(choices=(('17815', '17816'),))
would give what you want. Using a list is a great solution too (more Pythonic in my opinion), but hopefully this answer is informative since this can come up in other cases.
For example:
print("foo: %s" % (foo))
may give an error if foo is an iterable, but:
print("foo: %s" % (foo,))
or:
print("foo: %s" % [foo])
will properly convert foo to a string whether it's an iterable or not.
Documentation: http://docs.python.org/2/tutorial/datastructures.html#tuples-and-sequences
This error IMO occurs when a function returns three values, and you assign it to 2. e.g.:
def test():
a=0
b=0
c=0
....
a,b=test() <---three values returned, but only assigning to 2.
a,b,c=test() <---three values returned, assigned to 3.OK

Categories