Web2Py GET value - python

Hi I'm trying to get the value from request.args(0) and use it in the submitting of a form.
I want 'game_id' to be automatically assigned the args value (which is the unique ID of the game in my games table.
def review():
getId = db.games(request.args(0)) or redirect(URL('default', 'index'))
formReview = SQLFORM(db.reviews,fields = ['game_id','title','review']).process()
db.reviews.game_id.default= request.args(0)
formReview.vars.game_id = request.args(0)
if formReview.accepted: redirect(URL('index'))
return dict(formReview=formReview, getId=getId)
db.define_table('reviews',
Field('title',requires=IS_NOT_EMPTY()),
Field('review','text',requires=IS_NOT_EMPTY()),
Field('game_id', 'reference games'))
I thought the line:
formReview.vars.game_id = request.args(0)
would pre populate the field but it isn't working.

The most reliable way to pre-populate the form is by setting the field's default value (which must be done before creating the form):
def review():
getId = db.games(request.args(0)) or redirect(URL('default', 'index'))
db.reviews.game_id.default = request.args(0)
formReview = SQLFORM(db.reviews, fields=['game_id','title','review']).process()
if formReview.accepted: redirect(URL('index'))
return dict(formReview=formReview, getId=getId)

Related

Display 1 when no data is exist in database

I am trying to generate incremental id whenever I am adding new data in my model. here I am getting the the next number whenever I am adding new data. but If there is no any data in my table its giving me error. 'NoneType' object has no attribute 'tax_id'
Here is my code
views.py
def tax_settings(request):
latest_id = (Tax_Settings.objects.last()).tax_id+1
if request.method == 'POST':
tax_id = latest_id
name = request.POST['tax_name']
tax_percentage = request.POST['tax_percentage']
tax_details=Tax_Settings.objects.create(tax_id=tax_id, name=name, tax_percentage=tax_percentage)
tax_details.save()
next_id = (Tax_Settings.objects.last()).tax_id+1
return render(request,"settings/tax-settings.html",{"latest_id":next_id})
else:
return render(request,"settings/tax-settings.html",{"latest_id":latest_id})
html
<input type="text" class="form-control" placeholder="{{latest_id}}" name="tax_id" disabled>
which condition I can give to my latest_id if data(tax_id) not exists?
You are trying to do too much in too few lines of code. Wherever you use queryset .last() or .first() you must explicitly handle the case where it returns None!
You need code of the form:
o = Tax_Settings.objects.last()
if o is not None:
tax_id = o.tax_id + 1
else:
tax_id = 1 # if that's a sensible default value
or even
o = Tax_Settings.objects.last()
assert o is not None, "This can't happen!" # except obviously, it does in this question.
Either you first create a single record than don't need to handle this or
tax_id = 0
latest_rec = (Tax_Settings.objects.last())
if latest_rec is not None:
latest_id = latest_rec.tax_id+1
You could simply add:
if latest_id is None:
latest_id = 1
If I understand it correctly, you have issues with your first line in the provided function:
latest_id = Tax_Settings.objects.last().tax_id+1
when you have no data, i.e. Tax_Settings.objects.last() is None.
You should define default ID, for instance 0 which would be assigned in case of missing objects:
def tax_settings(request):
if Tax_Settings.objects.last() is not None:
# some data already stored
latest_id = Tax_Settings.objects.last().tax_id
else:
# no data present yet
latest_id = 0
. . .
btw. I am not sure why are you incrementing the latest value in the beginning, but you need to take into account that if your default latest ID is 0 then the ID of the first data unit stored will be 1.
The following code also works:
tax_data=Tax_Settings.objects.all()
if not tax_data:
print("no data found")
latest_id=1
else:
latest_id = (Tax_Settings.objects.last()).tax_id+1

Django form unittest with ChoiceField and MultipleChoiceField failing is_valid()

I'm running into a small problem with writing a unit test for a Django form. I really just want to check the is_valid() method and have seen examples but my code isn't working and after a day or so of reading up on Google I've yet to find the answer I'm looking for. Below is the code for the forms.py and test_forms.py
forms.py
class DataSelectForm(forms.Form):
#these are done in the init funct.
result_type = forms.ChoiceField(widget=forms.Select(attrs={'class': 'field-long'}))
band_selection = forms.MultipleChoiceField(widget=forms.SelectMultiple(attrs={'class': 'multiselect field-long'}))
title = forms.CharField(widget=forms.HiddenInput())
description = forms.CharField(widget=forms.HiddenInput())
def __init__(self, result_list=None, band_list=None, *args, **kwargs):
super(DataSelectForm, self).__init__(*args, **kwargs)
if result_list is not None and band_list is not None:
self.fields["result_type"] = forms.ChoiceField(choices=result_list, widget=forms.Select(attrs={'class': 'field-long'}))
self.fields["band_selection"] = forms.MultipleChoiceField(widget=forms.SelectMultiple(attrs={'class': 'multiselect field-long'}), choices=band_list
test_forms.py
def test_data_select_form(self):
results = ResultType.objects.all()
results_value = []
for result in results:
results_value.append(result.result_type)
bands = SatelliteBand.objects.all()
bands_value = []
for band in bands:
bands_value.append(band.band_name)
form_data = {'result_type': results_value, 'band_selection': bands_value, 'title': 'a title', 'description': 'some description'}
form = DataSelectForm(data = form_data)
print(form['title'].value())
print(form['description'].value())
print(form['result_type'].value())
print(form['band_selection'].value())
self.assertTrue(form.is_valid())
The only thing I get when I run the test case is "AssertionError: False is not true" I understand the error, just not why I'm getting it. I'm passing in all the data and I can see it when I run the print statements. I've tried taking the result_type and band_selection and passing it into the constructor instead of it being a part of the form_data but that didn't work either. What am I missing?
You need to pass result_list and band_list when you construct your form.
# These aren't the actual choices you want, I'm just showing that
# choices should be a list of 2-tuples.
result_list = [('result1', 'result1'), ('result2', 'result2'), ...]
band_list = [('band1', 'band1'), ('band2', 'band2'), ...]
DataSelectForm(result_list=result_list, band_list=band_list, data=form_data)
If you don't pass the values to the form, then you don't set the choices for the fields. If the fields don't have any choices, then the values in the data dict cannot be valid, so the form will always be invalid.

Returning multiple fetched users

I have a view which fetches multiple users from a database based on passed in skills. It works almost as desired except if it returns more than one user it only passes back the most recently fetched user. How do I aggregate fetched users to be passed back to the template. I've tried passing them back as a list but they didn't appear.
Here is my code:
form = FilterFreelancerForm(request.POST)
filtered_skills = set((request.POST.getlist('skills_select')))
match_fl = Freelancer.object.annotate(c=Count('skills')).filter(c=len(filtered_skills))
candidate_freelancers = None
for skill in filtered_skills:
candidate_freelancers = match_fl.filter(skills=skill)
freelancers = None
for freelancer in candidate_freelancers:
freelancers = User.objects.filter(freelancer=freelancer.id)
return render(request, 'freelancestudent/browsefreelancers.html', {'freelancers': freelancers,
'filter_form': form})
I previously had this:
freelancers = []
for freelancer in candidate_freelancers:
freelancers.append(User.objects.filter(freelancer=freelancer.id))
which returns nothing to the template.
Instead of:
for freelancer in candidate_freelancers:
freelancers = User.objects.filter(freelancer=freelancer.id)
try:
freelancers = User.objects.filter(freelancer__in=[freelancer.id for freelancer in candidate_freelancers])
out:
[<User: user1>, <User: user2>]

Append new value to old value

Im trying to save value to a textfield in django with a celery task, but if the textfield has a value, I want to append the new value to the old value.
Here is my model:
class Profile(models.Model):
username = models.CharField(max_length=200)
info = models.TextField(blank=True)
Here is what I have tried:
#shared_task
def update_profile(data, profile_username):
#Get the profile
profile = Profile.objects.get(username=profile_username) #(WORKING)
#Check if info is in dataset
if 'info' in data: #(WORKING)
#Check if there is an old value
if profile.info: #(WORKING)
#Old value found
old_info = profile.info
#Append old and new value
new_info = '{}\n{}'format(old_info, data['info'])
profile.info = new_info
else:
#No old value fond, save the new value
profile.info = data['info'] #(WORKING)
#Save profile
profile.save() #(WORKING)
If the field does not have an old value, I can save the new value just fine, but when I try save the old and new value together, I will not work! I can only save one of them, not "update" the field like I want to.
Edit:
I see now that new_info = '{}\n{}'format(old_info, data['info']) is working, but I get this error : UnicodeEncodeError('ascii', u'Test\xf8', 128, 129, 'ordinal not in range(128)')
You need to simplify the loop, so that you can debug it correctly. Use get (a method of dictionaries) to fetch the key, and you can assign it a default value if the key doesn't exist.
Putting this together, your code now is:
def update_profile(data, profile_username):
profile = Profile.objects.get(username=profile_username) #(WORKING)
profile.info = u'{}\n{}'.format(profile.info, data.get('info', '').encode('utf-8'))
profile.save()

How to save a non ModelForm form to database in Django

I'm a newbie Django user, struggling with submitting form data to the database. So that I can generate dynamic forms I am using a non-ModelForm form to capture field data.
I'm commented out validation for now but I am trying to capture the POST data from the form to the database. The latest 'draft' of my views.py code is as follows - most interested in format from form_to_save = Scenario(...):
def scenario_add(request, mode_from_url):
urlmap = {
'aviation': 'Aviation',
'maritime': 'Maritime',
'international_rail': 'International Rail',
'uk_transport_outside_london': 'UK Transport (Outside London)',
'transport_in_london': 'Transport in London',
}
target_mode = urlmap[mode_from_url]
m = Mode.objects.filter(mode=target_mode)
tl = m[0].current_tl.threat_l
scenario_form = ScenarioForm(request.POST or None, current_tl=tl, mode=target_mode)
if request.method == 'POST':
#if scenario_form.is_valid():
form_to_save = Scenario(
target = Target(descriptor = scenario_form.fields['target']),
t_type = ThreatType(t_type = scenario_form.fields['t_type']),
nra_reference = NraReference(nra_code = scenario_form.fields['nra_reference']),
subt = scenario_form.fields['subt'],
ship_t = ShipType(ship_t = scenario_form.fields['ship_t']),
likelihood = scenario_form.fields['likelihood'],
impact = scenario_form.fields['impact'],
mitigation = scenario_form.fields['mitigation'],
compliance_score = scenario_form.fields['compliance_score'],
notes = scenario_form.fields['notes']
)
form_to_save.save()
# This needs to be changed to a proper redirect or taken to
# a scenario summary page (which doesn't yet exit.)
return render(request, "ram/new_scenario_redirect.html", {
'scenario_form': scenario_form,
'mode': mode_from_url,
'mode_proper': target_mode
})
else:
# if there is no completed form then user is presented with a blank
# form
return render(request, 'ram/scenario_add.html', {
'scenario_form': scenario_form,
'current_tl': tl,
'mode': mode_from_url,
'mode_proper': target_mode
})
Any advice gratefully received. Many thanks.
You've commented out the is_valid check, for some reason. You need that: as well as checking for validity, it also populates the form's cleaned_data dictionary which is what you should be getting the data from to create your object. (And don't call that object "form_to_save": it's a model instance, not a form).
if request.method == 'POST':
if scenario_form.is_valid():
scenario = Scenario(
target = Target(descriptor=scenario_form.cleaned_data['target']),
t_type = ThreatType(t_type = scenario_form.cleaned_data['t_type'])
...etc
Plus, you should move the final "return render" call out of the else block, so that it is caught when the form is not valid, to show any errors.
However, as petkostas says, you would almost certainly be better off using an actual ModelForm in the first place.
You can add custom options by overriding the init function in your form. For example:
class SomeForm(forms.Form):
department = forms.ChoiceField(widget=forms.Select, required=True)
...
def __init__(self, *args, **kwargs):
super(SomeForm, self).__init__(*args, **kwargs)
self.fields['department'].choices = Department.objects.all().order_by('department_name).values_list('pk', 'department_name')
You can also change the queryset in the init function:
where Department is a foreign key for example
queryset = Department.objects.filter(your logic)
self.fields['department'].queryset = queryset

Categories