问题
I have a dating app and I need to create a link that is underneath each profile that a user matches on. Then, that link should pass their user id into the template so that messages are only displayed between the current user and that particular user based on the user id. I am having trouble here with the syntax of if/else statements within the Django template. How would I go about doing this?
**base.html/href messages link **
<li class="nav-item">
<a class="nav-link" href="{% url 'dating_app:messages' user.id %}">Check Messages</a>
</li>
models.py/InstantMessage
class InstantMessage(models.Model):
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'sender',on_delete=models.CASCADE )
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
message = models.TextField()
date = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.message
messages.html
<div id="msg-list-div" class="panel-body">
<ul id="msg-list" class="list-group">
<br><br><br>
{% for obj in messages %}
{% if obj.sender == request.user and obj.receiver == profile%}
{% if obj.sender == request.user%}
<li class="text-right list-group-item">{{obj.message}}<br>{{ obj.date }}<li>
{% elif obj.receiver == profile %}
<li class="text-left list-group-item">{{obj.message}}<br>{{ obj.date }}<li>
{%endif%}
{%endif%}
{% empty %}
<li class="text-right list-group-item">No messages yet...Keep mingling!</li>
{% endfor %}
</ul>
</div>
matches.html/ href link for messages.html
<p><a href="{% url 'dating_app:messages' profile.id %}">chat</a></p>
views.py/messages
def messages(request, profile_id):
messages = InstantMessage.objects.all()
profile = get_object_or_404(Profile,id=profile_id)
return render(request, 'dating_app/messages.html', {'messages': messages,'profile':profile,})
models.py
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 InstantMessage(models.Model):
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'sender',on_delete=models.CASCADE )
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
message = models.TextField()
date = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.message
entire models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser,BaseUserManager, User
from dating_project import settings
from django.contrib.auth import get_user_model
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 InstantMessage(models.Model):
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'senderr',on_delete=models.CASCADE )
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
message = models.TextField()
date = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.message
回答1:
As already suggested it is better to do all heavy work in a view, not in a template:
def messages(request, profile_id):
messages = InstantMessage.objects.filter(sender=request.user, receiver_id=profile_id, )
profile = get_object_or_404(Profile,id=profile_id)
...
Imagine if InstantMessage
contains billions of records - how fast would InstantMessage.objects.all()
work? And for what reason.
And since you want to render "a chat", I guess you need something like this:
from django.db.models import Q
...
messages = InstantMessage.objects.filter(Q(sender_id=request.user.id, receiver_id=profile_id,)
| Q(sender_id=profile_id, receiver_id=request.user.id,) ).\
values('sender_id', 'message', 'date', ).\
order_by('date',)
see also examples of making complex queries in the docs.
and the template:
{% for msg in messages %}
<li class="{% if msg.sender_id == request.user.id %}text-right{% else %}text-left{% endif %} list-group-item">
{{ msg.message }}<br/>{{ msg.date }}
</li>
{% empty %}
...
{% endfor %}
来源:https://stackoverflow.com/questions/61150352/correct-if-else-statement-syntax-for-django-templates