Home > Blockchain >  Django & SQLite.db - data is duplicated
Django & SQLite.db - data is duplicated

Time:02-04

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?

CodePudding user response:

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>

CodePudding user response:

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