1

So I'm a developer noobie, and building my first project from scratch. I'm currently building a messaging system for my app. How it's supposed to work is that A user goes to a link that checks their current conversations, so conversations are displayed. Then FROM the conversations, there is a link that takes them to a page that displays the contents of that conversation. But I'm having a problem here, because when I try to get the other user's pk to display their messages, my code is instead getting request.user pk and getting ALL the messages that the current user has going on not exclusively between 2 users within that specific conversation. Now, when I manually, and by manually I mean typing the actual pk of the specific user I want to check on that has messages with my user, when I manually enter their pk number in the http, I am able to get the correct messages and exclusive messages. Currently, my href link is passing conversation.pk and I haven't figured out how to get the other users pk. Everything I have tried has kept passing my request.user pk. So I guess what I'm asking is how can I get the other users pk passed in with my url? I am assuming I need to keep conversation.pk, and add the other users pk as another parameter. Or, is there another way to do this? Perhaps putting some extra logic in my view? Or in the template? I'm rather stuck here.

views.py/ message and messages

#displays active conversations
def messages(request,profile_id):


    conversations = Conversation.objects.filter(
        members= request.user
    ).annotate(
        last_message=Max('instantmessage__date')
    ).prefetch_related('members').order_by(
        '-last_message'
    )


#displays contents of conversations, messages 
def message(request, profile_id):


    receiver = get_object_or_404(Profile,id=profile_id)

    exclusive_conversations = Conversation.objects.filter(members= request.user ).filter(members= receiver)


    messages = InstantMessage.objects.filter(receiver__in=exclusive_conversations)


    context = {'messages' : messages, }

    return render(request, 'dating_app/message.html', context)

urls.py/message, messages

path('message/<int:profile_id>/', views.message, name='message'),
    path('messages/<int:profile_id>/', views.messages, name='messages'),
]

messages.html

{% for conversation in conversations%}
    <li class="text-right list-group-item">
        {% for member in conversation.members.all %}{% if member != user %}
            {{ member.username }}
            <a href="{% url 'dating_app:message' conversation.pk %}">Start messaging </a>
            <br><br>
        {% endif %}{% endfor %}

    </li>
{%endfor %}

message.html

{% for message in messages %}

        {% if message.sender_id == request.user.id  %}
        <li class="text-right list-group-item"> {{ message.message }}<br>{{ message.date }} </li>
        {% else %}
        <li class="text-left list-group-item"> {{ message.message }}<br>{{ message.date }} </li>

        {% endif %}



{%endfor %}

**models.py **

class ProfileManager(BaseUserManager):



    def create_user(self, username, email,description,photo, password=None):
        if not email:
            raise ValueError("You must creat an email")
        if not username:
            raise ValueError("You must create a username!")
        if not description:
            raise ValueError("You must write a description")
        if not photo:
            raise ValueError("You must upload a photo")

        user = self.model(
                email=self.normalize_email(email),
                username = username, 
                description= description,
                photo= photo,

            )

        user.set_password(password)
        user.save(using=self._db)
        return user 


    def create_superuser(self, username, email,description,photo, password):
        user = self.create_user(
                email=self.normalize_email(email),
                password=password,
                username=username,
                description=description,
                photo=photo,

            )

        user.is_admin=True
        user.is_staff=True
        user.is_superuser=True
        user.save(using=self._db)
        return user




class Profile(AbstractBaseUser):

    class Meta:
        swappable = 'AUTH_USER_MODEL'


    email                       = models.EmailField(verbose_name="email")
    username                    = models.CharField(max_length=30, unique=True)
    date_joined                 = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
    last_login                  = models.DateTimeField(verbose_name='last login', auto_now=True)
    is_admin                    = models.BooleanField(default=False)
    is_active                   = models.BooleanField(default=True)
    is_staff                    = models.BooleanField(default=False)
    is_superuser                = models.BooleanField(default=False)
    #what I added
    description                 = models.TextField()
    photo                       = models.ImageField(upload_to='profile_photo',blank=False, height_field=None, width_field=None, max_length=100)
    matches                     = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='+', blank=True)



    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['description','photo','email']


    objects = ProfileManager()


    def __str__(self):
        return self.username


    def has_perm(self, perm, obj=None):
        return self.is_admin


    def has_module_perms(self,app_label):
        return True



class UserVote(models.Model):

    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    voter = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='given_vote', on_delete=models.CASCADE)
    vote = models.BooleanField(default=False)

    class Meta:
        unique_together = (('user', 'voter'))


class Conversation(models.Model):
    members = models.ManyToManyField(settings.AUTH_USER_MODEL)




class InstantMessage(models.Model):

    sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'senderr',on_delete=models.CASCADE )
    receiver = models.ForeignKey(Conversation, on_delete=models.CASCADE)
    message = models.TextField()
    date = models.DateTimeField(auto_now_add=True)


    def __unicode__(self):
        return self.message

    #tests to see if messages are exclusive between sender, receiver 
    @classmethod
    def find_messages_exclusive_to_profile(cls,sender,receiver):
        #members = receiver AND sender, not receiver or sender 
        exclusive_conversations = Conversation.objects.filter(members= receiver ).filter(members= sender)


        exclusive_messages = InstantMessage.objects.filter(receiver__in=exclusive_conversations)

        return exclusive_messages
4
  • 1
    I would start by refactoring my database schema, because passing the conversation.pk as a parameter (like you do now), should be more than enough to get the two parties involved in the conversation (they should be fields in the Conversation model). Commented Apr 20, 2020 at 18:06
  • Are you saying my InstantMessage model and Conversation model should be one model? Commented Apr 20, 2020 at 18:17
  • 1
    Not exactly. They are both necessary but IMHO the schema is wrong. Let me elaborate an answer with the way I would do this. Commented Apr 20, 2020 at 18:24
  • ok cool, great. Commented Apr 20, 2020 at 18:25

1 Answer 1

1

Ok I ended up figuring out my own problem. Ok, so what I was doing wrong was passing the Conversation.pk rather than the other users pk. By passing in the conversation pk, I wasn't able to exclusively filter through only messages between the two users, but I was getting messages that weren't exclusive between the two users. And, the conversation PK will always have fewer pk's than users. There may be 3 conversation objects, but 5 users with differing pk's. Anyhow, the solution was simply to change conversation.pk to member.pk like so in messages.html

{% for conversation in conversations%}
<li class="text-right list-group-item">
    {% for member in conversation.members.all %}{% if member != user %}
        {{ member.username }}
        <a href="{% url 'dating_app:messages' member.pk %}">Start messaging </a>
        <br><br>
    {% endif %}{% endfor %}

</li>
{%endfor %}

And then, I tweaked my message.html to filter between request.user and other_user

{% for message in messages %}



        {% if message.sender_id == request.user.id %}
        <li class="text-right list-group-item"> {{ message.message }}<br>{{ message.date }} </li>
        {% elif message.sender_id == profile.id %}
        <li class="text-left list-group-item"> {{ message.message }}<br>{{ message.date }} </li>

        {% endif %}



{%endfor %}
Sign up to request clarification or add additional context in comments.

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.