using django cleaned_data to reset data before commit to db - python

I started this thread and managed to figure out the issue yesterday.
However, another related issue has occurred.
When I have a 2nd select list in the model, and I select '8888' or '9999' to remove / reset the values when the form is submitted, how can I set the value of the 2nd select list to the default value?
Here is an example of the models.py code I have:
.....
DISPLAY_ONLY_AWARD_AND_GRANT_DESCRIPTION_WITH_PROMPT = 8888
DISPLAY_ONLY_AWARD_AND_GRANT_DESCRIPTION_WITHOUT_PROMPT = 9999
.....
AWARD_GRANT_TYPES = (
(SELECT_AWARD_AND_GRANT_TYPE, _('Select Type')),
....
(OTHER_GRANT, _('Other Grant')),
(WRITE_MY_OWN_AWARD_AND_GRANT_TYPE_DESCRIPTION, _('Write my own Type description')), #7777
(DISPLAY_ONLY_AWARD_AND_GRANT_DESCRIPTION_WITH_PROMPT, _('Display only Description with prompt')), #8888
(DISPLAY_ONLY_AWARD_AND_GRANT_DESCRIPTION_WITHOUT_PROMPT, _('Display only Description without prompt')) #9999
)
....
AWARD_GRANT_DISPLAY_COMMENCEMENT_DATE_AND_COMPLETION_DATE_AS_DATE_PROMPTS = 1
....
AWARD_GRANT_DETAILS_DATE_DISPLAY_TYPES = (
(AWARD_GRANT_DISPLAY_COMMENCEMENT_DATE_AND_COMPLETION_DATE_AS_DATE_PROMPTS, _('Display Commencement and Completion as date prompts')),
....
)
user = models.ForeignKey(User)
language_version = models.ForeignKey('LanguageVersion')
award_grant_type = models.PositiveIntegerField(choices=AWARD_GRANT_TYPES, default=SELECT_AWARD_AND_GRANT_TYPE, validators=[MinValueValidator(1)])
award_grant_type_description = models.CharField(null=True, blank=True, max_length=250)
award_grant_date = models.DateField(null=True, blank=True)
award_grant_date_display_type = models.PositiveIntegerField(choices=AWARD_GRANT_DETAILS_DATE_DISPLAY_TYPES, default=AWARD_GRANT_DISPLAY_COMMENCEMENT_DATE_AND_COMPLETION_DATE_AS_DATE_PROMPTS)
award_grant_description = models.TextField(null=False, blank=False, max_length=5000)
Here is my forms.py clean code that should reset the award_grant_date_display_type to 1 when the user has selected 8888 or 9999 from the select list award_grant_type before being committed to the db:
def clean(self):
cd_agdf = super(AwardGrantDetailsForm, self).clean()
if 'award_grant_type' in cd_agdf:
if cd_agdf['award_grant_type'] == '':
self._errors['award_grant_type'] = self.error_class([_("You must select a Type.")])
elif cd_agdf['award_grant_type'] == '8888' or cd_agdf['award_grant_type'] == '9999':
# remove / reset the entered values when the award grant type only requires minimum data.
self.cleaned_data.pop('award_grant_type_description', None)
self.cleaned_data.pop('award_grant_date', None)
self.cleaned_data['award_grant_date_display_type'] = 1
else:
....
return cd_agdf
It appears that the line of code self.cleaned_data['award_grant_date_display_type'] = 1 is ignored and the original value retained.
I have tried placing the value in quotation marks, searched SO, Google and django docs, but I cannot figure this out.
EDIT
Here is my forms.py code as requested:
class AwardGrantDetailsForm(forms.ModelForm):
def __init__(self, available_languages, language_preference, *args, **kwargs):
"""
available_languages should be a valid choices list
"""
super(AwardGrantDetailsForm, self).__init__(*args, **kwargs)
self.fields['language_code'] = forms.ChoiceField(choices=available_languages, initial=language_preference, label=_('Language'),)
self.fields['award_grant_date'].input_formats = (settings.DATE_INPUT_FORMATS)
class Meta:
model = AwardGrantDetails
fields = (
'award_grant_type',
'award_grant_type_description',
'award_grant_date',
'award_grant_date_display_type',
'award_grant_description',
)
labels = {
'award_grant_type': _('Type'),
'award_grant_type_description': _('Type Description'),
'award_grant_date': _('Date'),
'award_grant_date_display_type': _('Date Prompts'),
'award_grant_description': _('Description'),
}
help_texts = {
'award_grant_description': _('5,000 character limit'),
}
input_formats = {
'award_grant_date': settings.DATE_INPUT_FORMATS,
}
widgets = {
#'award_grant_description': CKEditorWidget(),
'award_grant_date': forms.DateInput(attrs={'id': 'id_award_grant_date'}, format='%m/%Y'),
#'award_grant_date': forms.DateInput(attrs={'id': 'id_award_grant_date'}, format=settings.DATE_INPUT_FORMATS),
}
error_messages = {
'award_grant_type': {'validate_min': _('This field is required.')}, # validate_min used on award_grant_type in lieu of required field.
}
EDIT
Here is my views.py code as requested:
#login_required
#resume_menu_required(entry_number=settings.MENU_DETAIL_VALUE_AWARD_GRANT_DETAILS)
#complete_profile_required
def award_grant_details_edit(request, award_grant_details_id):
try:
award_grant_details = AwardGrantDetails.objects.get(pk=award_grant_details_id, user=request.user)
except AwardGrantDetails.DoesNotExist:
return redirect(settings.MENU_DETAIL_LINK_AWARD_GRANT_DETAILS)
language_versions = LanguageVersion.objects.filter(user=request.user).select_related('language_version')
available_languages = get_available_language_details(language_versions, request.user.userprofile.language_preference)
award_grant_details_num = request.user.awardgrantdetails_set.count()
language_code = award_grant_details.language_version.language_code
language_code_disabled = award_grant_details.language_version.language_code_disabled
preview_labels = get_award_grant_types(available_languages)
selected_resume_menu_entries = (request.user.userprofile.selected_resume_menu_entries)
if language_code_disabled:
return redirect(settings.MENU_DETAIL_LINK_AWARD_GRANT_DETAILS)
if request.method == 'GET':
language_code = award_grant_details.language_version.language_code
form = AwardGrantDetailsForm(
available_languages=available_languages,
language_preference=request.user.userprofile.language_preference,
initial=dict(model_to_dict(award_grant_details), language_code=language_code))
elif request.method == 'POST':
form = AwardGrantDetailsForm(
available_languages=available_languages,
language_preference=request.user.userprofile.language_preference,
data=request.POST)
if form.is_valid():
award_grant_details.fill(form.cleaned_data)
award_grant_details.save()
messages.success(request, _('successfully updated.'))
return redirect(settings.MENU_DETAIL_LINK_AWARD_GRANT_DETAILS)
return render(request,'resume_details/award_grant_details_edit.html',{
'address_details_count': get_address_details_count(request.user),
'award_grant_details': award_grant_details,
'award_grant_details_num': award_grant_details_num,
'contact_details_count': get_contact_details_count(request.user),
'display_default_language': display_default_language(request.user),
'form': form,
'language_versions': get_language_versions(user=request.user),
'language_versions_num': len(language_versions), # the count of all users Language Versions (enabled & disabled).
'languages': LANGUAGES,
'max_award_grant_details': settings.MAX_AWARD_GRANT_DETAILS,
'max_details_count': settings.MAX_AWARD_GRANT_DETAILS,
'name_details_count': get_name_details_count(request.user),
'preview_labels': preview_labels,
'resume_details_menu_link': settings.MENU_DETAIL_LINK_AWARD_GRANT_DETAILS,
'resume_details_menu_num': settings.MENU_DETAIL_VALUE_AWARD_GRANT_DETAILS,
'selected_resume_menu_entries': selected_resume_menu_entries,
})

I never discovered the answer to this issue.
However, a workaround is that on form submit when 8888 or 9999 is selected and there are no errors, I manually set the value to 1 using jquery:
$('#id_of_element_type').val('1');
I hope that this will assist someone.

Related

i am making a django website with multiple forms also used foregin key ValueEror :The view Capp.views.InsertProduct didn't return anHttpResponseobject

i am making a django website with multiple forms also used foregin key(user_id) to link one form with other in the database but at the last i get value error the error is:Exception Type: ValueError
Exception Value:
The view Capp.views.InsertProduct didn't return an HttpResponse object. It returned None insteated ,
the following is view.py file code(not complete code but only where error can lie)models.py part
def InsertProduct(request):
if request.method == 'POST':
if request.POST.get('user_id') and request.POST.get('pname') and request.POST.get('pcategory') and request.POST.get('pdetails') and request.POST.get('foundedin') and request.POST.get('orderoftest') and request.POST.get('t1') and request.POST.get('t2') and request.POST.get('t3') and request.POST.get('f1') and request.POST.get('f2') and request.POST.get('f3') and request.POST.get('f4') and request.POST.get('f5'):
saveproduct = ProInsert()
saveproduct.user_id = request.POST.get('user_id')
saveproduct.pname = request.POST.get('pname')
saveproduct.pcategory = request.POST.get('pcategory')
saveproduct.pdetails = request.POST.get('pdetails')
saveproduct.foundedin = request.POST.get('foundedin')
saveproduct.orderoftest = request.POST.get('orderoftest')
saveproduct.t1 = request.POST.get('t1')
saveproduct.t2 = request.POST.get('t2')
saveproduct.t3 = request.POST.get('t3')
saveproduct.f1 = request.POST.get('f1')
saveproduct.f2 = request.POST.get('f2')
saveproduct.f3 = request.POST.get('f3')
saveproduct.f4 = request.POST.get('f4')
saveproduct.f5 = request.POST.get('f5')
checkpname = ProInsert.objects.filter(
pname=saveproduct.pname).first()
return render(request, 'product_details.html')#here I had add what u said sir
if checkpname:
msgpname = messages.success(request, 'The user with Product Name ' +
request.POST['pname']+' already exist...!')
return render(request, 'product_details.html', {'msgpname': msgpname})
saveproduct.save()
messages.success(request, 'Product Added..!')
return render(request, 'product_details.html')
else:
return render(request, 'product_details.html')
I think you got it wrong I have update your code and commented the part i was telling you.
def InsertProduct(request):
if request.method == 'POST':
if request.POST.get('user_id') and request.POST.get('pname') and request.POST.get('pcategory') and request.POST.get('pdetails') and request.POST.get('foundedin') and request.POST.get('orderoftest') and request.POST.get('t1') and request.POST.get('t2') and request.POST.get('t3') and request.POST.get('f1') and request.POST.get('f2') and request.POST.get('f3') and request.POST.get('f4') and request.POST.get('f5'):
saveproduct = ProInsert()
saveproduct.user_id = request.POST.get('user_id')
saveproduct.pname = request.POST.get('pname')
saveproduct.pcategory = request.POST.get('pcategory')
saveproduct.pdetails = request.POST.get('pdetails')
saveproduct.foundedin = request.POST.get('foundedin')
saveproduct.orderoftest = request.POST.get('orderoftest')
saveproduct.t1 = request.POST.get('t1')
saveproduct.t2 = request.POST.get('t2')
saveproduct.t3 = request.POST.get('t3')
saveproduct.f1 = request.POST.get('f1')
saveproduct.f2 = request.POST.get('f2')
saveproduct.f3 = request.POST.get('f3')
saveproduct.f4 = request.POST.get('f4')
saveproduct.f5 = request.POST.get('f5')
checkpname = ProInsert.objects.filter(
pname=saveproduct.pname).first()
# return render(request, 'product_details.html')# NO need to add here as code below will be dead in this case.
if checkpname:
msgpname = messages.success(request, 'The user with Product Name ' +
request.POST['pname']+' already exist...!')
return render(request, 'product_details.html', {'msgpname': msgpname})
saveproduct.save()
messages.success(request, 'Product Added..!')
return render(request, 'product_details.html')
else:
return render(request, 'product_details.html')# What i meant was to add it here
else:
return render(request, 'product_details.html')

Django: Refactoring the "right" way

My DetailView currently gets longer and longer. And therefore I am trying to learn more about some better practices to shorten it again. Right now, I am looking into the def post() part. The full code is even longer. My best idea currently is to create a utils.py in the same folder and take out the code snippets inside the if else statements. Is that best practice or would you do it in a different way?
class EventDetail(DetailView):
[...]
#transaction.atomic
def post(self, request, *args, **kwargs):
# Discount code POST
if self.discount_form.is_valid():
discount_code = self.discount_form.cleaned_data['code']
request.session[discount_cookie_name(request.event)] = discount_code
return redirect(reverse_obj(self.request.event, 'events:detail'))
# Consent form POST
elif self.consent_form.is_valid():
# Check if email entry exists
contact = request.event.organizer.contacts.filter(
email=self.consent_form.cleaned_data['email']
).first()
success_message = _("You successfully signed up to receive event updates.")
if contact:
# Check if current event is allocated to entered email.
event_entry = contact.contact_relation.filter(
event=request.event
).first()
if event_entry:
event_entry.lead = True
event_entry.save(update_fields=['lead'])
messages.success(request, success_message)
else:
# Email entry exists, but event allocation must be added.
ContactRelation.objects.create(
lead=True, contact=contact, event=request.event
)
messages.success(request, success_message)
# Create new email entry and allocate event.
else:
instance = self.consent_form.save(commit=False)
instance.organizer = request.event.organizer
instance.save()
instance.contact_relations.add(
request.event, through_defaults={'lead': True}
)
messages.success(request, success_message)
return redirect(reverse_obj(self.request.event, 'events:detail'))
elif self.formset.is_valid():
# Check if the user already has an order_reference in the session
old_order_reference = request.session.get('order_reference')
if old_order_reference is not None:
ReservedItem.objects.filter(
order_reference=old_order_reference
).delete()
# Generate a new order_reference and save it in the session
order_reference = unique_order_reference_generator()
request.session['order_reference'] = order_reference
for form in self.formset:
quantity = form.cleaned_data['quantity']
qty = 0 if not quantity else quantity
if qty > 0:
reserved_item = form.save(commit=False)
ticket = form.cleaned_data['ticket']
reserved_item.order_reference = order_reference
reserved_item.ticket_name = ticket.name
if ticket.tax:
reserved_item.ticket_tax = ticket.tax
reserved_item.tax_name = ticket.tax.name
reserved_item.tax_percentage = ticket.tax.percentage
# Prevent AttributeError
discount_obj = None
if self.discount_code:
discount_obj = self.discount_code
if self.social_ticketing_referral:
# That part is not inside generate_reserved_discount_items
# as the influencer is still getting points. Even, if the ticket
# has no discount.
reserved_item.social_ticketing_referral = (
self.social_ticketing_referral.ambassador
)
# Add points earned per ticket
reserved_item.social_ticketing_unit_points_earned = (
ticket.points.points
if self.social_ticketing.is_point_mode_manual()
else monetary_amount_to_points(
ticket.price_gross, request.event.currency
)
)
# Check if Social Ticketing has incentive discount (not talking point).
# That also means self.discount_code doesn't apply
if self.social_ticketing.is_incentive_discount():
discount_obj = self.social_ticketing.discount
reserved_item.discount_code = (
self.social_ticketing_referral.code
)
if discount_obj:
generate_reserved_discount_items(
reserved_item=reserved_item,
discount=discount_obj,
ticket=ticket,
quantity=quantity,
)
# Save reserved item
reserved_item.save()
return redirect('checkout:checkout', step='start')
return super().get(request, *args, **kwargs)

How to display image on web page based on selected value from select field without reloading page

I am trying to figure out how to display an image on the webform page when a certain option is selected from the select field. And then getting the image to change when a different option is selected. The url image link is stored in the Sqlite3 database with the respective select field options. I am having trouble putting this all together and was wondering if someone may be able to help. Here is some code that may make things easier to understand.
The select field I am focusing on is the Host field and the extra part of the Host class is where the URL image link is stored.
class LoginForm(FlaskForm):
host = SelectField('Host Solution Required', choices = [], validators= .
[validators.InputRequired('Please select a Board')])
#app.route('/', methods=['GET', 'POST'])
def form():
form = LoginForm()
form.device.choices = [(device.id, device.name) for device in
Device.query.filter_by(cat=None).all()]
form.host.choices= [(host.id, host.name) for host in Host.query.all()]
#if form.validate_on_submit(): To use this I will have to figure out how
to validate the choices for device
if request.method =='POST':
device = Device.query.filter_by(id=form.device.data).first()
host = Host.query.filter_by(id= form.host.data).first()
#This code takes care of changing the format of the ordering link
that is put into bugzilla.
if host.name =='None' and form.cat.data == 'None':
return '<h1> You did not order anything, please go back and fill
out cat or host</h2>'
elif host.name == 'None':
return '<h1> ({} x {}) for {}</h1>'.format(form.number.data,
device.name, form.team.data)
elif form.cat.data == 'None':
return '<h1> ({} x {}-{}) for {} .
</h1>'.format(form.quantity.data, host.name, form.finish.data,
form.team.data)
else:
return '<h1> ({} x {}-{}) AND ({} x {}) for {} .
</h1>'.format(form.quantity.data, host.name, form.finish.data,
form.number.data, device.name, form.team.data)
return render_template('form.html', form=form, street = host.extra)
class Host(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
customer = db.Column(db.Boolean())
engineering = db.Column(db.Boolean())
extra = db.Column(db.String(400))
#app.route('/host/<name>')
def host(name):
hosts = Host.query.filter_by(name = name).all()
hostArray = []
for host in hosts:
hostObj = {}
hostObj['id'] = host.id
hostObj['name'] = host.name
hostObj['extra'] = host.extra
hostArray.append(hostObj)
return jsonify({'hosts':hostArray})
<br>
{{form.host.label}}
{{form.host}}
<img src={{street}} alt = 'pic' align = 'right' width = '200' height =
'200' />
<script>
var host_select = document.getElementById("host");
host_select.onchange = function() {
name = host_select.extra;
fetch('/host/' + name).then(function(response)){
response.json().then(function(data)){
for(host of data.hosts){
document.getElementById("tweet").src= host.extra;
}
})
});
}*/
</script>
The snippet above does not work, but it is where the image is being shown in the HTML.
Please let me know if I can clarify anything further.

Formset.is_valid() False, why?

I'm trying to validate a form set, it shows in the template perfectly but when I try to save it, its validation returns False.
I tried to put some errors callbacks and the error in print(formset.non_form_errors) say the following:
<bound method PhysicianSpecialtiesFormFormSet.non_form_errors of <django.forms.formsets.PhysicianSpecialtiesFormFormSet object at 0x7fd70af38a10>>
I don't know what to do to have a correct input in the form; the form is a dropdown list, and it's impossible to get wrong.
def UpdatePhysician(request,id):
physician = get_object_or_404(Physician, id=id)
employee = get_object_or_404(Employee, id=physician.employee.id)
person = get_object_or_404(Person, id=employee.person.id)
try:
address = get_object_or_404(Address, id=return_id(str(person.addresses.values('id'))))
except:
address = None
try:
email = get_object_or_404(Email, id=return_id(str(person.emails.values('id'))))
except:
email = None
try:
phone = get_object_or_404(PhoneNumber, id=return_id(str(person.phone_numbers.values('id'))))
except:
phone = None
try:
academic_degree = get_object_or_404(AcademicDegree, id=return_id(str(employee.academic_degrees.values('id'))))
university = get_object_or_404(University, id=return_id(str(employee.academic_degrees.values('university'))))
except:
academic_degree = None
university = None
physician_specialties = get_list_or_404(PhysicianSpecialties, employee_academic_degree__employee__pk=physician.employee.id)
for item in physician_specialties:
print(unicode(item.specialty))
specialties = Specialty.objects.all()
specialty = PhysicianSpecialties.objects.filter(employee_academic_degree__employee__physician__pk=id)
SpecialtyFormset = modelformset_factory(PhysicianSpecialties, fields=('specialty',),max_num=1, labels=None, )
formset = SpecialtyFormset(queryset=PhysicianSpecialties.objects.filter(employee_academic_degree__employee__pk=physician.employee.id))
person_form = PersonForm(request.POST or None, instance=person)
employee_form = EmployeeForm(request.POST or None, instance=employee)
physician_form = PhysicianForm(request.POST or None, instance=physician)
email_form = EmailForm(request.POST or None, instance=email)
address_form = AddressForm(request.POST or None, instance=address)
phone_form = PhoneForm(request.POST or None, instance=phone)
academic_degree_form = AcademicDegreeForm(request.POST or None, instance= academic_degree)
university_form = UniversityForm(request.POST or None, instance=university)
if request.method == "POST":
if (person_form.is_valid() and employee_form.is_valid() and physician_form.is_valid() and email_form.is_valid() and
address_form.is_valid() and phone_form.is_valid and physician_form.is_valid() and university_form.is_valid and
academic_degree_form.is_valid() and formset.is_valid()):
person_form.save()
physician_form.save()
new_address = address_form.save()
new_email = email_form.save()
new_phone = phone_form.save()
# academic_degree_form.save()
# university_form.save()
formset.save()
if address == None:
PersonAddress.objects.create(person=person, address=new_address)
if email == None:
PersonEmail.object.create(person=person, email=new_email)
if phone == None:
PersonPhoneNumber.objects.create(person=person, hone_number=new_phone)
return HttpResponse('yesh')
else:
print(formset.is_valid())
print(formset.non_form_errors)
print('nope')
return HttpResponse('nope')
You haven't passed data to your formset. Without post data, your formset is unbound and will always be invalid.
formset = SpecialtyFormset(request.POST or None, queryset=PhysicianSpecialties.objects.filter(employee_academic_degree__employee__pk=physician.employee.id))
Another problem is that you are trying to display the errors incorrectly. formset.non_form_errors is a method, you have to call it.
print(formset.non_form_errors())
There may also be errors attached to the forms in the formset, you can see these by printing formset.errors.
print(formset.errors)

How can I disconnect a django signal?

I have a signal in my MessageFolder model which works fine, however in some special ocassions I don't want the post_save signal action to occur. How can I deactivate it in this case?
I have tried the following but it's not workign.
Views.py
signals.post_save.disconnect(receiver=MessageFolder,sender=Message)
email_message = EmailMessage(
subject,
message,
my_username,
[recipent,],
[], # ['bcc#example.com'],
headers = {'Reply-To': 'gusreyes01#example.com'}
)
signals.post_save.connect(MessageFolder,MessageFolder.assign_message_folder)
# Save it
my_mailbox.record_outgoing_message(
email_message.message()
)
Models.py
class MessageFolder(models.Model):
folder = models.ForeignKey(Folder, null = True, blank = True)
message = models.ForeignKey(Message, null = True, blank = True)
#receiver((post_save), sender=Message, dispatch_uid="assign_message_folder")
def assign_message_folder(sender, instance, created, **kwargs):
if not created:
return
else:
# generate MessageFolder && UserFolder
if(instance.outgoing):
message_folder = MessageFolder(None, 2, instance.pk)
else:
message_folder = MessageFolder(None, 1, instance.pk)
message_folder.save()
return
I've used the following and it works for me
Disconnect:
signals.post_save.disconnect(assign_message_folder, sender=MessageFolder)
Connect:
signals.post_save.connect(assign_message_folder, sender=MessageFolder)

Categories