Deal with multiple forms from the same Model in Django - django

I have a template page where I can create multiple jobs at the same time.
They all use the same Form, and when I submit the form, I receive POST data on the view like this:
<QueryDict: {'csrfmiddlewaretoken': ['(token)'], 'name': ['name1', 'name2', 'name3'], 'min': ['1', '2', '3'], 'max': ['10', '20', '30'], 'color': ['green', 'blue', 'red']}>
In the view, when I do
form = JobForm(request.POST), I get the following clean data {'name': 'name3', 'min': 3, 'max': 30, 'color': 'red'}. I have seen this solution, but I don't know how many Jobs will be created at the same time so I can't create different prefixes on the view, so I only send the form to the template like this form = JobForm().
How can I check if all the submitted data is valid and create all the objects in a single page submission?

Related

Get respectives values from Django annotate method

I have the following query:
result = data.values('collaborator').annotate(amount=Count('cc'))
top = result.order_by('-amount')[:3]
This one, get the collaborator field from data, data is a Django Queryset, i am trying to make like a GROUP BY query, and it's functional, but when i call the .values() method on the top variable, it's returning all the models instances as dicts into a queryset, i need the annotate method result as a list of dicts:
The following is the top variable content on shell:
<QuerySet [{'collaborator': '1092788966', 'amount': 20}, {'collaborator': '1083692812', 'amount': 20}, {'collaborator': '1083572767', 'amount': 20}]>
But when i make list(top.values()) i get the following result:
[{'name': 'Alyse Caffin', 'cc': '1043346592', 'location': 'Wu’an', 'gender': 'MASCULINO', 'voting_place': 'Corporación Educativa American School Barranquilla', 'table_number': '6', 'status': 'ESPERADO', 'amount': 1}, {'name': 'Barthel Hanlin', 'cc': '1043238706', 'location': 'General Santos', 'gender': 'MASCULINO', 'voting_place': 'Colegio San José – Compañía de Jesús Barranquilla', 'table_number': '10', 'status': 'PENDIENTE', 'amount': 1}, {'name': 'Harv Gertz', 'cc': '1043550513', 'location': 'Makueni', 'gender': 'FEMENINO', 'voting_place': 'Corporación Educativa American School Barranquilla', 'table_number': '7', 'status': 'ESPERADO', 'amount': 1}]
I just want the result to be like:
[{'collaborator': '1092788966', 'amount': 20}, {'collaborator': '1083692812', 'amount': 20}, {'collaborator': '1083572767', 'amount': 20}]
there is something wrong, maybe a typo (also it seems you do not show the full query... something like data=yourmodel.objects.filter... is missing before):
The output of list(top.values()) returns a completely different model's fields then what you post as top Queryset- are you sure you really did:
result = data.values('collaborator').annotate(amount=Count('cc'))
top = result.order_by('-amount')[:3]
list(top.values())
because it should deliver what you expect (provided that data is a Queryset)

How to POST data to a Django Form that contains checkboxes

I have a problem when I am testing my registration form in Django. I am trying to make a POST request but I cannot select a checkbox field.
self.response = self.client.post(url, {
'username': 'testuser',
'password': 'testuserpassword',
'first_name': 'testtt',
'last_name': 'userrr',
'image': '',
'email': 'testuser#gmail.com',
'gender': 'M',
'dob': '10/10/1996',
'hobby': 'Fishing'
})
This is my line of code. The problem is at Hobby. The registration page is made of two forms. A profile form and a hobby form. There is a many-to-many relationship between Profile and Hobby models.
When I make the above POST request, I get this (Select a valid choice):
Thank you in advance!
According to the screenshot you've posted, the value for each hobby checkbox corresponds to an integer - 1, 2, 3, 4, etc. That would imply that the backend is expecting the hobby ID to be transmitted in the form. However, the test is not sending the hobby ID, it's sending the name.
Change the name to the corresponding ID - e.g.
self.response = self.client.post(url, {
...
'hobby': 1 # Fishing
})

Django extract field form html

I have a html page that returns data in a form. The forms is a multiple choice checkbox field with "name=states1". When I run print(vars(self)) in my forms.py I see that the data is there ['MD', 'WV', 'WY'] (see below) however, when I try to extract it with print(self.data['states1']) I just get 'WY' and print(len(self.data['states1'])) returns 2.
{'instance': <AA: AAobject>, '_validate_unique': False, 'is_bound': True, 'data': <QueryDict: {'csrfmiddlewaretoken': ['AAAAA']: ['1'], 'states1': ['MD', 'WV', 'WY'], 'states': [''], 'price': ['2.00'], 'user': ['1', '1']}>, ...
However, when I run
import json
print(json.dumps(self.data, indent=2))
I get the following output
{
"csrfmiddlewaretoken": "AAAAA",
"roles": "1",
"states1": "WY",
"states": "",
"price": "2.00",
"user": "1"
}
The data is just gone. Why is my data being restricted to the last field, when I can clearly see it when looking at vars?
forms.py
class UserProfileChangeForm(forms.ModelForm):
states = forms.CharField(widget=USStateSelect(), initial='TX', required=False)
class Meta:
model = SkilledLaborer
fields = ['user','roles','travel_flag','price','states']
def clean_states(self):
print('states')
states = self.cleaned_data['states']
print(type(vars(self)))
print(vars(self).keys())
print(vars(self))
print(self.data.keys())
print(self.data['states1'])
print(len(self.data['states1']))
import json
print(json.dumps(self.data, indent=2))
try:
self.data['states1']
except:
pass
return states

Testing formsets in Django

How do I pass the values of a formset in a unit test using client self.client.post('/url/', {})? I am getting a validation error saying management_form tampered.
Thanks in advance!
This is an example formset getting user's skills
class SkillForm(forms.Form):
level_id = forms.ChoiceField(choices=LEVEL_CHOICES, required = True)
txt_skills = forms.CharField(max_length=250, required = True)
SkillFormset = formset_factory(SkillForm,extra=1, max_num=10)
and this the sample POST data for test cases.
self.post_data.update({
'skillform-0-level_id': '2',
'skillform-0-txt_skills': 'Python',
'skillform-1-level_id': '3',
'skillform-1-txt_skills': 'Java',
'skillform-TOTAL_FORMS': '2',
'skillform-INITIAL_FORMS': '1',
'skillform-MAX_NUM_FORMS': '10'
})

Django unit testing; POST checkboxes with multiple values

I am trying to run a unit test on a form with multiple checkboxes, but cannot figure out how to send the POST data. The most similar question I can find is here. But how do I embed that url-encoded piece into the POST with the other form data?
If I do something like this, my test errors out and says classes = request.POST.getlist('class_choices')
AttributeError: 'dict' object has no attribute 'getlist':
request = HttpRequest()
request.method = 'POST'
request.POST['fname'] = 'A'
request.POST['lname'] = 'Student'
request.POST['email'] = 'me#name.com'
request.POST['class_choices'] = urllib.urlencode({
'class_choices': ['1', '2'],
}, True)
request.POST['passwd'] = 'password'
request.POST['conpasswd'] = 'password'
response = success(request)
self.assertIn('My Browser', response.content.decode())
But if I do this, I get an error on fname = request.POST['fname']
TypeError: string indices must be integers, not str
request.POST = urllib.urlencode({
'class_choices': ['1', '2'],
'fname': 'A',
'lname': 'Student',
'email': 'me#name.com',
'passwd': 'password',
'conpasswd': 'password'
}, True)
response = success(request)
So after trying out a couple other things, I'm basically going to say there is "technically" no answer to my question...I could not find any way to create a checkbox-type POST argument using HttpRequest. However, doing it the 'right' way with the Django test client as Hieu Nguyen suggested does allow for that capability. You just have to encapsulate the multiple options in parantheses, as:
response = c.post('/success/',{
'fname': 'A',
'lname': 'Student',
'email': 'me#name.com',
'passwd': 'password',
'conpasswd': 'password',
'class_choices': ('1','2'),
})