2

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 [email protected]. Messages: ['Hi', 'Hello', 'Bonjour'] and one message from [email protected] ['Hi'] DB table:

Actual result: 3 records

  1. [email protected] | 'Hi'
  2. [email protected] | 'Hello'
  3. [email protected] | 'Bonjour'
  4. [email protected] | '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

class EmailMessage(models.Model):
    """The guest's message."""
    email = models.ForeignKey(Email, on_delete=models.CASCADE)
    message = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.message

Then I want to pass all data to the HTML template in order to display them: url: /emails

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: (I want to display only emails on this page, without messages, and when I click on each email, the user should be redirected to another page that display all messages assigned to a particular email.)

<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>

url: /emails/email_id

def email(request, email_id):
    """Show a single email and all its messages."""
    email = Email.objects.get(id=email_id)
    messages = email.emailmessage_set.order_by('-date_added')
    context = {'email': email, 'messages': messages}
    return render(request, 'home/messages.html', context)

Template:

<h1>Email: {{ email }}</h1>

<ul>
    {% for message in messages %}
        <li>
            <p>{{ message.date_added|date:'M d, Y H:i' }}</p>
            <p>{{ message|linebreaks }}</p>
        </li>
    {% empty %}
        <li>No emails have benn added yet.</li>
    {% endfor %}
</ul>

But the final result is:

  1. [email protected]

message_1: Hi

  1. [email protected]

message_1: Hello

  1. [email protected]

message_1: Bonjour

  1. [email protected]

message_1: Hi

Expected result:

  1. [email protected]

message_1: Hi

message_2: Hello

message_3: Bonjour

  1. [email protected]

message_1: Hi

enter image description here !!! Messages are available when I click on a particular email! So when User click on a particular email, he will be redirected to another page with all messages.

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?

4
  • Please share the Email model. Commented Feb 4, 2023 at 11:15
  • Exactly where do you store the email address of the message in your model? Commented Feb 4, 2023 at 11:20
  • Your text is an Email field, so there does not seem to be anywhere to store the "message" itself? Commented Feb 4, 2023 at 11:28
  • I added second model as well Commented Feb 4, 2023 at 12:09

2 Answers 2

1

We can pass the EmailMessages 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>
Sign up to request clarification or add additional context in comments.

5 Comments

When I added your code the email [email protected] is still duplicated 3 times. I have 3x [email protected] and to each of them is assigned single message instead of 1 x [email protected] and assigned all messages send by [email protected].
@Maxwell: then you likely use different Email model objects for the same Email address...
and Im curious how can I for instance sent 100 messages from the same email adres e.g. [email protected] and only get [email protected] ONCE and 100 assigned messages. Now it looks like this [email protected] - message 1, [email protected] - message 2 ... inestad of 1x [email protected] + 100 bulleted messages.
and this is a good point, I should change how emails and messages are saved in the database. so DB should not create new models for emails with the same name I guess.
@Maxwell; you can fix it with regroup messages by email.text ... but you should really look how you create data, and try to fix that.
0

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()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.