I am trying to access to the current user information to filter the client's items but I am stuck with an error.
I guess must be a different way to request the information of the current user. I am using this: self.kwargs.request.user.
I got that error when using self.request.user I get this error get_context_data() missing 1 required positional argument: 'user'
My url.py
url(r'^update/(?P<pk>[0-9]+)/$', views.CampaignUpdate.as_view(), name='update_campaign'),
AttributeError at
'dict' object has no attribute 'request'
class CampaignUpdate(generic.UpdateView):
model = Campaign
fields = [.....]
template_name = 'campaign/campaign.html'
success_url = '../../'
def get_context_data(self, *args, **kwargs):
context = super(CampaignUpdate, self).get_context_data(**kwargs)
items = items.objects.get(client= self.kwargs.request.user)
Use the below code to get current user 'Item' object.
class CampaignUpdate(generic.UpdateView):
model = Campaign
fields = [.....]
template_name = 'campaign/campaign.html'
success_url = '../../'
def get_context_data(self, *args, **kwargs):
context = super(CampaignUpdate, self).get_context_data(**kwargs)
context['items'] = Items.objects.get(client= self.request.user)
return context
If you want to get the 'Campaign', you can just access line self.object as its a UpdateView
I changed
def get_context_data(self, *args, **kwargs):
to
def get_context_data(self, form_class=None, **kwargs):
and it worked fine, even though I don't know why...
Related
i am using django version 3 and when i tried to work on model managers i got this error
ModelManager is giving error
models.py
class ProductManager(models.Manager):
def get_queryset(self):
return ProductQuerySet(self.model, using=self._db)
def features(self):
return self.get_queryset().featured()
def get_by_id(self, id):
qs = self.get_queryset().filter(id=id)
if qs.count() == 1:
return qs.first()
return None
views.py
class ProductDetailView(DetailView):
template_name = "Products/details.html"
def get_context_data(self, *args, **kwargs):
context = super(ProductDetailView, self).get_context_data(*args, **kwargs)
print(context)
return context
def get_object(self, *args, **kwargs):
request = self.request
pk = self.kwargs.get('pk')
instance = Product.objects.get_by_id
if instance is None:
raise Http404('Product does not exist')
return instance
error:
AttributeError: 'Manager' object has no attribute 'get_by_id'
Well, the problem is that Django model object querysets don't have a method named 'get_by_id'. You should just use what's provided with Django. This is likely to be what you want:
Product.objects.get(id=1)
Substitute 1 by the id that you want..
I've tried this:
class MyClass(LoginRequiredMixin, UpdateView, ListView):
model = models.my_model
fields = ['first_model_field', 'second_model_field']
template_name = 'app/template_name.html'
extra_context = {'second_model': models.second_model.objects.get(pk=self.kwargs['pk']),#didn't work
'third_model':models.third_model.objects.get(pk='pk'),#didn't work
'fourth_model':models.fourth_model.objects.get(foreign_key_id = 'unique_kwarg')}#didn't work.
I also have url's that contain both the /<int:pk>/ kwarg and the /<int:unique_kwarg>/ kwarg.
I am having trouble figuring out how to reference the url **kwarg object.
def form_valid(self, form):
form_template_id = self.kwargs.get(self.pk_url_kwarg)
form.instance.model_id = model.objects.get(pk=form_template_id)
return super().form_valid(form)
and
def get_context_data(self, **kwargs):
"""Insert the form into the context dict."""
if 'unique_kwarg' not in kwargs:
kwargs['unique_kwarg'] = (self.kwargs.get(self.unique_kwarg))
kwargs['model_id'] = (model.objects.get(id=self.kwargs.get(self.unique_kwarg)))
return super().get_context_data(**kwargs)
I am building a view that I am passing in a uuid from the url. However when I try to access the kwarg, I get a "AttributeError: view object has no attribute 'kwargs'" error.
In my template, I am passing a UUID:
create/97261b96-23b8-4915-8da3-a90b7a0bdc8e/
The URL:
re_path(
r"^create/(?P<uuid>[-\w]+)/$",
views.DetailCreateView.as_view(),
name="detail_create"),
The View:
class DetailCreateView(SetHeadlineMixin, LoginRequiredMixin, InlineFormSetView):
inline_model = Detail
headline = "Create a Detail"
form_class = DetailForm
success_message = "Detail Added"
template_name = "details/detail_create.html"
def get_object(self, **kwargs):
return Post.objects.get_subclass(uuid=self.kwargs.get('uuid'))
def __init__(self, *args, **kwargs):
super(DetailCreateView, self).__init__(*args, **kwargs)
self.object = self.get_object()
self.model = self.object.__class__()
For context on what is happening -
Post is a model that is an InheritanceManager that other models (Product & Variation) inherit from.
Both models Product & Variation have a manytomanyfield to Detail.
Upon creating a Detail, I will be adding it to either the Product object or Variation object.
To set the model for the InlineFormSetView, I am trying to use the UUID to query for the object and dynamically set that based upon the class of the object I am trying to create a Detail for.
Question
Any ideas why I can't access the kwargs which is being sent in the URL path?
In as_view method kwargs and args attributes are assigned to the view after __init__ method. So when you call get_object inside __init__ it raises the error since self.kwargs is not assigned yet. To fix this error you can move
self.object = self.get_object()
self.model = self.object.__class__()
from __init__ to get_object:
class DetailCreateView(SetHeadlineMixin, LoginRequiredMixin, InlineFormSetView):
inline_model = Detail
headline = "Create a Detail"
form_class = DetailForm
extra = 10
success_message = "Detail Added"
template_name = "details/detail_create.html"
def get_object(self, **kwargs):
self.object = Post.objects.get_subclass(uuid=self.kwargs.get('uuid'))
self.model = self.object.__class__()
return self.object
def __init__(self, *args, **kwargs):
super(DetailCreateView, self).__init__(*args, **kwargs)
Try to use self.request.query_params.get('uuid')
How can I get 'pk' or 'id' in get_context_data from CBV DetailView?
class MyDetail(DetailView):
model = Book
template_name = 'book.html'
def get_context_data(self, **kwargs):
context = super(MyDetail, self).get_context_data(**kwargs)
context['something'] = Book.objects.filter(pk=pk)
return context
url:
url(r'^book/(?P<pk>\d+)/$', MyDetail.as_view(), name='book'),
You can get it from self.kwargs['pk'].
I'm not sure why you want to, though, since the superclass already gets the Book corresponding to that pk - that's the whole point of a DetailView.
class MyDetail(DetailView):
model = Book
template_name = 'book.html'
def get_context_data(self, **kwargs):
context = super(MyDetail, self).get_context_data(**kwargs)
context['something'] =Book.objects.filter(pk=self.kwargs.get('pk'))
return context
self.kwargs['pk'] it doesn't work in Django 2.2
in DetailView
self.object is the object that this view is displaying.
So, to access the object's fields like id or pk just self.object.id or self.object.pk
So, The answer in Django 2.2 can be like:
class MyDetail(DetailView):
model = Book
template_name = 'book.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['something'] = Book.objects.filter(pk=self.object.pk) # <<<---
return context
Django 2.2 Doc
In get_context_data you already have the object in self.object (and you can do self.object.pk). Here's what happens upstream in the class hierarchy (DetailView inherits from BaseDetailView):
class BaseDetailView(SingleObjectMixin, View):
"""
A base view for displaying a single object
"""
def get(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
Reading Django source code to understand stuff is incredibly easy.
And by the way, I am not sure you can always rely on the fact that kwargs has a 'pk' key.
In addition to getting it from self.kwargs as Daniel Roseman suggested, you can use self.get_object().pk, for example if you change your URL identifier from pk to, say, slug or something.
you can simply get it in the 'get' method, like this:
def get_context_data(self, request, pk, *args, **kwargs):
context = super(MyDetail, self).get_context_data(**kwargs)
context['something'] =Book.objects.filter(pk=self.kwargs.get('pk'))
return context
def get_context_data(self, request, pk, *args, **kwargs):
context = super(MyDetail, self).get_context_data(**kwargs)
context['something'] =Book.objects.filter(pk=self.kwargs.get('pk'))
return context
Filter returns a query set that matches the lookup parameter (pk). Since 'pk' is unique, it would return the same results as get but for performance issues, ideally you'd want to use the get method to return one single object:
def get_context_data(self, request, pk, *args, **kwargs):
context = super(MyDetail, self).get_context_data(**kwargs)
context['something'] =Book.objects.get(pk=self.kwargs.get('pk'))
return context
I need to display a detail page for a video with some other data.
For that I use DetailView that I have overridden to add some variables to the context.
Here are the code parts:
#urlconf
#...
(r'viewtube/(?P<pk>\d+)$', VideoFileDetailView.as_view()),
#...
#view
class VideoFileDetailView(DetailView):
model = VideoFile
def get_context_data(self, **kwargs):
context = super(VideoFileDetailView, self).get_context_data(**kwargs)
# context['rates'] = VideoRate.objects.filter(video=11, user=1)
return context
Here pk is the id of a video, I need to get the rates of the selected video by the current user.
It would have been useful to show the models. But I think you need to override get(), not get_context_data, as unfortunately the latter doesn't get passed the request, which you need in order to get the user. So:
def get(self, request, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
context['rates'] = VideoRate.objects.filter(video=self.object, user=request.user)
return self.render_to_response(context)
The request should be accessible at self.request. self.request is set at the beginning of the request (in View.dispatch) and should be available any of the subclass methods.
class VideoFileDetailView(DetailView):
model = VideoFile
def get_context_data(self, **kwargs):
context = super(VideoFileDetailView, self).get_context_data(**kwargs)
context['rates'] = VideoRate.objects.filter(video=11, self.request.user)
# note that the object is available via self.object or kwargs.get("object")
return context