Django & SQLite.db - data is duplicated
I created 2 models in the Django framework. The first model is responsible to save emails and the second model to save messages. All emails and messages are saved in the SQLite.db. But when I add the same emails multiple times, the data base creates a new record and I don't have a clue how can I manage saving data to retrieve multiple emails with the same name and then pass them as a one mutual email to the HTML template with all assigned messages to them.
An example: I sent 3 messages from test@test.com. Messages: ['Hi', 'Hello', 'Bonjour'] and one message from user@user.com ['Hi'] DB table:
Actual result: 3 records
- test@test.com | 'Hi'
- test@test.com | 'Hello'
- test@test.com | 'Bonjour'
- user@user.com | 'Hi'
Model:
class Email(models.Model):
"""The guest's email."""
text = models.EmailField(max_length=100)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""Return a string representation of the model."""
return self.text
Then I want to pass all data to the HTML template in order to display them:
def emails(request):
"""Show all emails."""
emails = Email.objects.order_by('date_added')
context = {'emails': emails}
return render(request, 'home/emails.html', context)
HTML portion:
<h1>Emails</h1>
<ul>
{% for email in emails %}
<li>
<a href="{% url 'home:email' email.id %}">{{ email.text }}</a>
</li>
{% empty %}
<li>No emails have benn added yet.</li>
{% endfor %}
</ul>
But the final result is:
- test@test.com
message_1: Hi
- test@test.com
message_1: Hello
- test@test.com
message_1: Bonjour
- user@user.com
message_1: Hi
Expected result:
- test@test.com
message_1: Hi
message_2: Hello
message_3: Bonjour
- user@user.com
message_1: Hi
The question is how to handle it? And should I modify the HTML (javascript), view function or created models? Which approach is the best to make my page more stable?
To group the messages by email, you need to modify the view function to group the messages based on the email. Here's a sample code for your view function:
def emails(request):
""" Show all emails with grouped messages."""
emails = Email.objects.order_by('date_added').values('email').annotate(message_count=Count('email'))
messages = Message.objects.order_by('email') # guessing that you message is saved in this model.
context = {'emails': emails, 'messages': messages}
return render(request, 'home/emails.html', context)
#html file
<h1>Emails</h1>
<ul>
{% for email in emails %}
<li>{{ email.email }}</li>
<ul>
{% for message in messages %}
{% if email.email == message.email %}
<li>message_{{ forloop.counter }}: {{ message.text }}</li>
{% endif %}
{% endfor %}
</ul>
{% empty %}
<li>No emails have been added yet.</li>
{% endfor %}
</ul>
We can pass the EmailMessage
s with:
def emails(request):
messages = EmailMessage.objects.select_related('email').order_by('date_added')
context = {'messages': messages}
return render(request, 'home/emails.html', context)
You can {% regroup … %}
[Django-doc] the messages by email address:
<h1>Emails</h1> <ul> {% regroup messages by email.text as message_group %} {% for email, messages in message_group %} <li> {{ email }}: <ul> {% for message in messages %} <a href="{% url 'home:email' message.pk %}">{{ message.message }}</a> {% endfor %} </ul> </li> {% empty %} <li>No emails have been added yet.</li> {% endfor %} </ul>
I added simple try-except block that solve this problem:
if form_email.is_valid() and form_message.is_valid():
try:
email = Email.objects.get(text=request.POST['text'])
except:
form_email.save()
email = Email.objects.last()
message = form_message.save(commit=False)
message.email = email
message.save()