Django/Python: views.py and passing strings of text - html

So in my template, I have the following code:
<span class="state-txt">{{ state }}</span>
In my views.py, it's handled with the following if/else loop:
if user is not None:
if user.is_active:
login(request, user)
state = "You're successfully logged in!"
return render_to_response('uc/portal/index.html', {'state':state, 'username':username}, context_instance=RequestContext(request))
else:
state = "Your account is not active, please contact UC admin."
else:
state = "Your username and/or password were incorrect."
Essentially, it's working fine at the moment but I want each state to be able to contain different <img> tags, but when I just type state = "<img src="some.jpg"> Your username and/or password were incorrect." The html doesn't render correctly. Is there some way to do what I'm trying to do in Django, or am I barking up the wrong tree?

I would just pass the image URL in the context from the view, and consume that in the template. Something like this:
if user:
if user.is_active:
login(request, user)
state = "You're successfully logged in!"
state_img = success_image_url
return render_to_response('uc/portal/index.html',
{'state': state,
'state_img': state_img,
'username':username
}, context_instance=RequestContext(request))
else:
state_img = inactive_image_url
state = "Your account is not active, please contact UC admin."
else:
state_img = invalid_credentials_url
state = "Your username and/or password were incorrect."
and in the template
<span class="state-txt">
<img src="{{state_img}}" />{{ state }}
</span>

For completeness' sake, as karthikr already posted an excellent solution:
The reason the html doesn't render correctly, is because the Django template language automatically assumes that all output by {{ ... }} is not safe, all symbols that have a special meaning in HTML will be escaped (< becomes < etc.).
To render a string as pure HTML code, use the safe filter.
views.py:
state = "<img src="some.jpg" /> Your username and/or password were incorrect."
index.html:
<span class="state-txt">{{ state|safe }}</span>

Don't render the image. try if else
view.py
if user is not None:
if user.is_active:
login(request, user)
state = True
return render_to_response('uc/portal/index.html', {'state':state, 'username':username}, context_instance=RequestContext(request))
else:
state = False
else:
state = False
in template
{%if state %}
<img></img>
you are successfully logged in.
{%endif%}

Related

How to get value attribute in views

Hello is there a way to get 'value' attribute from HTML template into views.py and use it there??
HTML:
<form class="card__delete" method="POST"> {% csrf_token %}
<button value="{{item.id}}" class="card__delete__button" name="delete" type="submit">&#10008</button>
</form>
views.py
class TodoView(UserPassesTestMixin, CreateView):
model = Item
template_name = 'home/todo.html'
form_class = ItemCreationForm
def test_func(self):
return self.request.user.username in self.request.path
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['card'] = Card.objects.get(user=self.request.user, pk=self.kwargs.get('pk'))
return context
def post(self, request, pk, username):
if 'delete' in self.request.POST:
Item.objects.get(id=pk).delete()
print('deleted')
return redirect('home-page')
The value is in request.POST, so you should be able to access it with
value = self.request.POST.get('delete', None)
Take care to validate that value before using the id of an object to do anything catastrophic to it (such as .delete()). It's not being validated through a form, and a random hacker on the internet might try posting back random numbers which might be the id of other objects
Added after reading comment:
Data pulled out of request.POST is raw data. I don't think CSRF token can protect against a person who uses inspect object in his browser and changes the value of that button before clicking it. I may be wrong.
Anyway, if you can check the value using a queryset of the object type with a filter for objects that this user is permitted to delete, then do. For example,
value = request.POST.get("delete", None)
if value:
obj = Card.objects.filter(
user=self.request.user ).get( pk=value)
# will raise CardDoesNotExist if value isn't one of user's objects,
# because it's been filtered out
obj.delete()

Can't call model to Django template

I'm trying to call an attribute from my model into my HTML template using Django. There is something strange going on as I am only able to call one of my two models into the template. Both models are working perfectly fine as far as I can tell by looking into my database. This is what my models.py looks like
class Respondez(models.Model):
responder = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='scores')
score = models.IntegerField(default=0)
post_time = models.DateTimeField(default=timezone.now)
class Meta:
ordering = ['post_time']
def __str__(self):
return self.score
class Profilez(models.Model):
newuser = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True,null=True)
preference = models.CharField(max_length=30)
def __str__(self):
return self.newuser
I am trying to call Profilez. However, only Respondez can be called. This is the view I'm calling from, which I simplified.
#login_required
def add(request):
p = Profilez()
z = Respondez()
context = {
'p' : p,
'z' : z
}
return render(request, 'rating/add.html', context)
To test whether I can call my models, I have simple header tags in HTML for my template, add.html:
{% extends "rating/base.html" %}
{% block content%}
<h3> {{user.username}} </h3>
<h3> {{ z.post_time }}</h3>
<h3>{{ p.preference }}</h3>
No matter which attribute I call from the models, the line for Respondez works but nothing works for my Profilez model. This is despite the fact that my database has values saved for each attribute from both models.
I am getting inputs for preference from the following view on a separate template (first line won't paste with correct indentation), where users select 1 of 2 choices:
def onboarding2(request):
p = Prof()
p.newuser = request.user
if request.method == 'POST':
selected_opt = (request.POST['ob'])
if selected_opt == 'mood':
p.preference = 'mood'
elif selected_opt == 'productivity':
p.preference = 'productivity'
else:
return HttpResponse(400, 'Invalid form')
p.save()
return redirect('rating-onboarding3')
context = {
'p' : p,
}
return render(request, 'rating/onboard2.html', context)
How can I accurately call my Profilez model? What's wrong here?
Since you have instantiated Profilez with no parameters in the constructor, none of its fields get the initial value. Hence, p.preference also happens to be null. That is why p.preference is not visible in the template.
But, in case of Respondez, though you are still instantiating the object with no parameters, you still have given the default value of current time to z.post_time, so z.post_time is working.
If you want to access p.preference, you need to explicitly assign some value to p.preference, else how will the template show the value for something that doesn't have a value initialized in the first place? For instance, you could do p = Profilez(preference='xyz') while creating the object, and see what happens.
Also, if you want to fetch a specific entry from the database, then you need to do a query, rather than creating a new object. The syntax for creating query would be something like Profilez.objects.get(newuser=some_random_user).

Validation erorr raise for the form that validates its value from another model

I am trying to raise validation error for the entry field in the forms.py
My models.py
class StudBackground(models.Model):
stud_name=models.CharField(max_length=200)
class Student(models.Model):
name=models.CharField(max_length=200)
My forms.py
class StudentForm(forms.ModelForm):
name = forms.CharField(max_length=150, label='',widget= forms.TextInput)
class Meta:
model = Student
fields = ['name',]
where i tried to apply clean method :
def clean_student(self,*args,**kwargs):
name=self.cleaned_data.get("name")
if not studBackground.stud_name in name:
raise forms.ValidationError ( "It is a not valid student")
else: return name
I tried to incorporate stud_name from the StudBackground model to the form but it does not work it raises following error when i try to type student name that is not in DB:
Profiles matching query does not exist
however it supposed to return near the name field "It is a not valid student"
How to make it work? What is the wrong with the code?
You can try like this:
def clean_student(self):
name=self.cleaned_data.get("name")
if not StudBackground.objects.filter(stud_name=name).exists():
raise forms.ValidationError("It is a not valid student")
return name
I am using filter(...) function from queryset to check if a name exists in StudBackground. I am also running exists() to check if entry exists in DB.
Update
I think your indentations are not correct for the view. But, you can try like this:
def home(request):
form = StudentForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
instance = form.save()
name = instance.name
class_background=StudBackground.objects.get(stud_name=name)
context={'back':class_background}
return render(request, 'class10/background.html', context)
# Now let us handle if request type is GET or the form is not validated for some reason
# Sending the form instance to template where student form is rendered. If form is not validated, then form.errors should render the errors.
# How to show form error: https://docs.djangoproject.com/en/3.0/topics/forms/#rendering-form-error-messages
return render(request, 'your_student_form_template.html', context={'form':form})

django admin send email to user

\admin.py
#admin.register(ParentsProfile)
class ParentsProfile(admin.ModelAdmin):
list_display = ('Father_Email','Fathers_Firstname' , 'Fathers_Middle_Initial', 'Fathers_Lastname', 'Request')
ordering = ('Request',)
search_fields = ('Request',)
actions = ['Send_Email','Send_Email_Disapproved']
def Send_Email(self, request, queryset):
html_content = "Your Registration has been approved.\n\nPlease use this %s as your username and %s as your password. \nYou may now start enrolling your student using this link https://...../Plogin_form/ \n\n\n REGISTRAR "
for profile in queryset:
send_mail(subject="Invite", message=html_content %(profile.Father_Email,profile.Parent_Password), from_email=settings.EMAIL_HOST_USER,
recipient_list=[profile.Father_Email]) # use your email function here
def Send_Email_Disapproved(self, request, queryset):
# the below can be modified according to your application.
# queryset will hold the instances of your model
for profile in queryset:
send_mail(subject="Invite", message="Our Apology,\n\n Your Registration has been Disapproved " + profile.Father_Email + "\n\n\n REGISTRAR" + "", from_email=settings.EMAIL_HOST_USER,
recipient_list=[profile.Father_Email])
i have this code to send an email to user, how do i convert my html_content into HTML? so that i can design my message to user?
it send to user gmail like this,
You can render it with django.template.loader.render_to_string
You first need to store your template in your template folder, for example:
<!-- your_app/templates/my_template.html -->
<h1>hello, {{ user.first_name }}</h1>
Then in your code, change the html_content to
html_content = render_to_string('my_template.html', {
'user': User.objects.get(username="some_username")
})
Doc: https://docs.djangoproject.com/en/2.2/topics/templates/#django.template.loader.render_to_string

Rebuilding Links with Django

I have created a Django app with the URL structure:
eventdetails/?event_id=94099
This would take me to the index page of the event details app. However My app has sections, and each section needs the event_id to use.
Therefore I need a url structure like:
eventdetails/who/?event_id=94099
So I can still access the event ID.
Could anyone advise me how to create the links for the navigation or a better way of doing this.
Thanks,
django's URL maps do not take into account the query string, which is passed as is to any view that is mapped.
In practical terms, this means that if you have:
url(r'^eventdetails/who/$', 'event_who', name='e-who'),
url(r'^eventdetails/$', 'event_detail', name='e-detail')
Then both your view methods will have access to the query string:
def event_detail(request):
id = request.GET.get('event_id')
def event_who(request):
id = request.GET.get('event_id')
if not id:
print 'No ID!'
else:
print 'do stuff'
return render(request, 'who.html')
You can also add the event id as part of the url itself, for example eventdetails/94099/:
url(r'^eventdetails/(?P<id>\d+)/$', 'event_detail', name='e-detail')
Then your views will be:
def event_detail(request, id=None):
if not id:
print 'No ID!'
else:
print 'do stuff'
return render(request, 'detail.html')
The other benefit you get is that you can easily generate URLs for your events in your templates and views:
<ul>
{% for event in events %}
<li> {{ event.name }}</li>
{% endfor %}
</ul>
In your view:
def go_to_event(request, id):
return redirect('e-detail', id=id)