I am trying to annotate a queryset so that a button can appear in the home page (Listview) what there are posts more than one and when there Posts are admin_approved=True
So far the I have reached when there items in the list view with designers related to each item and in the for each post there is a user, in the queryset it checks if there posts related to the designer and these posts should by approvedby_Admin=True so that the button appears.
The issue is that when a user has 2 posts one which is approved and another not approved, 2 items appears and duplication takes place in the homepage List view
I have tried to use .distinct() but it didn't work items are still duplicated
Here is the models.py
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100, unique=True)
admin_approved = models.BooleanField(default=False)
here is the views
from .models import Item
from django.db.models import Case, When, BooleanField, Q
class HomeView(ListView):
model = Item
paginate_by = 12
template_name = "home.html"
ordering = ['-timestamp']
def get_queryset(self):
has_post = Case(
When(Q(designer__post__isnull=False) & Q(designer__post__admin_approved=True), then=True),
default=False,
output_field=BooleanField()
)
return super().get_queryset().annotate(has_post=has_post).distinct()
here is the template
{% for item in object_list %}
{{ item.title }}
{% if item.has_post %}
SHOW BUTTON
{% else %}
HIDE BUTTON
{% endif %}
{% endfor %}
here is the item model
class Item(models.Model):
designer = models.ForeignKey(
User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
In Conditional Expressions, you are not passing value when condition evaluates to True,
has_post = Case(
When(designer__post__isnull=False,
then=True
default=False,
output_field=BooleanField()
)
Read more at https://docs.djangoproject.com/en/3.0/ref/models/conditional-expressions/
Related
This might be a rookie problem but I cannot find a way around it.
I am trying to implement add recipe to favourites.
The view and model work properly as when I hit the button once it sends the request and adds the recipe to the user's favourites. Then when clicked again it removes it correctly from the database.
Alas now when i try to make visible on the template I ran into trouble with the template language.
I cannot find a way to check if the current user's profile has liked the paginated recipe.
I have the following class based list view
class Home(ListView):
model = Recipe
template_name = 'home.html'
paginate_by = 2
def get_queryset(self):
return Recipe.objects.order_by('id').prefetch_related('profile__recipecomment_set__recipe')
and the following Recipe model
class Recipe(models.Model):
title = models.CharField(
max_length=TITLE_MAX_LENGTH,
validators=(
MaxLengthValidator(TITLE_MAX_LENGTH),
MinLengthValidator(TITLE_MIN_LENGTH),
),
null=False,
blank=False,
)
profile = models.ForeignKey(
Profile,
on_delete=models.RESTRICT,
null=False,
blank=True,
editable=False,
)
favourites = models.ManyToManyField(
Profile,
related_name='favourite',
default=None,
blank=True,
)
the template.html is as follows, this is the code that doesn't work
{% for recipe in page_obj %}
{% if request.user.profile.id in recipe.favorites %}
<button>Recipe added to favourites</button>
{% else %}
<button>Add to favourites</button>
{% endif %}
{% endfor %}
the pagination works, everything else is working except that I cannot check if the user has added each recipe to his favourites or not.
At last I found an answer myself.
It might not be the best but it works.
In the Home view I added a static method that checks each item in the context object_list and adds an attribute that later can be used inside the template.
#staticmethod
def is_in_favourites(request, recipe):
if request.user.is_authenticated:
return True if recipe.favourites.filter(id=request.user.profile.id).exists() else False
return False
def get_context_data(self, *, object_list=None, **kwargs):
ctx = super().get_context_data(object_list=object_list, **kwargs)
for i in ctx.get('object_list'):
i.is_in_favourites = self.is_in_favourites(self.request, i)
return ctx
I have a list of users and want to display their tasks only if the selected user belongs to the same department. My Models have a department field that I want to compare.
This is my template code.
{% extends 'view_users.html' %}
{% block view_user_tasks %}
Back
<p> todo lists for {{ user }}</p>
{% for todo in view_user_tasks %}
<a id="{{todo.id}}" class="todo_remove"></a>
{% endfor %}
{% endblock view_user_tasks %}
What i want to do is evaluate this condition:
if request.user.Department == user.Department:
show user tasks
This are my respective views.
class ViewUsers(ListView):
model = CustomUser
template_name = 'view_users.html'
class ViewUserTasks(ListView):
model = Todo
template_name = 'view_user_tasks.html'
context_object_name = 'view_user_tasks'
My models.py
class Todo(models.Model):
title = models.CharField(max_length=30)
body = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
checked = models.BooleanField(default=False)
owner = models.ManyToManyField(CustomUser)
id = HashidAutoField(primary_key=True)
def __str__(self):
return "%s: %s" % (self.title, self.body)
class CustomUser(AbstractUser):
Department = models.CharField(max_length=30, blank=True)
How can I be able to accomplish this?
Do your filtering logic in the view. You can override the default get_queryset method and return only the Todos that you want.
class ViewUserTasks(ListView):
template_name = 'view_user_tasks.html'
context_object_name = 'view_user_tasks'
def get_queryset(self):
return Todo.objects.filter(user__Department=self.request.user.Department)
And then just loop through the returned data like you are already doing.
If I clearly understand your question, you can compare it like this:
{% if todo.user.id == user.id %}
Intro: I have a 3 models user, post, group. User is able to make posts however each post has to belong to a group. Users have to choose from the existing groups for their posts. Users cannot add, delete, update group's.
Furthermore:
Users can become a member of groups and when they click on a certain group. They see all the posts in that group.
What I want When Users come on the home page they see posts that were added since the last time they logged in
My Models
class Post(models.Model):
user = models.ForeignKey(User, related_name='posts')
group = models.ForeignKey(Group, related_name='posts')
title = models.CharField(max_length=250, unique=True)
message = models.TextField()
created_at = models.DateTimeField(auto_now=True)
My Views
class Homepage(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context = super(Homepage, self).get_context_data(**kwargs)
context['object_list'] = Group.objects.all()
context['post_list'] = Post.objects.order_by("-created_at")
#What am I doing wrong in the below code
if self.request.user.is_authenticated():
new_posts = Post.objects.filter(created_at__gt(self.request.user.last_login))
context['new_posts'] = new_posts.count()
return context
In my templates I have
<div class="list-group">
{% for group in object_list %}
{{group.name}}
{% if new_posts > 0 %}
{{new_posts}} new
{% endfor %}
</div>
NameError: name 'created_at__gt' is not defined
The error is because of you've missed a Equal to symbol,
new_posts = Post.objects.filter(created_at__gt = self.request.user.last_login)
^^^ here
I have a Django project where a user can re post other users posts by creating a relationship between the user and the post itself. But when I display this on my template, I want the tweets that have been re posted to have a different link next to them in order to un repost but instead with my current set up it still has the re post link, so I was just wondering how I could see if a relationship exists in a Django template as part of my conditional.
template
{% for tweets in combined_tweets %}
<p>{{ tweets.userprofile.user}} | {{ tweets }} | {{ tweets.date }} |
{% if tweets.userprofile.user == request.user %}
<a href='{% url "delete_tweet" request.user.id tweets.id %}'>DELETE</a>
{% elif ###Something to check if realtionship exists### %}
UN REPOST LINK
{% else %}
<a href='{% url "retweet" tweets.id %}'>RETWEET</a>
{% endif %}</p>
{% endfor %}
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
bio = models.CharField(max_length=120, blank=True, verbose_name='Biography')
follows = models.ManyToManyField('self', related_name='followers', symmetrical=False, blank=True)
theme = models.ImageField(upload_to=get_image_path, blank=True)
profile_picture = models.ImageField(upload_to=get_image_path, blank=True)
def __str__(self):
return self.bio
class Tweet(models.Model):
userprofile = models.ForeignKey(UserProfile)
retweet = models.ManyToManyField(UserProfile, related_name='retweet_people', symmetrical=False, blank=True)
tweets = models.TextField(max_length=120)
date = models.DateTimeField()
You can check that a relationship exists between the current user and other user tweets using a custom template filter.
We will write a custom template filter check_relationship_exists which will take the current user as the argument. This will check if the current tweet object is related to the user passed by performing a filter on its retweet attribute using user.id. If there exists a relationship, then the UN REPOST link will be displayed otherwise a RETWEET link will be shown.
from django import template
register = template.Library()
#register.filter(name='check_relationship_exists')
def check_relationship_exists(tweet_object, user):
user_id = int(user.id) # get the user id
return tweet_object.retweet.filter(id=user_id).exists() # check if relationship exists
Then in your template, you can do the following:
{% elif tweets|check_relationship_exists:request.user %}
I'm new in Django and I'm developing an app but I'm stuck in this Error.
First I want to apologize for my English since is not my first language and then I hope I'm in the right place to ask for little help.
I'm developing a website about Publication of articles. The page "Publication" return a list of the model instances - in my case all the publications in the db.
What I'm trying to do is to assign a url to each of the instances of my Model, such that the user can click on it and see the page which is populated with other relevant information of that instance.
To do this I'm using get_absolute_url in my template and DetailView in my view.
The list of all the instance works fine but when I click on each of the instance I run the error 'NoneType' object has no attribute '_default_manager' .
I google already and try to follow some guidelines here and there, and try to find solution in Django doc couldnt figure out the solution...
Here my code:
models.py
class Publications(MPTTModel):
code = models.CharField(max_length=50)
title = models.CharField(max_length=150)
date = models.DateField(null=True)
magazine = models.CharField(max_length=50)
country = models.CharField(max_length=30)
slug = models.SlugField(max_length=150)
img01 = models.ImageField(upload_to="photo", blank=True, null=True)
link = models.URLField(max_length=200, blank=True, null=True)
template = models.ForeignKey("Template", related_name="publications", null=True, blank=True)
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
control_field = models.CharField(max_length=15)
class Meta:
verbose_name_plural = "Publications"
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('mag-publication',args=(self.slug,))
publications.html
{% load mptt_tags %}
{% load sito_tags %}
{% full_tree_for_model myApp.Publications as publications %}
{% for publications,structure in publications|tree_info %}
{% if publications.img01 %}
<div id="title_publication_container">
{{ publications.magazine }}
</div>
{% else %}
....
{% endif %}
{% endfor %}
urls.py
urlpatterns = patterns('',
url(r'^(?P<id_page>\d+)/(?P<slug>[\w-]+)/$', pages,),
url(r'^(?P<id_page>\d+)/(?P<slug_page>[\w-]+)/(?P<id>\d+)/(?P<slug>[\w-]+)/$', projects,),
url(r'^mag-publication/(?P<slug>[\w-]+)/$', PublicationDetailView.as_view() , name='mag-publication'),
)
view.py
class PublicationView(object):
queryset = Publications.objects.all()
class PublicationListView(PublicationView, ListView):
paginate_by = 20
class PublicationDetailView(PublicationView, DetailView):
slug_field = 'slug'
The error show me this Debug informations:
AttributeError at /6/publications/*title_publication*/
**'NoneType' object has no attribute '_default_manager'**
Request Method: GET
Request URL: .../6/publications/*title_publication*/
Django Version: 1.5.4
Exception Type: AttributeError
Exception Value: 'NoneType' object has no attribute '_default_manager'
Exception Location: /home/gabriele/virtual_envs/virt2/lib/python2.7/site-packages/feincms/views/cbv/views.py in get_object, line 20
Python Executable: /home/gabriele/virtual_envs/virt2/bin/python
Maybe the problem has something to do with feincms as it said in the "Exception Location" but everything came out after I tried to work on the instance of the Model.
Thank you for your help.
You probably didn't add feincms.module.page to your INSTALLED_APPS as per the documentation. If you follow the traceback, the error appears in get_object() where it tries to access the page model.
Are you using an older FeinCMS version? Newer versions raise a warning in that case.
Well i don't know for feincms but in your views you have :
class PublicationView(object):
queryset = Publications.objects.all()
class PublicationListView(PublicationView, ListView):
paginate_by = 20
class PublicationDetailView(PublicationView, DetailView):
slug_field = 'slug'
First of all you don't need to set the slug field if his name is already 'slug'.
And an other thing :
You inherit from PublicationView in your PublicationDetailView, but the DetailView need a single object, just try like this in your url file :
url(r'^mag-publication/(?P<slug>[\w-]+)/$', DetailView.as_view(model=Publications) , name='mag-publication')
Off course don't forget to import DetailView and Publications model into your url file.
EDIT 20/08/2014
In your get_absolute_url method you use :
return reverse('mag-publication',args=({'slug':self.slug}))
If you want to use dict for params you must use :
return reverse('mag-publication',kwargs={'slug':self.slug})
And if you want to use args you must do :
return reverse('mag-publication',args=(self.slug,))
I solved part of the problem. I used a combination of get_absolute_url and DetailView.
I can see the perfectly the list of the publications in publication.html but when I click to one of them the app show me - in publications_detail.html - the detail of all the instances of the Model instead only one.
From publications in admin "view on site" it works but there's the same problem, show me all the instances together.
The question is how to catch only one instance. Follow the code :
models.py
class Publications(MPTTModel):
title = models.CharField(max_length=150)
slug = models.SlugField(max_length=150)
img01 = models.ImageField(upload_to="photo", blank=True, null=True)
template = models.ForeignKey("Template", related_name="publications", null=True, blank=True)
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
control_field = models.CharField(max_length=15)
class Meta:
verbose_name_plural = "Publications"
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('mag-publication',args=(self.slug,))
views.py
class PublicationsDetail(DetailView):
queryset = Publications.objects.all()
template_name = 'website/publications_detail.html'
urls.py
url(r'^mag-publication/(?P<slug>[\w-]+)/$', PublicationsDetail.as_view()
publications_detail.html
{% load mptt_tags %}
{% load sito_tags %}
{% full_tree_for_model napeApp.Publications as publications %}
{% for publications,structure in publications|tree_info %}
{% if publications.img01 %}
<div id="title_publication_container">
{{ publications.magazine }}
</div>
{% else %}
....
{% endif %}
{% endfor %}
In my case I just renamed meta to Meta and it solved.maybe it is related to sensitive capital class name