Here is my view
class SingleNewsView(ListView):
model = News
form_class = SearchForm
template_name = "single_news.html"
def get(self, request, pk, **kwargs):
self.pk = pk
self.pub_from = request.GET.get('pub_date_from',False)
self.pub_to = request.GET.get('pub_date_to',False)
self.crawlers = request.GET.get('crawler',False)
print self.crawlers
return super(SingleNewsView,self).get(request,pk, **kwargs)
def get_context_data(self, **kwargs):
context = super(SingleNewsView,self).get_context_data(**kwargs)
context["form"] = SearchForm#(self.request.GET)
context["something"] = News.objects.filter(category_id=self.pk).filter(published_date__range=(self.pub_from,self.pub_to), crawler=self.crawlers)
return context
Here when I enter into the page it doesnot show any news because to data are not provided. I want all the news to be displayed initially and when the user submit the form then only filter work. How can I do that ??
You should add get_queryset() method than the doing filtering in get_context_data(). You can add the method as below
def get_queryset(self):
qs = News.objects.filter(category_id=self.pk)
#you can change this to just support one of the pub_from or pub_to
if self.pub_from and self.pub_to :
qs = qs.filter(published_date__range=(self.pub_from,self.pub_to)
if self.crawler:
qs = qs.filter(crawler=self.crawlers)
Related
How can I make transitions to the next article from the post_details(DetailView), so that both the next article and the previous one are available ?
vievs.py
class HomeView(ListView):
model = Post
#queryset = Post.objects.filter(status=1)
cats = Category.objects.all()
template_name = 'home.html'
#ordering = ['-post_date']
paginate_by = 6
def get_context_data(self, *args, **kwargs):
cat_menu = Category.objects.all()
context = super(HomeView, self).get_context_data(*args, **kwargs)
context["cat_menu"] = cat_menu
return context
class ArticleDetailView(HitCountDetailView):
model = Post
template_name = 'post_detail.html'
count_hit = True
def get_context_data(self, *args, **kwargs):
cat_menu = Category.objects.all()
context = super(ArticleDetailView, self).get_context_data(*args, **kwargs)
stuff = get_object_or_404(Post, id=self.kwargs['pk'])
total_likes = stuff.total_likes()
context["cat_menu"] = cat_menu
context["total_likes"] = total_likes
return context
Sort by date and ID
If you want the previous or next item based on a DateTimeField, you can work with .get_previous_by_fieldname(…) [Django-doc] or .get_next_by_fieldname(…) [Django-doc]. You thus can obtain the previous/next item for stuff with:
try:
prev_stuff = stuff.get_previous_by_post_date()
except Stuff.DoesNotExist:
prev_stuff = None
try:
next_stuff = stuff.get_next_by_post_date()
except Stuff.DoesNotExist:
next_stuff = None
I am having one issue with the django template view.
I am having two urls
1) For Current User Profile
2) For His Team mates
urls.py
path('profile/', views.UserprofileIndex.as_view(), name='user-profile'),
path('profile/<int:pk>', views.TeamProfileIndex.as_view(), name='team-profile'),
It's views
class TeamProfileIndex(TemplateView):
template_name = 'accounts/profile/team_profile.html'
def get_context_data(self, **kwargs):
context = dict()
self.pk = self.kwargs.get("pk")
try:
user_profile = Profile.objects.get(user=self.pk)
except Profile.DoesNotExist:
logger.error("Requested user profile not available")
raise Http404
teams = User.objects.all()
context.update(
{
'user_profile': user_profile,
'teams' : teams
}
)
return context
class UserprofileIndex(TemplateView):
template_name = 'accounts/profile/index.html'
def get_context_data(self, **kwargs):
context = dict()
try:
user_profile = Profile.objects.get(user=self.request.user)
except Profile.DoesNotExist:
logger.error("Requested user profile not available")
raise Http404
teams = User.objects.all
context.update(
{
'user_profile': user_profile,
'teams' : teams
}
)
return context
In both views only one query is changing , that is 'user_profile'.
Is there any way to pass this in a single views to two diffrent html pages ?
I have tried following method
class UserprofileIndex(TemplateView):
# template_name = 'accounts/profile/index.html'
def initialize(self, *args, **kwargs):
self.pk = None
self.pk = kwargs.get('pk')
def get_template_names(self, *args, **kwargs):
if self.pk:
return 'accounts/profile/team_profile.html'
else:
return 'accounts/profile/index.html'
def get_context_data(self, **kwargs):
context = dict()
try:
if self.pk:
user_profile = UserProfile.objects.get(user=self.pk)
else:
user_profile = Profile.objects.get(user=self.request.user)
except Profile.DoesNotExist:
logger.error("Requested user profile not available")
raise Http404
teams = User.objects.all()
context.update(
{
'user_profile': user_profile,
'teams' : teams
}
)
return context
But its not working
This will work. But I would advise using DetailView
class UserProfile(TemplateView):
"""
User profile view
"""
user_profile = None
template_name = 'accounts/profile/index.html'
team_profile_template_name = 'accounts/profile/team_profile.html'
def get_user_profile(self):
"""
Get user
"""
if not self.user_profile:
user_profile_pk = self.kwargs.get('pk')
model, filter_kwargs = (UserProfile, dict(user=user_profile_pk)) \
if user_profile_pk else (Profile, dict(user=self.request.user))
self.user_profile = get_object_or_404(model, **filter_kwargs)
return self.user_profile
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update(dict(user_profile=self.get_user_profile(),
teams=User.objects.all()))
return context
def get_template_names(self):
if self.kwargs.get('pk'):
return [self.team_profile_template_name]
return super().get_template_names()
If you want to use two template in signle class based view
Do something like this which i do for
DetailView
class PollDetail(DetailView):
model = Poll
context_object_name = "poll"
Instead mentioning template name in Class mention it in urls
ulrs.py
path("result/<pk>",PollDetail.as_view(template_name="results.html")),
path("vote/<pk>",PollDetail.as_view(template_name="vote.html"))
I am new in Django (1.9)
I have a NOT NULL constraint failed when I save my ModelForm and i don't understand why ...
I propose to the user a form to post a comment and the only field include in the form is "text", i want to set the excluded fields in my view after the validation and before save in database
Models.py :
class Commentaire(models.Model):
text = RichTextField()
pub_date = models.DateTimeField()
author = models.ForeignKey(User)
post = models.ForeignKey(Post)
publish = models.BooleanField()
def __str__(self):
return "/%s/%s" % (self.pub_date,self.author.username)
class Meta:
ordering = ["-pub_date"]
Forms.py :
class CommentaireForm(forms.ModelForm):
class Meta:
model = Commentaire
fields = ['text']
Views.py :
class PostDetail(View):
def get(self, request, *args, **kwargs):
view = PostDisplay.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = PostComment.as_view()
return view(request, *args, **kwargs)
class PostDisplay(DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super(PostDisplay, self).get_context_data(**kwargs)
context['form'] = CommentaireForm()
return context
class PostComment(SingleObjectMixin, FormView):
template_name = 'blogengine/post_detail.html'
form_class = CommentaireForm
model = Post
def post(self, request, *args, **kwargs):
#if not request.user.is_authenticated():
# return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
"""
If the form is valid, redirect to the supplied URL
"""
form.save(commit=False)
form.post = self.object
form.author = self.request.user
form.pub_date = datetime.now()
form.publish = True
form.save()
return HttpResponseRedirect(self.get_success_url())
When Django save the form, i have this exception :
NOT NULL constraint failed: blogengine_commentaire.pub_date
The values i set for the excluded fields (author, post, pub_date) in "form_valid" are not taken into account, they seem to stay NULL
Could you explain me why because i am lost ?
Thanks
You need to rewrite form_valid method like that
def form_valid(self, form):
"""
If the form is valid, redirect to the supplied URL
"""
model_instance = form.save(commit=False)
model_instance.post = self.object
model_instance.author = self.request.user
model_instance.pub_date = datetime.now()
model_instance.publish = True
model_instance.save()
return HttpResponseRedirect(self.get_success_url())
Because save(commit=False) will return you an Post instance that you then need to populate and save.
May be someone know, can i use Multiple object mixins with get method in my view? I understand that i need to specify queryset. But can i do this from method?
class Search(MultipleObjectMixin, View):
paginate_by = 2
def get(self, request, *args, **kwargs):
name = request.GET.get('name')
products = Product.objects.filter(name__contains=name)
self.queryset = products
category = Category.objects.all()
return render(request, 'search_results.html', {'main_list': products,
'category_list': category, 'name': name,
'matches': len(products)})
A better solution to what you are trying to accomplish is going to be to use a TemplateView or a ListView you are effectively not even using the MultipleObjectMixin in your example.
Here is an example with just a TemplateView without paging
class SearchView(TemplateView):
template_name = 'search_results.thml'
def get_context_data(self, **kwargs):
context = super(SearchView, self).get_context_data(**kwargs)
name = self.request.GET.get('name', '')
products = Product.objects.filter(name__contains=name)
context['main_list'] = products
context['category_list'] = Category.objects.all()
context['name'] = name
context['matches'] = products.count()
return context
Here is an example with a ListView, which I recommend since it uses the MultipleObjectMixin with it, but saves you some work.
class SearchView(ListView):
template_name = 'search_results.html'
model = Product
context_object_name = 'main_list'
def get_context_data(self, **kwargs):
context = super(SearchView, self).get_context_data(**kwargs)
context['category_list'] = Category.objects.all()
context['name'] = self.request.GET.get('name', '')
context['matches'] = self.get_queryset().count()
return context
def get_queryset(self):
qs = super(SearchView, self).get_queryset()
name = self.request.GET.get('name', '')
return qs.filter(name__contains=name)
You can even go a step further and create a CategoryMixin so you can inherit it in other views so you just add it in to get a list of categories
class CategoryMixin(object):
def get_context_data(self, **kwargs):
context['category_list'] = Category.objects.all()
return context
class SearchView(CategoryMixin, ListView):
template_name = 'search_results.html'
model = Product
context_object_name = 'main_list'
def get_context_data(self, **kwargs):
context = super(SearchView, self).get_context_data(**kwargs)
context['name'] = self.request.GET.get('name', '')
context['matches'] = self.get_queryset().count()
return context
def get_queryset(self):
qs = super(SearchView, self).get_queryset()
name = self.request.GET.get('name', '')
return qs.filter(name__contains=name)
I have made a search form like this where user can filter the news accroding to published date and the crawlers that they have selected previously.. Here is my form
class SearchForm(forms.Form):
pub_date_from = forms.CharField(label="From",max_length=20)
pub_date_to = forms.CharField(label="To",max_length=30)
crawler = forms.ModelMultipleChoiceField(label="Crawler",queryset=Crawler.objects.filter(created_by=self.request.user)
Here I want the crawler to be shown only the user have selected previously..
Here is my view..
class SingleNewsView(ListView):
model = News
form_class = SearchForm
template_name = "single_news.html"
# def post(self, request, **kwargs):
# print "request"
# form = SearchForm(request.user)
def get(self, request, pk, **kwargs):
#form = SearchForm(request.user)
self.pk = pk
self.pub_from = request.GET.get('pub_date_from',False)
self.pub_to = request.GET.get('pub_date_to',False)
self.crawlers = request.GET.get('crawler',False)
self.format = request.GET.get('format',False)
print self.format
print self.crawlers
return super(SingleNewsView,self).get(request,pk, **kwargs)
def get_context_data(self, **kwargs):
context = super(SingleNewsView,self).get_context_data(**kwargs)
context["form"] = SearchForm
if self.pub_from and self.pub_to and self.crawlers:
qs = News.objects.filter(category_id=self.pk).filter(published_date__range=(self.pub_from,self.pub_to), crawler=self.crawlers)
else:
qs = News.objects.filter(category_id=self.pk)
context["something"] = qs
self.request.session['something_pks'] = [ i.details for i in qs ]
return context
How can I get the current user in form and filter according to current user.. Need help
Just pass the user to form in view as keyword argument.
Just don't pass it on in form init method. Check out this post:
Passing **kwargs to Django Form
you hand over request.user just like user_details are passed into form in that example.
# Your best option is to declare the variable before `__init__`,
# and then set the variable to a form field inside `__init__`:
from django import forms
class MyForm(forms.Form):
location = None
def __init__(self, *args, **kwargs):
self.location = forms.ChoiceField(choices=Locations.objects.filter(user=kwargs.pop('user', None)))
super(MyForm, self).__init__(*args, **kwargs)
# In your class-based view pass self.request.user
# or in a function-based view pass request.user:
def MyView(request)
MyForm(user=request.user)