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)
Related
Thank you for taking the time to help! I've been stuck for hours. I'm learning django by going through this fantastic youtube video: https://www.youtube.com/watch?v=sm1mokevMWk&t=4252s. I believe I copied the code from the video exactly, and I double and triple checked it. Yet, despite declaring method = "post" in "create".html django consistently uses a get response. WHY?!
#urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<int:id>', views.index, name='index'),
path("",views.home, name = 'home'),
path("create/", views.create, name="create"),
]
#views.py
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from .models import ToDoList, Item
from .forms import CreateNewList
def index(response, id):
ls = ToDoList.objects.get(id=id)
return render(response, 'main/list.html', {"ls":ls})
def home(response):
return render(response, "main/home.html", {})
def create(response):
print(response.method)
if response.method == "POST":
form = CreateNewList(response.POST)
if form.is_valid():
n = form.cleaned_data['name']
t = ToDoList(name=n)
t.save()
return HttpResponseRedirect("/%i" %t.id)
else:
form = CreateNewList()
return render(response, "main/create.html", {"form":form})
#create.html
{% extends 'main/base.html' %}
{% block title %} Create New List {% endblock %}
{% block content %}
Create Pages
<form method="post" action="/create/">
{{form.as_p}}
<button type="submit", name ="save" >Create New</button>
</form>
{% endblock %}
#base.html
<html>
<head>
<title>{% block title %}Jeff's website{% endblock %}</title>
</head>
<body>
<div id="content", name="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
#home.html
{% extends 'main/base.html' %}
{% block title %}
Home
{% endblock %}
{% block content %}
<h1>Home Page</h1>
{% endblock %}
#models.py
from django.db import models
class ToDoList(models.Model):
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Item(models.Model):
todolist = models.ForeignKey(ToDoList, on_delete=models.CASCADE)
text = models.CharField(max_length=300)
complete = models.BooleanField()
def __str__(self):
return self.text
You need to perform a GET request first to display your form and then , you make a post request for the submit, that why you check the request method .
if response.method == "POST" => The form is already displayed and we need to submit it
else we need to display our form
I am learning fresh django development. Working on a blog project I am facing a issue that, while publishing a new blog, that doesn't redirects to home/blogs page. I tried to manually to go home It says,
OperationalError at /blog/
no such column: App_Blog_blog.author_id
I tried to debug several times, searched in documentation can't get away with this author_id. These are my codes:
Views.py
class CreateBlog(LoginRequiredMixin, CreateView):
model = Blog
template_name = 'App_Blog/create_blog.html'
fields = ('blog_title', 'blog_content', 'blog_image',)
def form_valid(self, form):
blog_obj = form.save(commit=False)
blog_obj.author = self.request.user
title = blog_obj.blog_title
blog_obj.slug = title.replace(" ", "-") + "-" + str(uuid.uuid4())
blog_obj.save()
return HttpResponseRedirect(reverse('index'))
class BlogList(ListView):
context_object_name = 'blogs'
model = Blog
template_name = 'App_Blog/blog_list.html'
Views.py of main project file
def index(request):
return HttpResponseRedirect(reverse('App_Blog:blog_list'))
urls.py
from django.urls import path
from App_Blog import views
app_name = 'App_Blog'
urlpatterns = [
path('', views.BlogList.as_view(), name='blog_list'),
path('write/', views.CreateBlog.as_view(), name='create_blog'),
]
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Blog(models.Model):
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='post_author')
blog_title = models.CharField(max_length=264, verbose_name="Put a Title")
slug = models.SlugField(max_length=264, unique=True)
blog_content = models.TextField(verbose_name="What is on your mind?")
blog_image = models.ImageField(
upload_to='blog_images', verbose_name="Image")
publish_date = models.DateTimeField(auto_now_add=True)
update_date = models.DateTimeField(auto_now=True)
def __str__(self):
return self.blog_title
create_blog.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title_block %}
Write a Blog
{% endblock title_block %}
{% block body_block %}
<h2>Start Writing:</h2>
<form method="POST">
{{ form | crispy }}
{% csrf_token %}
<br>
<button type="button" class="btn btn-success btn-sm">Publish</button>
</form>
{% endblock body_block %}
blog_list.html
{% extends 'base.html' %}
{% block title_block %} Home {% endblock %}
{% block body_block %}
{% for blog in blogs %}
<h3>{{blog.blog_title}}</h3>
<h6>{{blog.publish_date}}</h6>
{% endfor %}
{% endblock %}
Create Blog form:
Error showing on site:
I am trying to get the uploaded image to show in the project template. Here is what my code looks like currently:
projects.html
{% extends "base.html" %}
{% block content %}
<h1>{{ project.title }} HELLO</h1>
<div class="content-section">
<div class="media">
<img src="{{ project.image.url }}" alt="beach" width=250px height=250px />
</div>
<div>
<h5>About the project:</h5>
<p>{{ project.description }}</p>
<br>
<h5>Technology used:</h5>
<p>{{ project.tools }}</p>
</div>
</div>
{% endblock content %}
models.py
class Project(models.Model):
title = models.CharField(max_length=500, unique=True)
description = models.TextField(max_length=500)
tools = models.CharField(max_length=200)
image = models.ImageField(default='default.jpg', upload_to="beach_photos", blank=True)
def __str__(self):
return f'{self.title}'
views.py
from django.shortcuts import render
from django.http import HttpResponse
from projects.models import Project
def projects(request):
project = {
'project':Project.objects.all()
}
return render(request, 'projects/projects.html', context = project)
settings.py configuration (app is installed)
STATIC_URL = 'static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
When I inspect the image element in the webpage, the source shows up as
src=""
None of the other calls to the model are appearing either.
Any help would be appreciated.
i think you forgot to add a for-loop in your template. try this:
{% for p in project %}
{{ p.title %}}
{% endfor %}
Make sure that the image field of your record in the database is full.
Access the required model with the python manage.py shell command and check if this model has a value of variable.image.url.
I've been trying to fix my messages in order to show the messages by most recent. I can't figure out where did I go wrong in the code.
The output in my inbox shows the list of newly created conversations with a new user on the very top followed by the previous messages. Whenever I try to message the other person in my inbox, it does not go up as the most recent in the list. I am hoping to put the most recent on the top of the list.
I am thinking that I can use sent_at to know the last active conversation in an active chat but I don't know where to start.
Here are my codes:
models.py
from django.db import models
from django.core.exceptions import ValidationError
from django.utils import timezone
from django.conf import settings
AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
class Message(models.Model):
"""
A private direct message.
"""
content = models.TextField('Content')
document = models.FileField(upload_to='direct_messages', blank=True, null=True)
sender = models.ForeignKey(
AUTH_USER_MODEL, on_delete=models.CASCADE,
related_name='sent_dm', verbose_name='Sender'
)
recipient = models.ForeignKey(
AUTH_USER_MODEL, on_delete=models.CASCADE,
related_name='received_dm', verbose_name='Recipient'
)
sent_at = models.DateTimeField('sent at', auto_now_add=True)
read_at = models.DateTimeField('read at', null=True, blank=True)
class Meta:
ordering = ['-sent_at']
#property
def unread(self):
"""
Returns whether the message was read or not.
"""
if self.read_at is not None:
return True
def __str__(self):
return self.content
def save(self, **kwargs):
"""
Check message sender and recipient and raise error if the are saved.
Save message when the condition passes.
"""
if self.sender == self.recipient:
raise ValidationError("You cant't send messages to yourself!")
if not self.id:
self.sent_at = timezone.now()
super(Message, self).save(**kwargs)
class ChatRoom(models.Model):
"""
A private char room
Attributes:
created_at (datetime): datetime value when chatroom is created.
recipient (user): user whom the chatroom sends first message.
sender (user): user who created the chatroom
"""
sender = models.ForeignKey(
AUTH_USER_MODEL, on_delete=models.CASCADE,
related_name='chatroom_sender', verbose_name='Sender'
)
recipient = models.ForeignKey(
AUTH_USER_MODEL, on_delete=models.CASCADE,
related_name='chatroom_recipient'
)
created_at = models.DateTimeField('sent at', auto_now_add=True)
class Meta:
ordering = ['-created_at']
unique_together = ('sender', 'recipient')
views.py
from django.shortcuts import render,redirect
from django.urls import reverse
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from django.db.models import Q
from django.views.generic import CreateView, RedirectView
from .models import Message, ChatRoom
from .forms import MessageForm
from .services import MessagingService
from users.models import User
class MessageDetailView(CreateView):
"""
Show a messages, and could send messages.
"""
model = ChatRoom
form_class = MessageForm
template_name = 'direct_messages/direct_messages.html'
def get_context_data(self, **kwargs):
"""
Returns conversations based on different conditions.
1. Fetch message based on chatroom (sender, recipient)
2. Fetch current conversation of the current user and assign it
to conversations context value
3. If current loggedIn user is sender, active_recipient will be
message recipient otherwise, message sender.
4. Fetch active conversation for message / chat tab.
:param kwargs: Description
:return: Description
"""
chat_id = self.kwargs.get('pk')
chatroom = ChatRoom.objects.get(pk=chat_id)
message = Message.objects.filter(
sender=chatroom.sender,
recipient=chatroom.recipient
).first()
if not message:
message = Message.objects.filter(
sender=chatroom.sender,
recipient=chatroom.recipient
).first()
# MessagingService().mark_as_read(message)
user = self.request.user
kwargs['active_conversation'] = message
current_conversations = MessagingService().get_conversations(user=self.request.user)
kwargs['conversations'] = current_conversations
if user == message.sender:
active_recipient = message.recipient
# kwargs['recipient'] = User.objects.get(username=message.recipient)
else:
active_recipient = message.sender
# kwargs['sender'] = message.sender
running_conversations = MessagingService().get_active_conversations(user, active_recipient)
kwargs['running_conversations'] = running_conversations
return super().get_context_data(**kwargs)
def form_valid(self, form):
"""
Checks for valid form and submit with updating message object.
:param form: form object
:return: Redirect to cuurent message conversation.
"""
obj = self.get_object()
if self.request.user == obj.sender:
recipient = obj.recipient
else:
recipient = obj.sender
message = form.save(commit=False)
message.sender = self.request.user
message.recipient = recipient
message.save()
messages.success(self.request, 'The message is sent with success!')
return redirect('direct_messages:user_message', obj.pk)
#method_decorator([login_required], name='dispatch')
class MessageView(RedirectView):
permanent = False
query_string = True
pattern_name = 'direct_messages:user_message'
def get_redirect_url(self, *args, **kwargs):
"""
Prepares redirect url when the project owner accept the proposal.
"""
user = self.request.user
chatroom = ChatRoom.objects.filter(Q(sender=user) | Q(recipient=user)).first()
if chatroom:
return super().get_redirect_url(*args, pk=chatroom.pk)
messages.warning(self.request, 'You do not have any messages to show.')
return reverse('direct_messages:list_message')
direct_messages.html
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% load humanize %}
{% block styles %}
<link rel="stylesheet" href="{% static 'assets/css/message.css' %}">
<link rel="stylesheet" href="{% static 'css/profile.css' %}" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
{% endblock %}
{% block content %}
<section id="main">
<div class="container">
<div class="messaging">
<div class="inbox_msg">
<div class="inbox_people">
<div class="headind_srch">
<div class="recent_heading">
<h4>Recent</h4>
</div>
</div>
<div class="inbox_chat">
{% for chat in conversations %}
<div class="chat_list {% if forloop.counter == 1 %} active_chat {% endif %} ">
<a style="display: block;
height: 100%;
width: 100%;
text-decoration: none;"
href="{% url 'direct_messages:user_message' chat.pk %}" class="fill-div">
<div class="chat_people" >
<div class="chat_img" >
<img src="{{ MEDIA_URL }}{{ chat.recipient.profile_photo.url }}" alt="sunil">
</div>
<div class="chat_ib" >
<h5>{{ chat.recipient }}</h5>
</div>
</div>
</a>
</div>
{% endfor %}
</div>
</div>
<div class="mesgs">
<div class="msg_history">
{% for conversation in running_conversations %}
{% if user == conversation.sender %}
<div class="outgoing_msg">
<div class="sent_msg">
<p>{{ conversation.content | safe }}</p>
{% if conversation.document %}
<a type="button" style="color:#FFFFFF; background-color:#A9A9A9; border: 3pt lightgrey" class="badge badge-secondary" target="_blank" href="{{ MEDIA_URL }}{{ conversation.document.url | safe }}" >See attachment</a>
{% endif %}
<span class="time_date">{{ conversation.sent_at | naturaltime }}</span>
</div>
</div>
{% else %}
<div class="incoming_msg">
<div class="incoming_msg_img">
<img src="{{ MEDIA_URL }}{{ conversation.sender.profile_photo.url }}" alt="{{ conversation.recipient.username }}">
</div>
<div class="received_msg">
<div class="received_withd_msg">
<p>{{ conversation.content | safe }}</p>
{% if conversation.document %}
<a type="button" style="color:#FFFFFF; background-color:#A9A9A9; border: 3pt lightgrey" class="badge badge-secondary" target="_blank" href="{{ MEDIA_URL }}{{ conversation.document.url | safe }}" >See attachment</a>
{% endif %}
<span class="time_date">{{ conversation.sent_at | naturaltime }}</span>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="type_msg">
<div class="input_msg_write">
<form method="post" novalidate enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
{{ field }}
{# {% if field.help_text %}#}
{# {{ field.help_text }}#}
{# {% endif %}#}
{# {% for error in field.errors %}#}
{# {{ error }}#}
{# {% endfor %}#}
{% endfor %}
<button class="msg_send_btn" type="submit"> <i class="fa fa-paper-plane-o" style="font-size:15px" aria-hidden="true"> </i> </button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
if you want to organize chats then you should update your model like:
class ChatRoom(models.Model):
"""
A private char room
Attributes:
created_at (datetime): datetime value when chatroom is created.
recipient (user): user whom the chatroom sends first message.
sender (user): user who created the chatroom
"""
sender = models.ForeignKey(
AUTH_USER_MODEL, on_delete=models.CASCADE,
related_name='chatroom_sender', verbose_name='Sender'
)
recipient = models.ForeignKey(
AUTH_USER_MODEL, on_delete=models.CASCADE,
related_name='chatroom_recipient'
)
created_at = models.DateTimeField('sent at', auto_now_add=True)
last_update = models.DateTimeField('last message',auto_now=False)
class Meta:
ordering = ['-created_at']
unique_together = ('sender', 'recipient')
then you have to update last_update field when new message arrives from sender or send by user and arrange chat list according to last_update time like:
chats = ChatRoom.objects.all().order_by('-last_update')
I hope this is what you want
This is the code to start a new conversation, I am developing a freelance marketplace so a new conversation will only be made when the employer accepts the proposal of the freelancer
class ProposalAcceptView(RedirectView):
"""
Aceept a proposal.
"""
permanent = False
query_string = True
pattern_name = 'jobs:job_detail'
def get_redirect_url(self, *args, **kwargs):
job = get_object_or_404(Job, pk=kwargs['pk'])
job.freelancer = User.objects.get(username=kwargs.get('username'))
job.status = 'working'
job.save()
# Create message opening
is_chatroom = False
try:
chatroom = ChatRoom.objects.get(sender=self.request.user, recipient=job.freelancer)
is_chatroom = True
except:
pass
if not is_chatroom:
try:
chatroom = ChatRoom.objects.get(sender=job.freelancer, recipient=self.request.user)
except:
pass
if not is_chatroom:
chatroom = ChatRoom.objects.create(sender=self.request.user, recipient=job.freelancer)
print('is chatroom', is_chatroom)
print('chat roo', chatroom)
print('chat room created....')
MessagingService().send_message(
sender=self.request.user,
recipient=job.freelancer,
message="""
Hi {username},
Your proposal is accepted.
Project details: <a href='{url}'>{job}</a>
""".format(username=job.freelancer.username,
url=reverse("jobs:job_detail", kwargs={"pk": job.pk}),
job=job.job_title
)
)
messages.success(
self.request, 'User : {} is assiged to your project'.format(kwargs.get('username'))
)
return super().get_redirect_url(*args, pk=kwargs['pk'])
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()),
]