Django Queryset to search for article title - django

I aim to search for the article title using a query set, I am following this 'basic filtering' guide however it doesn't work for me.
terminal traceback-
AttributeError: 'DeferredAttribute' object has no attribute 'filter'
views.py
class SearchResultsView(ListView):
model = Article
template_name = 'search_results.html'
queryset = Article.title.filter(name__icontains='1st')
I tried using queryset = Article.objects.filter(name__icontains='1st') however this resulted in the below which is why I used 'title' rather than 'objects'
File "/Users/Lucas/Python/Projects/news/.venv/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1677, in names_to_path
raise FieldError(
django.core.exceptions.FieldError: Cannot resolve keyword 'name' into field. Choices are: author, author_id, body, comment, date, id, title
models.py
class Article(models.Model):
title = models.CharField(max_length=225)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("article_detail", kwargs={"pk": self.pk})
I looked at this but can't get it to work. Also tried the documentation.
If i remove the query set line at the bottom of the class the search function returns all of the values as per the below .html file. Which displays all the article content but without any filters of course.
search_results.html
<ul>
{% for article in article_list %}
<li>
{{ article.title }}, {{ article.body }} {{ article.date }}{{ article.author }}
</li>
{% endfor %}
</ul>
Am I missing something from the model perhaps?
Thanks.

Try:
queryset = Article.objects.filter(title__icontains='1st') in SearchResultsView
The error mentions that you do not have name field. Since you are using title field, you need to use that instead.

Related

How I can get the pk in the home view www.mywebsite.com

I tried to get the pk from this function def home_view(request, pk): but because this in home view www.site.com it return error home_view() missing 1 required positional argument: 'pk' so it is didn't worked with me
My qustion is how I can pass pk to the template that in website domain without any extra urls like this
www.site.com
My view
def home_screen_view(request, pk, *args, **kwargs):
post= Post.objects.filter(pk=pk) #here I want to get the pk
comment = PostCommentIDF.objects.filter(post=post)
return render(request, 'personal/home.html', {'comment': comment)
My Urls
path('', home_screen_view, name='home'),
Edit
Firstly I return my posts using list [], I need the pk of the post because the comment model is separate from the post model so I use the pk to use in this function
posts = Post.objects.filter(pk=pk)
comment = PostCommentIDF.objects.filter(post=post)
post = []
for u in users:
p = Account.objects.get(username=u)
posts = p.post_set.all()
p_posts = p.video_set.all()
post .append(p_posts)
my_posts = request.user.post_set.all()
post.append(my_posts)
if len(post):
post = sorted(chain(*post), reverse=True, key=lambda post: post.created_date)
My comment MPTT model
class PostCommentIDF(MPTTModel):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='pos_com')
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='post_children')
author = models.ForeignKey(Account, on_delete=models.CASCADE)
content = models.TextField()
created_date = models.DateTimeField(auto_now_add=True)
My Post Model
class Post(models.Model):
author = models.ForeignKey(Account, on_delete=models.CASCADE)
article = models.TextField(null=True, blank=True)
photo_article = models.ImageField(max_length=255, upload_to=get_poster_filepath)
created_date = models.DateTimeField(auto_now_add=True)
My template that related to render the comments
{% recursetree video.total_comts %}
<div id="{{ node.id }}" class="my-2 p-2" style="border: 0px solid grey">
<div class="d-flex justify-content-between">
{{ node.publish|naturaltime }}
<div class="node-content mt-3">{{ node.content }}</div>
</div>
{% endrecursetree %}
Solution One
As you do not pass the pk information from url, you can't use pk in the view. So change the view to:
def home_screen_view(request):
#rest of the code
Instead of pk, if you want to see the logged in user's posts, you can use:
def home_screen_view(request):
posts = Post.objects.filter(account__user=request.user) # assuming there is a FK relation in Account model.
Solution Two
Also, you can't find pk arbitarily in the home view at / url, unless you pass it like /12/, if you pass that value then you need to update url code:
path('<int:pk>/', home_screen_view, name='home'),
Solution Three
You can use url querystring to get the primary key:
def home_screen_view(request):
pk = request.GET.get('pk', None)
posts = Posts.objects.all()
if pk:
posts = posts.filter(pk=pk)
Then use the browser url should look like https://example.com/?pk=1.
Update
If you want to get post specific comments, then you can use following solution:
# view
def home_screen_view(request):
return render(request, 'personal/home.html', {'posts': Post.objects.filter(author__user=request.user)})
# template
{% for post in posts %}
{% for comment in post.comment_set.all %} // if you use related_name in PostCommentIDF then you need to use post.<related_name>.all
{{ comment }}
{% endfor %}
{% endfor %}

django: display UpdateView in language defined by the object

I have a django project where I would like to display an UpdateView of a ModelForm in the language which is defined by the model itself. I would like to avoid using i18n patterns in the URL.
The object to be displayed is identified via an UUID provided in the URL of the form
http://name.tld/submit/55dbf53c-9364-4938-873f-6abad2e4ed45
I have:
Model:
class MyModel(models.Model):
unique_id = models.UUIDField(
default=uuid.uuid4,
editable=False,
unique=True,
verbose_name=_("UUID Field")
)
language = models.CharField(
default = "en",
max_length=7,
choices=settings.LANGUAGES,
verbose_name=_("Selected language")
)
ModelForm:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
localized_fields = '__all__'
fields = '__all__'
UpdateView:
class MyModelUpdate(UpdateView):
model = MyModel
form_class = MyModelForm
template_name_suffix = '_form'
def get_object(self, **kwargs):
# get the uuid and find the corresponding object
obj = MyModel.objects.filter(unique_id=self.kwargs.get('uuid')).first()
if not obj or obj.is_answered:
raise Http404("Page not found")
else:
translation.activate(obj.language)
return obj
def get_success_url(self):
return reverse('submit-success')
Template:
{% load i18n %}
{% trans alert %}
<h2>{% trans "My great translated UpdateView" %}</h2>
<form action="" method="post">
{% csrf_token %}
{% form %}
</form>
However, despite providing the translated strings in the PO files (created using django-admin makemessages and django-admin compilemessages the page always shows up in English (my browser language, that is).
What am I missing?

Django select_related FK model

I'm trying to list all the objects that are in Movie model that are Genre ForeignKey related say comedy genre list all Movie objects related to comedy
# models.py
class Genre(models.Model):
name = models.CharField(max_length=80, unique=True)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return reverse("genres:list", kwargs={"slug": self.slug})
class Movie(models.Model):
title = models.CharField(max_length=80)
genre = models.ForeignKey(Genre)
# views.py
def genre_list(request, slug):
instance = get_object_or_404(Genre, slug=slug)
movies = Movie.objects.select_related('genre').all()
context = {
"objects_list": movies,
}
return render(request, 'genres/genres_list.html', context)
template view genres/genres_list.html
{% for obj in objects_list %}
<div class="box">
<b>{{ obj.title }}</b>
</div>
{% endfor %}
nothing turns up what am I doing wrong?
Your variable name in the context, object_list, doesn't match the variable name in the template, objects_list.
context = {
"object_list": shows,
}
{% for obj in objects_list %}
You need to use the same variable name in both places. I would recommend object_list because it is more common in Django, however something descriptive like movies would be even better.
Finally, if you want to select all the movies in a particular genre, then you should use filter.
instance = get_object_or_404(Genre, slug=slug)
movies = Movie.objects.filter(genre=instance)
You are currently using select_related, which does something different.

Django foreign key user has no attribute post_set

I've got these two models.
class UserProfile(models.Model):
user = models.OneToOneField(User)
THIS SHOULD BE
def posts(self):
return self.user.poster.all()
INSTEAD OF
def posts(self):
return self.user.post_set.all()
def __unicode__(self):
return self.user.username
class Post(models.Model):
author = models.ForeignKey(User, related_name='poster')
def __unicode__(self):
return self.title
and I'm attempting to display all posts by a user on this html page, where user_list = UserProfile.objects.all()
{% for user in user_list %}
{{ user.user }}
{{ user.posts }}
{% endfor %}
However, I'm being greeted by this error page that says 'UserProfile' object has no attribute 'post_set', or 'UserProfile' object has no attribute 'post_set', depending on if I use user.user.posts or user.posts.
Anyone have any ideas?
Thanks
In your Post class you have defined the related name of your ForeignKey to User as poster. This means you can access all of a user's posts through user.poster.all().
So your the posts method of your UserProfile class should be as follows:
def posts(self):
return self.user.poster.all()
In you example User does not have post_set attribute. If you want to get all posts for related User try this:
self.user.post.all()

Creating Tag Index Django

Im using django-taggit to create a tagging system for a blog. How do you separate and filter objects so that only ones with selected tags are shown? Kind of like how on StackOverflow if you click on django
it will give you all the questions tagged django. I have tried the method described on this blog post, but I get an IndexError: tuple index out of range. This is the code I am using:
url(r'^tagged/(?P<tag>[\w-]+)/$', TagView.as_view(), name='tag_url'),
class TagView(ListView):
context_object_name = 'blog'
template_name = 'links/index.html'
def get_queryset(self):
return Blog.objects.filter(tags__name__in=[self.args[0]])
def get_context_data(self, **kwargs):
context = super(TagView, self).get_context_data(**kwargs)
context['requested_tag'] = self.args[0]
return context
<a href='{% url tag_url tag=tag %}'>{{ tag.name }}</a>
Am I missing something to get this method to work?
It seems like this is a pretty common programming necessity. Maybe you know a better method... Thanks for your ideas!
EDIT: TagView based on #catherine's suggestions:
class TagView(ListView):
model = Blog
context_object_name = 'blog_list'
template_name = 'tag-list.html'
def get_queryset(self):
queryset = super(TagView, self).get_queryset()
return queryset.filter(tags__name__in=self.kwargs['tags'])
class Blog(models.Model):
name = models.CharField(max_length=50)
date = models.DateTimeField()
slug = models.SlugField()
article = models.TextField()
tags = TaggableManager()
def __unicode__(self):
return self.name
tag-list.html:
{% block content %}
stuff
{% for blog in blog_list %}
{{ blog.article }}
{{ blog.name }}
{% endfor %}
{% endblock %}
The blog_list does not exist in the template, and no blog objects are available. Rather, only 'stuff' is rendered to the template. Any ideas are appreciated! Thanks!
class TagView(ListView):
model = Blog
......
def get_queryset(self):
# Fetch the queryset from the parent get_queryset
queryset = super(TagView, self).get_queryset()
return queryset.filter(tags__name__in=self.kwargs['tag'])
This answer is based on "EDIT: TagView based on #catherine's suggestions:".
You have a typo, in get_queryset method:
return queryset.filter(tags__name__in=self.kwargs['tags'])
you use tag and not tags thus it should be:
return queryset.filter(tags__name__in=[self.kwargs['tag']])