Django Category Model and Template View Issue - python

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

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 can I get item from a model field

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

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

Django: Query Selected Info in Model Within Class Based Views

I created some link with model-slug. But When I click my link, go to the page but return the empty value. I want to When I click any link, It will query value from the selected field like class_name or slug field.
this class list html page
{% extends "result/base.html" %}
{% block title %}Class List Name{% endblock title %} {% block content %}
<div class="row">
<div class="col-md-12 col-xs-offset-4">
<h2>Class List</h2>
{% for object in object_list %}
{{object.class_name}}
{% endfor %}
</div>
</div>
{% endblock %}
this is models.py file
class ClassName(models.Model):
class_name=models.CharField('Class Name', max_length=10)
class_added=models.DateTimeField(auto_now_add=True)
class_updated=models.DateTimeField(auto_now=True)
slug=models.SlugField(max_length=200, unique=True)
def __str__(self):
return self.class_name
this is views.py file
class ClassListView(ListView):
model=ClassName
slug_field = 'slug'
template_name='result/class_list.html'
class ClassDetailView(DetailView):
model=ClassName
slug_field = 'slug'
template_name='result/class_detail.html'
def get_context_data(self,*args, **kwargs):
context = super(ClassDetailView, self).get_context_data(*args,**kwargs)
context['class_wise_std'] = StudentInfo.objects.filter(
student_class_name__class_name__startswith=self.model.slug)
return context
this is class details html page
{% extends "result/base.html" %}
{% block title %}Class Detail's List{% endblock title %}
{% block content %}
<div class="row">
{% for object in class_wise_std %}
<div class="col-lg-12 col-sm-offset-4" style="margin:20px 10px">
<p>Name: {{object.student_name}}</p>
<p>Class: {{object.student_class_name}}</p>
<p>Father's Name: {{object.student_father_name}}</p>
<p>Mother's Name: {{object.student_mother_name}}</p>
<p>Roll: {{object.student_roll}}</p>
</div>
{% endfor %}
</div>
{% endblock content %}
this code
def get_context_data(self,*args, **kwargs):
context = super(ClassDetailView, self).get_context_data(*args,**kwargs)
context['class_wise_std'] = StudentInfo.objects.filter(
student_class_name__class_name__startswith=self.model.slug)
return context
I found this problem happen with this code. I want to filter with class_name field in ClassName Model.
StudentInfo.objects.filter(student_class_name__class_name__startswith=self.model.slug)
But I can successfully query my targeted info this way.
StudentInfo.objects.filter(student_class_name__class_name__startswith='One')
But It is not an efficient way. Now, How can I implement dynamically this?

Categories

Resources