Originally I made a script in PHP and because I put html in .php file it was easy to show a message when adding data to database was done.
Now I'd like to do the same in Django. I have simple form, and view that add the data. And when adding is done I want to display some div with information below the "send" button, so I don't want to load any other template. I want to show message in the same template where is my form.
Is it possible to do without ajax? How to do this?
Django has inbuilt messaging support for this type of flash messages.
You can add a success message like this in the view:
messages.success(request, 'Profile details updated.')
In your template, you can render it as follows:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
This is documented in this link:
https://docs.djangoproject.com/en/1.8/ref/contrib/messages/
If you are using class based views, then use the already implemented mixin
from django.contrib.messages.views import SuccessMessageMixin
from django.views.generic.edit import CreateView
from myapp.models import Author
class AuthorCreate(SuccessMessageMixin, CreateView):
model = Author
success_url = '/success/'
success_message = "%(name)s was created successfully"
How about passing a variable to the template ?
(# views.py)
return render(request, "some_app/some_template.html", context={
'sent': True
})
and then somewhere in
(# some_template.html)
{% if sent %}
<div> blah blah</div>
{% endif %}
Edit: fixed typos :/
Here's a basic version using a class based view for a contact page. It shows a success message above the original form.
mywebapp/forms.py
### forms.py
from django import forms
class ContactForm(forms.Form):
contact_name = forms.CharField(label='Your Name', max_length=40, required=True)
contact_email = forms.EmailField(label='Your E-Mail Address', required=True)
content = forms.CharField(label='Message', widget=forms.Textarea, required=True)
mywebapp/views.py
### views.py
from django.contrib.messages.views import SuccessMessageMixin
from django.core.mail import EmailMessage
from django.core.urlresolvers import reverse_lazy
from django.template.loader import get_template
from django.views.generic import TemplateView, FormView
from mywebapp.forms import ContactForm
class ContactView(SuccessMessageMixin, FormView):
form_class = ContactForm
success_url = reverse_lazy('contact')
success_message = "Your message was sent successfully."
template_name = 'contact.html'
def form_valid(self, form):
contact_name = form.cleaned_data['contact_name']
contact_email = form.cleaned_data['contact_email']
form_content = form.cleaned_data['content']
to_recipient = ['Jane Doe <info#example.com>']
from_email = 'John Smith <postmaster#example.com>'
subject = 'Website Contact'
template = get_template('contact_template.txt')
context = {
'contact_name': contact_name,
'contact_email': contact_email,
'form_content': form_content
}
content = template.render(context)
email = EmailMessage(
subject,
content,
from_email,
to_recipient,
reply_to=[contact_name + ' <' +contact_email + '>'],
)
email.send()
return super(ContactView, self).form_valid(form)
templates/contact.html
### templates/contact.html
{% extends 'base.html' %}
{% block title %}Contact{% endblock %}
{% block content %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<form role="form" action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock %}
templates/contact_template.txt
### templates/contact_template.txt
### used to render the body of the email
Contact Name: {{contact_name}}
Email: {{contact_email}}
Content: {{form_content}}
config/urls.py
### config/urls.py
from mywebapp.views import *
urlpatterns = [
url(r'^about/', AboutView.as_view(), name='about'),
url(r'^contact/$', ContactView.as_view(), name='contact'),
url(r'^$', IndexView.as_view()),
]
Related
Hello I have faced an Issue regarding sending email In django rest API.
The Idea is user sends email and Uploads image from serializer part and I want to send same image to users Email. But I am not getting image in email.
here is the code I have been working.
models.py
class Mail(BaseModel):
full_name = models.CharField(max_length=100)
image = models.ImageField(upload_to=mail_image_to)
email = models.EmailField()
below is my serializer
class MailSerializer(serializers.ModelSerializer):
class Meta:
model = Mail
fields = '__all__'
class AddMailSerializer(MailSerializer):
class Meta(MailSerializer.Meta):
fields = (
'full_name',
'image',
'email',
)
views.py
class AddMailView(generics.CreateAPIView):
"""
Use this endpoint to add mail
"""
serializer_class = serializers.AddMailSerializer
def perform_create(self, serializer):
return AddMailUseCase(serializer=serializer).execute()
I usually write my rest of code in usecase.py
class AddMailUseCase:
def __init__(self, serializer):
self.serializer = serializer
self.data = serializer.validated_data
def execute(self):
self._factory()
def _factory(self):
self._mail = Mail(**self.data)
self._mail.save()
SendEmail(
context={
"fullname": self.data['full_name'],
'image': self.data['image']
}
).send(to=[self.data['email']])
I am using django-templated-mail 1.1.1 to send email here is my rest of code.
from templated_mail.mail import BaseEmailMessage
class SendEmail(BaseEmailMessage):
template_name = 'email.html'
and finally my email.html
{% load i18n %}
{% block subject %}
{% blocktrans %}Email Successfully Sent {% endblocktrans %}
{% endblock subject %}
{% block text_body %}
{% blocktrans %}You're receiving this email because you recently registered to our website.{% endblocktrans %}
{% trans "Your submitted details are as follow" %}
{% endblock text_body %}
{% block html_body %}
{% blocktrans %}
<p>hello {{ fullname }}</p>{% endblocktrans %}
{% blocktrans %}
<img src="{{ image }}" alt="email-image">
<p>{% trans "Thanks for using our site!" %}</p>
{% endblock html_body %}
any help regarding this issue?
the email I got is as below image is not loading
instead of using
<img src="{{ image }}" alt="email-image">
use
<img src="{{ image.url }}" alt="email-image">
and in your URL.py add
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
# ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
I am building an todo app with Register, Login, Logout functionalities, I created a TaskForm to let user create their tasks, but when is click add it gives an
IntegrityError at / NOT NULL constraint failed: tasks_task.user_id
I tried many different approaches but it gives the same error
it works when i add user in fields in TaskForm but it creates a Dropdown list of All users
tasks/models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Task(models.Model):
name = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
date_created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="tasks")
def __str__(self):
return f"{self.name}:{self.user}"
tasks/forms.py
from django import forms
from .models import Task
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = [
'name',
]
tasks/views.py
from django.shortcuts import render, redirect
from .forms import TaskForm
from .models import Task
from django.contrib.auth.decorators import login_required
# Create your views here.
#login_required
def home(request):
tasks = Task.objects.all()
if request.method == "POST":
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
form = TaskForm()
context = {
'tasks': tasks,
'form': form,
}
return render(request, "tasks/home.html", context )
tasks/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name= 'home' )
]
home.html
{% extends 'users/layout.html' %}
{% load crispy_forms_tags %}
{% block body %}
<div class="container pt-5 ">
{% if user.is_authenticated %}
<p style="text: 'center'">User: {{ user.get_username }}</p>
<div class="container">
<form method="post">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4" >Create Task</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-primary">Add</button>
</div>
</form>
</div>
{% else %}
Login Here
{% endif %}
<div class = "container">
<ul>
{% for task in tasks %}
{% if task in user.tasks.all %}
<li>{{ task.name }}</li>
{% endif %}
{% empty %}
<li>No Tasks for Today</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
forms.py
from django import forms
from .models import Task
class TaskForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
task = super(TaskForm, self).__init__(*args, **kwargs)
self.fields['user'].required = False
class Meta:
model = Task
fields = [
'name',
'user'
]
views.py
# You can save the user with form object then
#login_required
def home(request):
tasks = Task.objects.all()
if request.method == "POST":
form = TaskForm(request.POST)
if form.is_valid():
form_obj = form.save(commit=False)
form_obj.user = request.user
form.save()
return redirect('home')
form = TaskForm()
context = {
'tasks': tasks,
'form': form,
}
return render(request, "tasks/home.html", context )
Note: there's a similar question to mine, there're a few differences in our code, and I tried the solutions to his question, didn't work for me.
I'm working on a blog using Django, I'm trying to add an edit_post feature but when I go to localhost:8000 it shows NoReverseMatch, the problem is related to the post's id, I'm trying to create a home page that shows the post's title and it's content.
here'e my code:
models.py
from django.db import models
# Create your models here.
class BlogPost(models.Model):
title = models.CharField(max_length=20)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
urls.py
from django.urls import path
from . import views
app_name = 'blogs'
urlpatterns = [
# Home page
path('', views.index, name='index'),
# page for adding a new post
path('new_post/', views.new_post, name='new_post'),
# page for editing a post
path('edit_post/<int:post_id>/', views.edit_post, name='edit_post'),
]
index.html
{% block content %}
<p>My personal Blog</p>
Add a new post
<ul>
{% for p in posts %}
# the problem is probably here
<li>{{ p.title }}</li>
<li>{{ p.text }}</li>
<p>
Edit post
</p>
{% endfor %}
</ul>
{% endblock content %}
edit_post.html
{% block content %}
<p>Edit post:</p>
<form action="{% url 'blogs:edit_post' post.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submet">Save changes</button>
</form>
{% endblock content %}
new_post.html
{% block content %}
<P>Add a new post:</P>
<form action="{% url 'blogs:new_post' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submet">Add post</button>
</form>
{% endblock content %}
views.py
from django.shortcuts import render, redirect
from .models import BlogPost
from .forms import BlogPostForm
# Create your views here.
def index(request):
posts = BlogPost.objects.order_by('date_added')
context = {'posts': posts}
return render(request, 'blogs/index.html', context)
def new_post(request):
"""Add a new post."""
if request.method != 'POST':
form = BlogPostForm()
else:
form = BlogPostForm(data=request.POST)
if form.is_valid():
new_p = form.save()
return redirect('blogs:index')
context = {'form': form}
return render(request, 'blogs/new_post.html', context)
def edit_post(request, post_id):
post = BlogPost.objects.get(id=post_id)
if request.method != 'POST':
form = BlogPostForm(instance=post)
else:
form = BlogPostForm(instance=post, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:index', post_id=post.id)
context = {'post': post, 'index': index, 'form': form}
return render(request, 'blogs/edit_post.html', context)
forms.py
from django import forms
from .models import BlogPost
class BlogPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols':80})}
The problem is with the arguments of the url you are creating on index.html, you are looping posts as p in html so try to change:
Edit post
With
Edit post
I am tring to sent email with django using gmail smtp server i write settings in setting.py.here is my other code but I am getting AttributeError at /share/4 'str' object has no attribute 'get' ? please help me to solve that error.
**forms.py**
from django import forms
class EmailPostForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
to = forms.EmailField()
comment = forms.CharField(widget=forms.Textarea, required=False)
views.py
def share_email(request, id):
post = get_object_or_404(Post, id=id)
sent = False
if request.method == 'POST':
form = EmailPostForm(data=request.method)
if form.is_valid():
cd = form.cleaned_data
post_url =
request.build_absolute_uri(post.get_absolute_url())
subject = '{} ({}) recommend you reading "{}"'.format(cd['name'], cd['email'], post.title)
message = 'Read "{}" at {}\n\n{}\'s comments: {}'.format(post.title, post_url, cd['name'], cd['comment'])
send_mail(subject, message, 'admin#gmail.com', cd['to'])
sent = True
else:
form = EmailPostForm()
return render(request, 'blog/post/share_post.html', {'post': post, 'form': form, 'sent': sent})
url.py
urlpatterns = [path('share/<int:id>', views.share_email, name='share_post'),]
share_post.html
{% extends 'blog/base.html' %}
{% block title %}
Share Post
{% endblock %}
{% block content %}
{% if sent %}
<h2>E-mail successfully sent</h2>
<p>{{ post.title }} is successfully dent by email</p>
{% else %}
<h2>Share {{ post.title }} by email</h2>
<form action="{% url 'blog:share_post' post.id %}" method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="submit" value="Send Email">
</form>
{% endif %}
{% endblock %}
Here:
form = EmailPostForm(data=request.method)
you want request.POST, not request.method.
As a side note: a successful post should be followed by a redirect (to prevent page reload to repost the same data). You can use the contrib.messages app to set a message in session, that will then be displayed on the next page.
For some reason, my forms.py doesn't view any of the fields, instead, it only shows the 'Add' button and I don't know what to do anymore. I'd really appreciate if someone who knows what they're doing could tell me what I did, or didn't do.
Please note that I'm new to Django, thank you.
Here's my views.py:
from django.shortcuts import render
from django.utils import timezone
from .models import Measurement
from .forms import MeasurementForm
from django.views import generic
class IndexView(generic.ListView):
model = Measurement
context_object_name = 'measurement_list'
template_name = 'index.html'
queryset = Measurement.objects.all()
def new_measurement(request):
if request.method == "POST":
form = MeasurementForm(request.POST)
if form.is_valid():
measurement = form.save(commit=False)
measurement.measurement_date = timezone.now()
measurement.save()
else:
form = MeasurementForm()
return render(request, 'index.html', {'form': form})
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
]
forms.py:
from django import forms
from .models import Measurement
class MeasurementForm(forms.ModelForm):
class Meta:
model = Measurement
fields = ('measurement_value', 'measurement_unit')
index.html:
{% extends "base.html" %}
{% block content %}
<h1>Climate Measurement Tool</h1>
<h2>Add a new measurement</h2>
<form method="POST" class="post-form">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save">Add</button>
</form>
<h2>Measurements</h2>
{% if measurement_list %}
<ul>
{% for measurement in measurement_list %}
<li>
<p>{{ measurement }}</p>
</li>
{% endfor %}
</ul>
{% else %}
<p>No measurements yet</p>
{% endif %}
{% endblock %}
The new_measurement() view correctly initializes a form instance and passes it to the template.
Unfortunately, that view is never called.
urls.py defines only one url, handled by IndexView.as_view(), which does not pass a form instance to the template.