How can I get item from a model field - python

I'm a Django beginner, how can I get profile_pic from Profile Model connecting it to 'to_user' field in FriendRequest Model.
I was able to get the names of users in 'to_user' field by this:
{% for data in sent_friend_request %}
{{ data.to_user.username }}
{% endfor %}
How do I get the profile_pic for each users?
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
profile_pic = models.ImageField()
class FriendRequest(models.Model):
to_user = models.ForeignKey(settings.AUTH_USER_MODEL)
from_user = models.ForeignKey(settings.AUTH_USER_MODEL)
def following_view(request, username):
sent_friend_request = FriendRequest.objects.filter(from_user__username=username)
context = {'sent_friend_request':sent_friend_request}
{% if data.to_user.profile_pic %}
<img src="{{ data.to_user.profile_pic }}">
{% endif %}

You can do like this:
{% if data.to_user.profile.profile_pic %}
<img src="{{ data.to_user.profile.profile_pic.url }}">
{% endif %}

Related

How to dynamically insert a value in a Django ModelForm

I have a project where users can create a company. However, there is a Theme that needs to be dynamically inserted, once the user chooses a theme on the frontend - more like when you want to choose a template in a no-code builder. Below is my models.py
class Theme(models.Model):
name = models.CharField(max_length=100, null=True)
image = models.ImageField(upload_to='static/images/themes_images', null=True, blank=True)
category = models.CharField(max_length=200, choices=CATEGORY_CHOICES, null=True)
class Company (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, editable=False)
date_created = models.DateField(default=timezone.now, null=True)
company_name = models.CharField(max_length=100, null=True)
theme = models.ForeignKey(Theme, on_delete=models.CASCADE, null=True, blank=True)
For the Theme model, it is only the administrator who will create it and the user will only have to choose it on the front end. Sort of like when choosing a premade template in Weebly. All the Theme Objects will have their own page where the user can visually see which theme to go with:
#login_required(login_url='login')
def theme(request):
themes = Theme.objects.all()
context = {'themes': themes}
return render(request, 'themes.html', context)
I haven't done much with the view, cause I am not sure how to go about it to achieve the desired result.
Themes.html
{% extends 'index.html' %}
{% load static %}
{% block 'title' %} <title>Themes | Simpledocs</title> {% endblock %}
{% block content2 %}
{% endblock %}
{% block content %}
<h2 class="my-4">Choose your theme</h2>
<div class="columns">
{% for t in themes %}
<div class="column is-4">
{{t.name}}<br>
<img src = "/{{t.image}}" height="150px" width="150"/><be>
{{t.category}}<br>
<a class="button" href="#">Choose Theme</a>
</div>
{% endfor %}
</div>
{% endblock %}
So with a click on the above view, the user should be able to select a theme and apply it dynamically in the Company model on the theme entry. I have never dealt with such a challenge and need help here.
It is actually easy. Got the solution.
Create another view that shows individual themes:
{% extends 'index.html' %}
{% load static %}
{% block 'title' %} <title>Themes | Simpledocs</title> {% endblock %}
{% block content2 %}
{% endblock %}
{% block content %}
<h2 class="my-4">Choose your theme</h2>
<div class="columns">
{{single_theme.name}}<br><br>
<img src="/{{single_theme.image}}" /><br><be>
{{single_theme.category}}<br>
<form method="POST">
{% csrf_token %}
<button class="button">Choose Theme</button>
</form>
</div>
{% endblock %}
Create another View showcasing the theme. And execute the change of the Company.theme entry.
#login_required(login_url='login')
def theme_single(request, pk):
single_theme = Theme.objects.get(id=pk)
company = Company.objects.all()
if request.method == 'POST':
for c in company:
c.theme = single_theme
c.save()
return redirect('company')
context = {'single_theme':single_theme}
return render(request, 'theme_single.html', context)
This will change the company.theme model entry to the current theme selected.

Django, problem with the comment form below the post

I just can't figure it out for a very long time, I made a conclusion of comments to posts from the admin panel. But I just can't figure out how to make a comment form right under the post for users to comment. Thanks to all!
models.py
class Post(models.Model):
photo = models.ImageField(upload_to='media/photos/',null=True, blank=True)
name_barber = models.CharField(max_length=30)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.description[:10]
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
name = models.CharField(max_length=30)
body = models.TextField(null=True)
add_date = models.DateTimeField(auto_now_add=True)
enter code here
def __str__(self):
return '%s - %s' % (self.post, self.name)
form.py
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ('name', 'body')
views.py
class HomePage(ListView):
model = Post
template_name = 'main/index.html'
context_object_name = 'posts1'
class BarbersPage(ListView):
model = Post
template_name = 'main/barbers.html'
context_object_name = 'posts'
urls.py
urlpatterns = [
path('',views.HomePage.as_view(),name='index'),
path('barbers/',views.BarbersPage.as_view(), name='barbers'),
]
barbers.html
{% for post in posts %}
<img src="{{MEDIA_URL}}{{post.photo.url}}" width="800" />
<h3>
{{ post.name_barber}}
</h3>
<p>{{ post.description}}</p>
<h3> Comments.. </h3>
{% if not post.comments.all %}
no comments yet...Add one
{% else %}
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}
{{ comment.add_date }}
</strong>
<p>{{comment.body }}</p>
<br>
{% endfor %}
{% endif %}
{% endfor %}
You will need to add a form block below the post for users to add a comment.
Something like this:
{% for post in posts %}
<img src="{{MEDIA_URL}}{{post.photo.url}}" width="800" />
<h3>
{{ post.name_barber}}
</h3>
<p>{{ post.description}}</p>
<h3> Comments.. </h3>
{% if not post.comments.all %}
no comments yet...Add one
{% else %}
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}
{{ comment.add_date }}
</strong>
<p>{{comment.body }}</p>
<br>
{% endfor %}
{% endif %}
Add Comment:<br/>
<form method="post" action="/AddComment">
<input type="hidden" id="postid" value="{{post.id}}"/>
<input type="text" id="newcomment" size="50"/><input type="submit" value="Submit"/>
</form><br/>
{% endfor %}
You will need to decide where to submit the comment data and update the action attribute in the form.

how to show data from 2 models in django with one to many relashion in template

Hello i have 2 classes in my model:
class MO (models.Model):
many variables
class PhotoMO (models.Model):
mo = models.ForeignKey(MO, on_delete=models.CASCADE)
photo = models.ImageField(
upload_to='img/photo/%Y/%m/'
)
my views for template
class MOListView(DetailView):
template_name = 'main_site/mo_view.html'
model = models.MO
with template :
{% block content %}
<h1>{{ mo.name }}</h1>
<h3>{{ mo.phone_number }}</h3>
<h3>{{ mo.email_mo }}</h3>
<h3>{{ mo.adress_mo }}</h3>
{% for photos in mo.photomo.set.all %}
<img src="{{ photos.photo.url }}" alt="no img">
{% endfor %}
{% endblock %}
How can I display all the pictures from PhotoMO that refer to a specific entry in MO. With my "for" it dosen't work
You need to set the back relation:
class PhotoMO (models.Model):
mo = models.ForeignKey(MO, on_delete=models.CASCADE, related_name='photomo')
Then migrate the database to be able to access photomo.
Kind regards.
{% for photo in mo.photomo_set.all %}
<img src="{{ photo.photo.url }}" alt="none">
{% endfor %}
need to use mo.photomo_set.all

Why _set.all dont work in tempale?

I have 3 connected with each other models. GroupRequirementType --> GroupRequirement --> Requirement. I am tring to show all requirements in template. Next code show me only GroupRequirementType objects. It seems like I have problems with _set.all. Whats wrong?
models.py:
class GroupRequirementType(models.Model):
name = models.CharField(_('Name'), max_length=250)
class GroupRequirement(models.Model):
group_requirement_type = models.ForeignKey(GroupRequirementType, on_delete=models.CASCADE)
name = models.CharField(_('Name'), max_length=250)
class Requirement(models.Model):
group_requirement = models.ForeignKey(GroupRequirement, on_delete=models.CASCADE)
name = models.CharField(_('Name'), max_length=250)
template:
{% for group_requirement_type in group_requirement_types %}
{{ group_requirement_type }}
{% for group_requirement in group_requirement_type.group_requirement_set.all %} <!--DONT WORK. WHY?-->
{{ group_requirement }}
{% for requirement in group_requirement.requirement_set.all %}
{{ requirement }}
{% endfor %}
{% endfor %}
{% endfor %}
It looks like Django doesn't automatically add an underscore when converting the CamelCase model name to lower case. grouprequirement_set.all works.
I'd highly recommend using Django ForeignKey related_name property in your models declaration, this makes backwards relations operations much easier: https://docs.djangoproject.com/en/1.11/ref/models/fields/#django.db.models.ForeignKey.related_name
In your case it will turn into something like
models.py:
class GroupRequirementType(models.Model):
name = models.CharField(_('Name'), max_length=250)
class GroupRequirement(models.Model):
group_requirement_type = models.ForeignKey(GroupRequirementType, related_name='group_requirements', on_delete=models.CASCADE)
name = models.CharField(_('Name'), max_length=250)
class Requirement(models.Model):
group_requirement = models.ForeignKey(GroupRequirement, related_name='requirements', on_delete=models.CASCADE)
name = models.CharField(_('Name'), max_length=250)
template:
{% for group_requirement_type in group_requirement_types %}
{{ group_requirement_type }}
{% for group_requirement in group_requirement_type.group_requirements.all %} <!--DONT WORK. WHY?-->
{{ group_requirement }}
{% for requirement in group_requirement.requirements.all %}
{{ requirement }}
{% endfor %}
{% endfor %}
{% endfor %}

Django Category Model and Template View Issue

My question is two phased but it's from the same Django Model. I am trying to get my Category model to work properly with my Petition model. Currently,
I get this 'FieldError' error when I define a queryset for my 'CategoryView' class:
Cannot resolve keyword 'created_on' into field. Choices are: description, id, petition, slug, title
Here is the code for the 'CategoryView' class:
class CategoryView(generic.ListView):
model = Category
template_name = 'petition/category.html'
context_object_name = 'category_list'
def get_queryset(self):
return Category.objects.order_by('-created_on')[:10]
Here is the code in my models.py:
class Category(models.Model):
title = models.CharField(max_length=90, default="Select an appropriate category")
slug = models.SlugField(max_length=200, unique=True)
description = models.TextField(null=False, blank=False)
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.title
def get_absolute_url(self):
return "/categories/%s/"%self.slug
class Petition(models.Model):
title = models.CharField(max_length= 90, default="Enter petition title here")
created_on = models.DateTimeField(auto_now_add=True)
image = models.ImageField(null=False, upload_to=imageupload)
video = models.CharField(max_length=600, default="Enter an external video link")
petition = models.TextField(null=False, default="Type your petition here")
created_by = models.ForeignKey(User)
category = models.ManyToManyField(Category)
def total_likes(self):
return self.like_set.count()
def __str__(self):
return self.title[:50]
def get_signatures(self):
return self.signature_set.all()
I get the 'FieldError' on my category view template (category.html) when the 'get_queryset()' has been defined.
When I comment it out, the page displays but posts are not retrieved; I get a list of the categories instead. Here is my category view template(category.html):
{% include 'layout/header.html' %}
{% load humanize %}
<div class="container content">
<div class="row">
<div class="col-md-8 post-area">
{% if category_list %}
{% for petition in category_list %}
<div class="petition-block">
<h2 class="home-title">{{petition.title}}</h2>
<span class="petition-meta">
Created {{petition.created_on|naturaltime}} by
{% if petition.created_by == user %}
You
{% else %}
#{{ petition.created_by }}
{% endif %}
{% if petition.created_by == user %}
Edit
{% endif %}
{% if petition.created_by == user %}
Delete
{% endif %}
</span>
{% if petition.image %}
<img src="{{ petition.image.url }}" alt="petition image" class="img-responsive" />
{% endif %}
</div><!--//petition-block-->
{% endfor %}
{% else %}
<p>Sorry, there are no posts in the database</p>
{% endif %}
</div>
<div class="col-md-4">
<h3>Topics</h3>
<ul>
{% for petition in category_list %}
<li>{{petition.title}}</li>
{% endfor %}
</ul>
</div>
</body>
</html>
What am I doing wrong? Please help.
That's because you are trying to order the Category's queryset by created_on and your Category model doesn't have any field called created_on. That field is within Petition model. If you want to order the categories by petition's created_on you should do a "join" between tables, but with Django's ORM is easy.
For simplicity on your code is better to name the relation
class Petition(models.Model):
...
categories = models.ManyToManyField(Category, related_name='petitions')
...
Now you can refer to the category's petitions as 'petitions'
Category.objects.order_by('-petitions__created_on')
For use the petitions within the template the best way is prefetch the petitions on the queryset to avoid hitting the database every time in the for loop.
Category.objects.prefetch_related('petitions').order_by('-petitions__created_on')
That would bring every petition for each category. So in your template you can use:
{% for category in category_list %}
{% for petition in category.petitions.all %}
...
#{{ petition.created_by }}
...
{% end for %}
{% end for %}

Categories

Resources