I want to display in an email template some conditional informations but even if the {{ error }} confirms the value of my error is list index out of range , the condition is not applied and else is taken in account.
I send to my (email) template this:
views.py
try:
[...]
except Exception as e:
error_product_import_alert(
{'order_increment_id': order_increment_id, 'product': item['sku'],
'error': e, 'request': request})
error_product_import_alert()
def error_product_import_alert(context):
product = context['product']
order_id = context['order_increment_id']
error = context['error']
sujet = f' Anomalie : Import SKU {product} ({order_id}) impossible
({error})!'
contenu = render_to_string('gsm2/alerts/product_import_ko.html', context)
[...]
email template
<p>--{{ error }}--</p>
{% if error == 'list index out of range' %}
<p><strong>Le produit est introuvable dans la base.</strong></p>
{% else %}
<p><strong>Erreur inconnue : veuillez contacter l'administrateur.</strong></p>
{% endif %}
Maybe my error is so big that I even can't see it.
Is there one ?
You are comparing an Exception to a string. This would not work in templates. Try doing the logic in your python function itself and return the error string that will be rendered in the template.
For example:
You should try:
views.py
try:
[...]
except Exception as e:
error = "Erreur inconnue : veuillez contacter l'administrateur."
if e.args[0] == 'list index out of range':
error = "Le produit est introuvable dans la base."
error_product_import_alert({
'order_increment_id': order_increment_id,
'product': item['sku'],
'error': error,
'request': request
})
template
<p><strong>{{error}}</strong></p>
Related
I want to request id differ in every page data, same as request id is in available in approve_url .
index function send session variable approve_url in test function.
Here is index function
global j, k, approve_url
#api_view(['POST', 'GET'])
def index(request):
# j = ''
# approve_url = ''
if request.method == "POST":
form = InputForm(request.POST)
if form.is_valid():
form.save()
try:
ids = form.cleaned_data['git_Id']
print(ids)
obj = sql()
query = f""" SELECT request_id FROM request_form_db.request_form_mymodel
where git_Id= '{ids}' ;
"""
print(query)
p = obj.fetch_query(query)
print("Query Result", p)
for i in p:
print("Result[0] : ", i[0])
print("Result : ", p)
i = i[0]
j = i
approve_url = f"http://127.0.0.1:8000/form/test?request_id={i}"
print("Url : ", approve_url)
try:
send_mail(
'KSA Test Activation',
approve_url,
'Noreplygcontrol#airlinq.com',
['sorav.parmar#airlinq.com'],
fail_silently=False,
)
except Exception as e:
print("Error : ", e)
except Exception as e:
print("Error : ", e)
request.session['ids'] = ids
request.session['approve_url'] = approve_url
print('Request ID Sent : ', ids)
print('Approve Url Sent : ', approve_url)
form = InputForm()
else:
form = InputForm()
return render(request, 'home.html', {'form': form})
Here is test function where approve_url getting from session variable and put into UI, but res value change in previous data as well.Its not same as request_id in approve_url.
the latest request id is overwrite in previous as well.
#api_view(['GET', 'POST'])
def test(request):
ids = request.session.get('ids')
print("Git ID from Index View : ", ids)
if 'approve_url' in request.session:
s = request.session['approve_url']
print(s)
res = s.split('=')[1]
print(res)
if request.method == "POST":
form = TestForm(request.POST)
url = s
url_req = url.split('=')[1]
# rq = request_id["request_id"]
s = sql()
query = f"""update request_form_db.request_form_mymodel
set is_approved=1
where request_id = '{url_req}' """
print(query)
s.update_query(query)
print("Updated Successfully")
form = TestForm()
else:
form = TestForm()
context = {'form': form, 'res': res, }
return render(request, 'test.html', context)
Here is test.html code where value of res
<form action ="{% url 'test' %}" method="POST">
<div class="form_data">
{% csrf_token %}
<br><br>
{{form.myfield}}
<br><br>
<label><b>Request Id</b></label> {{res}}<br>
<input type="submit" value="Submit" class="btn btn-success" />
Below both screenshots of request id overwrites in previous data, I want to different request id is setting on different approve_url.
latest url code
previous data that request id is overwrite
my django app acts as an emailing service, emails that are sent are view-able and it's possible to send html emails. How do I display the html emails on the view-mail page rather than just displaying the name of the file ? (the following is the mail-view for an html email):
How would I display the actual html in the body of this page?
This is my views.py:
def outbox(request):
#Mail_Item.objects.all().delete()
if request.method == "POST" and request.POST.get('Username', False)!=False:
username = request.POST.get('Username')
password = request.POST.get('Password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user, backend='django.contrib.auth.backends.ModelBackend')
print(username + " has logged in")
messages = Mail_Item.objects.filter(user=request.user.username)
args = {'messages':messages}
return render(request, 'outbox.html', args)
else:
return render(request, '404.html')
elif request.POST.get('Username', False) == False and request.POST.get('mail_body_field', False) == False:
pass
elif request.method == "POST" and request.POST.get('mail_subject_field')!=False:
subject = request.POST.get('mail_subject_field')
body = request.POST['mail_body_field']
file = ""
try:
file = request.FILES['filename']
except:
pass
print("sending mail:")
for i in range(1, len(Res)+1):
y = Res['ID' + str(i)].email
print("sent to " + y )
msg = EmailMessage(subject, body, 'email#example.com', [y])
msg.content_subtype = "html"
if (str(file)) != "" and (str(file))[-4:] != 'html':
msg.attach_file(str(file))
obj = Mail_Item(subject=subject, body=body, user=request.user.username, file_name=(str(file)))
obj.save()
print("email stored in database")
elif (str(file)) != "" and (str(file))[-4:] == 'html' :
uploaded_file = file
fs = FileSystemStorage()
fs.save((str(file)), uploaded_file)
html_message = render_to_string((str(file)), {'context': 'values'})
plain_message = strip_tags(html_message)
from_email = 'From <email2#example.com>'
mail.send_mail(subject, plain_message, from_email, [y], html_message=html_message)
obj = Mail_Item(subject=subject, body=body, user=request.user.username, file_name=(str(file)))
obj.save()
else:
obj = Mail_Item(subject=subject, body=body, user=request.user.username, file_name='None')
obj.save()
print("email stored in database")
#msg.send()
i += 1
messages = Mail_Item.objects.filter(user=request.user.username)
args = {'messages':messages}
return HttpResponseRedirect('../templates/outbox.html', args, request)
else:
print("pleeeeeaassee")
return render(request, '404.html')
messages = Mail_Item.objects.filter(user=request.user.username)
args = {'messages':messages}
return render(request, 'outbox.html', args)
def login_page(request):
if request.method == "POST":
username = request.POST['sign-up-name']
email = request.POST['sign-up-email']
password = request.POST['sign-up-password']
user = User.objects.create_user(username, email, password)
user.save()
print(username + " has been added to the user database.")
else:
pass
return render(request, 'login.html')
def signup_page(request):
return render(request, 'signup.html')
def mail_view(request, id=None):
if id:
email = Mail_Item.objects.get(id=id)
args = {'email':email}
else:
pass
return render(request, 'mail-view.html', args)
def log_out(request):
logout(request)
return render(request, 'log-out.html')
def delete(request):
Mail_Item.objects.filter(id=id).delete()
messages = Mail_Item.objects.filter(user=request.user.username)
args = {'messages':messages}
return render(request, 'outbox.html', args)
This is the code for my mail-view template where I'd like to place the html that is being sent:
<div class="mail-view">
<h4 class="m-0">{{ email.subject }}</h4>
<div class="divid"></div>
<div class="media">
<div class="media-left">
<div class="avatar avatar-lg avatar-circle">
<img class="img-responsive" src="{% static '../static/assets/images/221.jpg' %}" alt="avatar"/>
</div><!-- .avatar -->
</div>
<div class="media-body">
<div class="m-b-sm">
<h4 class="m-0 inline-block m-r-lg">
Access Bank
</h4>
</div>
<p><b>Attachment: </b>{{ email.file_name }}</p>
</div>
</div>
<div class="divid"></div>
<div class="row">
<div class="col-md-12">
<div class="m-h-lg lh-xl">
<p>{{ email.body }}</p>
</div>
</div>
</div>
</div>
Models.py:
from django.db import models
class Details(models.Model):
email = models.CharField(max_length=200)
def __str__(self):
return self.email
class Mail_Item(models.Model):
subject = models.CharField(max_length=200)
body = models.CharField(max_length=300)
time = models.DateTimeField(auto_now=True)
user = models.CharField(max_length=15)
file_name = models.CharField(max_length=100, null=True, default=None)
def __str__(self):
template = '{0.subject} {0.body} {0.time} {0.user} {0.file_name}'
return template.format(self)
I need your help in order to know How I can actualize my Django template from get_context_data.
I have this class in my view :
class IdentitySocieteResumeView(LoginRequiredMixin,TemplateView) :
template_name = 'Identity_Societe_Resume.html'
model = Societe
def get_context_data(self, **kwargs) :
context_data = super(IdentitySocieteResumeView, self).get_context_data(**kwargs)
id = self.kwargs['id']
societe = get_object_or_404(Societe, pk=id)
obj = Societe.objects.filter(Nom=societe.Nom, SIRET=societe.SIRET, SIREN=societe.SIREN, Ville=societe.Ville)
if obj:
sc_obj = obj[0]
NIU = lib.Individu_Recherche.NIUGeneratorSociete(ModelBase=societe)
societe.NumeroIdentification = NIU
societe.save()
context_data['queryset'] = obj
return context_data
And this important function in lib.Individu_Recherche :
def NIUGeneratorSociete(ModelBase) :
create_year_temp = str(ModelBase.Creation.year)
create_year_temp2 = str(create_year_temp.split(" "))
create_year = create_year_temp2[4] + create_year_temp2[5]
''' A process which let to generate NumeroIdentification '''
NumeroIdentification = force_text('%s-%s%s-%s-%s-%s' % ('E', create_year, create_month, create_city, key, create_country_id))
return NumeroIdentification
Part of my template :
{% block content %}
<div class="title_subtitle_space"></div>
<div class="resume">
{% for societe in queryset %}
Votre société porte le numéro : <b> {{ societe.id}} </b> <p></p>
N° identification attribué : <b>{{societe.NumeroIdentification}}</b> <br></br>
{% endfor %}
{% endblock %}
I'm sure my template is loaded before to execute this function and I get in my template NumeroIdentification = None but in my database this field is well-filled.
My question is : How I can display my variable NumeroIdentification with the good value in my template (value stored in my database) instead of None ?
If I press Cmd + R (MacOS Actualize), NumeroIdentification won't be None but a different value. I would like to get this value in my template the first time.
It's pretty easy with FBV, but with CBV I don't overcome to make it
EDIT :
I add my function NIUGeneratorSociete :
def NIUGeneratorSociete(ModelBase) :
create_year_temp = str(ModelBase.Creation.year)
create_year_temp2 = str(create_year_temp.split(" "))
create_year = create_year_temp2[4] + create_year_temp2[5]
create_month_temp = ModelBase.Creation.month
if len(str(create_month_temp)) == 1 :
create_month = '0' + str(create_month_temp)
else :
create_month = create_month_temp
create_city = Villes[ModelBase.Ville]
key_temp = randint(0,999999)
if len(str(key_temp)) == 1 :
key = '00000' + str(key_temp)
elif len(str(key_temp)) == 2 :
key = '0000' + str(key_temp)
elif len(str(key_temp)) == 3 :
key = '000' + str(key_temp)
elif len(str(key_temp)) == 4 :
key = '00' + str(key_temp)
elif len(str(key_temp)) == 5 :
key = '0' + str(key_temp)
else :
key = key_temp
create_country = ModelBase.Pays
create_country_id = None
if create_country == "CG" :
create_country_id = 1
else :
create_country_id = 2
NumeroIdentification = force_text('%s-%s%s-%s-%s-%s' % ('E', create_year, create_month, create_city, key, create_country_id))
return NumeroIdentification
Unfortunately, this code is all kinds of confused. You're getting the same object in multiple different ways, and updating one copy but expecting the others to reflect the change.
You first get the relevant object as societe. Then for some reason you do another query on that model with all the fields of that object, to get a queryset consisting of one object. Then you do some manipulation of the original object and save it, but don't pass it to the context; instead you pass the queryset.
Your code can be simplified to just this:
def get_context_data(self, **kwargs) :
context_data = super(IdentitySocieteResumeView, self).get_context_data(**kwargs)
id = self.kwargs['id']
societe = get_object_or_404(Societe, pk=id)
NIU = lib.Individu_Recherche.NIUGeneratorSociete(societe)
societe.NumeroIdentification = NIU
societe.save()
context_data['societe'] = societe
return context_data
and the template:
{% block content %}
<div class="title_subtitle_space"></div>
<div class="resume">
Votre société porte le numéro : <b> {{ societe.id}} </b> <p></p>
N° identification attribué : <b>{{societe.NumeroIdentification}}</b> <br></br>
</div>
</div>
{% endblock %}
There are also some strange things going on in your library function. one is that you pass the object as the parameter ModelBase; although it doesn't matter what you call it, ModelBase is a class, but your parameter is an instance of your Societe class. You should call things what they are.
I can't correct that function though as it is clearly incomplete; all of create_month, create_city, key, create_country_id are undefined.
Finally, you should consider if any of this is appropriate. The update function is called from get_context_data in a normal GET request of your page; it would be very surprising for an object to be updated like this on a GET. Really this should be done on a POST only.
Lots of weird things going on here.
After societe = get_object_or_404(Societe, pk=id) you will have a Societe instance (or 404). You then filter Societe to get a list of objects that have the same properties at the instance you already received, and then fetch the first one of those. Why not just obj = get_object_or_404(Societe, pk=id) and skip the rest?
You then mix obj, societe and sc_obj. Your actions on one of them will be lost on the others until you fetch them again, which is probably why this works on refresh. Might be helpful to see your Societe model to confirm though.
I'm looking to add Django messages in my form in order to display success message if my form is validated and error message if my form is not validated (missing field, data type error, ...)
My error message works perfectly well, but I don't overcome to display my success message in the next template when my form is valid.
This is my view :
def BirthCertificate_Form_unique_number(request) :
validity = []
submission = []
#User fill some fields
query_social_number = request.GET.get('social_number')
query_social_number_father = request.GET.get('social_number_father')
query_social_number_mother = request.GET.get('social_number_mother')
success = False
if request.method == 'POST':
form = BirthCertificateForm2(request.POST or None)
if form.is_valid() : # Vérification sur la validité des données
post = form.save()
messages.success(request, 'Le formulaire a été enregistré !')
return HttpResponseRedirect(reverse('BC_treated2', args=(messages,),kwargs={'id': post.id}))
else:
messages.error(request, "Le formulaire est invalide !")
elif request.method == 'GET':
form = BirthCertificateForm2()
parent1 = Person.objects.filter(social_number=query_social_number_father)
parent2 = Person.objects.filter(social_number=query_social_number_mother)
if query_social_number :
if Person.objects.filter(social_number = query_social_number).exists() == True :
individu = get_object_or_404(Person, social_number = query_social_number)
messages.success(request, 'Le numéro unique existe !')
form.fields['fk_parent1'].queryset = parent1
form.fields['fk_parent2'].queryset = parent2
form.fields['lastname'].initial = individu.lastname
form.fields['firstname'].initial = individu.firstname
form.fields['birthday'].initial = individu.birthday
form.fields['birthcity'].initial = individu.birthcity
form.fields['birthcountry'].initial = individu.birthcountry
form.fields['sex'].initial = individu.sex
form.fields['social_number'].initial = individu.social_number
elif Person.objects.filter(social_number = query_social_number).exists() == False :
validity = False
messages.error(request, "Le numéro unique est invalide !")
context = {
"form" : form,
"validity" : validity,
"submission" : submission
}
return render(request, 'BC_form2.html', context)
and in my html template :
{% for message in messages %}
<div class="alert {{ message.tags }} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
{{ message }}
</div>
{% endfor %}
How I could display the success message when my form is valid ?
EDIT :
My urls.py file :
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^BC_accueil$', views.BirthCertificate_Home, name="BChome"),
url(r'^formulaire$', views.BirthCertificate_Form, name = "BCform"),
url(r'^formulaire2$', views.BirthCertificate_Form_unique_number, name = "BCform2"),
url(r'^formulaire_traite/(?P<id>\d+)/$', views.BirthCertificate_Resume, name="BC_treated"),
url(r'^formulaire2_traite/(?P<id>\d+)/$', views.BirthCertificate_Resume_unique_number, name="BC_treated2"),
url(r'^BirthCertificate_PDF/(?P<id>\d+)/$', views.BirthCertificate_PDF, name="PDF"),
url(r'^not_found$', views.BirthCertificate_notfound, name="BCnotfound"),
]
You need to know one thing that, messages will execute only once. Why did you do
args=(messages, )
You can access those messages in BC_treated2 without passing it as args
I'm generating a form from metadata
class MeasureForm(forms.Form):
def __init__(self,*args,**kwargs):
super(MeasureForm,self).__init__()
measure_id = kwargs['measure_id']
m = Measure.objects.get(pk=measure_id);
if (m):
# add the measure identifier as a hidden field
self.fields["measure_id"] = forms.IntegerField(initial = m.id , widget=forms.HiddenInput())
for mp in MeasureParameters.objects.filter(measure = m):
# get the NVL'ed copy of the parameter
p = mp.get_parameter_for_measure()
if not p.is_modifiable:
# the file has a constant value
if (p.values and p.default): # constant must have both values and default index
value_ = p.values[p.values.keys()[p.default-1]];
self.fields[p.name] = forms.IntegerField(
label = p.description ,
initial = value_,
help_text = p.help_text)
self.fields[p.name].widget.attrs['readonly'] = True
else:
raise Exception("Parameter set as unmodifiable but has no value. \
[measure: %s, parameter: %s, measureparameter %s]"
% (m.id , p.id , mp.__unicode__()))
elif (p.values):
# convert hstore dict to list of tuples for the choices to read
values_ = [(v, k) for k, v in p.values.iteritems()];
# set default if exists , else take the first item
default_ = values_[p.default-1][0] if p.default else values_[0][0]
self.fields[p.name] = forms.ChoiceField(
label = p.description ,
choices = values_ ,
initial = default_,
help_text = p.help_text)
else:
self.fields[p.name] = forms.IntegerField(label = p.description, help_text = p.help_text)
if (not p.is_visible):
self.fields[p.name].widget = forms.HiddenInput()
else:
raise Exception ("Could not find measure. [measure %s]" % (m.id))
def clean(self):
return self.cleaned_data;
this is my view
def index(request,measure_id = None):
owners = Owner.objects.all()
form = None
result = None
title = None;
msg = None;
# handle the form
if request.method == 'POST': # the form has been submitted
form = MeasureForm(request.POST, measure_id = request.POST.get('measure_id')) # A form bound to the POST data
result = -100
if form.is_valid(): # All validation rules pass
result = 100
msg = "%s" % repr(form.errors) # list of validation errors
else:
if (measure_id):
title = Measure.objects.get(pk=measure_id).name;
# make an unbound form
form = MeasureForm(measure_id = measure_id)
return render(request, 'calc/index.html' ,
{'owners' : owners,
'form' : form ,
'title' : title ,
'result' : result,
'debug' : msg })
this is a snippet from my template
<div class="content">
{{ form.errors }}
{{ form.non_field_errors }}
{% if form %}
<h2>{{ title }}</h2>
<form action="/calc/{{m.id}}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Calculate" />
</form>
{% if result %}
The Result is <span class="result"> {{ result }} </span>
{% endif %}
</div>
So i get empty braces {} for "%s" % repr(form.errors), form.errors and form.non_field_errors returns nothing. the form posts and I can see the raw data in the request but i keep getting false from is_valid(). why is that ?
EDIT: when checking if the form is bound i also get false. guessing this is the problem. why isn't the form bound after the call for form = MeasureForm(request.POST, measure_id = request.POST.get('measure_id')) ?
** django newbie, Thanks.
Because you're not passing the arguments into the super call. You should do this:
super(MeasureForm,self).__init__(*args, **kwargs)
otherwise the form will never actually be initialised with the POST data.
Edit after comment The answer to that question didn't recommend removing all the arguments from the super call. If you're passing in measure_id you'll simply need to remove it from kwargs beforehand:
def __init__(self, *args, **kwargs):
measure_id = kwargs.pop('measure_id', None)
super(MeasureForm,self).__init__(*args, **kwargs)