here is the views.py for registration redux. i am a little bit confused and i don't really understand how to pass in context variables.
class RegistrationView(BaseRegistrationView):
SEND_ACTIVATION_EMAIL = getattr(settings, 'SEND_ACTIVATION_EMAIL', True)
success_url = 'registration_complete'
def register(self, request, form):
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
if hasattr(form, 'save'):
new_user_instance = form.save()
else:
new_user_instance = UserModel().objects.create_user(**form.cleaned_data)
new_user = RegistrationProfile.objects.create_inactive_user(
new_user=new_user_instance,
site=site,
send_email=self.SEND_ACTIVATION_EMAIL,
request=request,
)
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=request)
return new_user
BaseRegistrationView inherits from FormView, which has in its inheritance chain django.views.generic.base.ContextMixin. This defines the get_context_data method, which returns context as a dict. You can override that method and add in your own variables like so:
class RegistrationView(BaseRegistrationView):
...
def get_context_data(self, **kwargs):
context = super(RegistrationView, self).get_context_data(**kwargs)
context['key'] = value
return context
Related
I have BaseContext and Listview which is for Searching in multiple models, Search Class inherits from BaseContext. I set the current user to context and want to use it in my def get_queryset method, But it doesn't work. I think in Search CBV get_context_data execute after get_queryset that's why, self.user is None.
class BaseContext(ContextMixin):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
request = self.request
if request.COOKIES.get('token') is not None:
...
user = Users.objects.filter(user_id=user_id).first()
context.update({'current_user': user})
context.update({'is_logged_in ': True})
else:
context.update({'is_logged_in ': False})
return context
class Search(BaseContext, ListView):
template_name = 'search.html'
context_object_name = "results"
paginate_by = 15
user = None
def get_queryset(self):
query = self.request.GET.get('search', None)
if query is not None and self.user is not None:
...
return queryset_chain
return faqModel.objects.none()
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
if 'is_logged_in' in context and context['is_logged_in']:
self.user = context['current_user']
else:
redirect("index")
return context
My question is how can I get context data in def get_queryset(self)?
for Listview get_quersyset() is called before get_contex_data() , hence getting context data is not possible in get_queryset()
I've a Function definition that works perfect, but I need to update to a Class Based View.
function def:
def ProdCatDetail(request, c_slug, product_slug):
try:
product = Product.objects.get(category__slug=c_slug, slug = product_slug)
except Exception as e:
raise e
return render(request, 'shop/product.html', {'product':product})
So far, I've read that to modify the context of a Class Based View (CBV) I need to overwrite the def get_context_data(self, **kwargs) in the CBV.
So, I've done this:
Class Based View:
class ProdCatDetailView(FormView):
form_class = ProdCatDetailForm
template_name = 'shop/product.html'
success_url = 'shop/subir-arte'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['product'] = Product.objects.get(category__slug=c_slug, slug = product_slug)
return context
How should I pass the arguments c_slug, product_slug to the get_context_data definition for this CBV to work as the Function definition?
A class based view is, by the .as_view basically used as a function-based view. The positional and named parameters, are stored in self.args, and self.kwargs respectively, so we can use:
class ProdCatDetailView(FormView):
# ...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['product'] = Product.objects.get(
category__slug=self.kwargs['c_slug'],
slug =self.kwargs['product_slug']
)
return context
I have a view that shows a list of objects that have specific tag.
class AllView(ListView):
context_object_name = 'facts'
template_name = 'facts_blog/all_facts.html'
def get_context_data(self, **kwargs):
context = super(AllView, self).get_context_data(**kwargs)
if 'TagForm' not in context:
context['TagForm'] = TagForm()
return context
def get_queryset(self):
form = TagForm(self.request.GET)
if form.is_valid():
context = RequestContext(self.request)
return self.send_results(form.cleaned_data['tag'])
else:
return Fact.objects.all()
def send_results(self, tag):
return Fact.objects.filter(tags__slug=tag)
I want to return form.cleaned_data['tag'] to template, but i have already used get_context_data... What should I do to do this?
If I'm understanding what you're saying, you want to include the "tag" in your context dict while the ListView queryset will return the "Fact" instances associated with the tag. Correct?
If you look at Django's BaseListView the get method will call get_queryset first, then right before it calls render_to_response it will call your get_context_data method:
class BaseListView(MultipleObjectMixin, View):
"""
A base view for displaying a list of objects.
"""
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
# [snip]
# some code not related to this omitted
# [snip]
context = self.get_context_data()
return self.render_to_response(context)
What you can do is set an attribute (self.object) in your get_queryset method to store the "tag" from your validated form, then retrieve it in your get_context_data method so you can stuff it in the context dict:
def get_queryset(self):
form = TagForm(self.request.GET)
if form.is_valid():
context = RequestContext(self.request)
# set self.object to the "tag"
self.object = form.cleaned_data['tag']
return self.send_results(self.object)
else:
# set self.object to None since the form is not validated
self.object = None
return Fact.objects.all()
def get_context_data(self, **kwargs):
context = super(AllView, self).get_context_data(**kwargs)
if 'TagForm' not in context:
context['TagForm'] = TagForm()
# put self.object in the context dict
context['tag'] = self.object
return context
Your template will then have a var called tag with either the "tag" value or None.
Assuming that the form's action returns to the AllView view via GET request, you can modify the get_context_data in this way:
def get_context_data(self, **kwargs):
context = super(AllView, self).get_context_data(**kwargs)
if 'TagForm' not in context:
context['TagForm'] = TagForm()
tag_form = TagForm(self.request.GET)
if tag_form.is_valid():
context['tag'] = tag_form.cleaned_data.get('tag')
return context
Hope it does the trick.
I have a update view:
class GeneralUserUpdateView(UpdateView):
model = GeneralUser
form_class = GeneralUserChangeForm
template_name = "general_user_change.html"
def dispatch(self, *args, **kwargs):
return super(GeneralUserUpdateView, self).dispatch(*args, **kwargs)
def post(self, request, pk, username):
self.pk = pk
self.username = username
self.gnu = GeneralUser.objects.get(pk=self.pk)
#form = self.form_class(request.POST, request.FILES)
return super(GeneralUserUpdateView, self).post(request, pk)
def form_valid(self, form, *args, **kwargs):
self.gnu.username = form.cleaned_data['username']
self.gnu.email = form.cleaned_data['email']
self.gnu.first_name = form.cleaned_data['first_name']
self.gnu.last_name = form.cleaned_data['last_name']
self.gnu.address = form.cleaned_data['address']
self.gnu.save()
return redirect("user_profile", self.pk, self.username)
Here in this view I want to pass a context like:
context['picture'] = GeneralUser.objects.get(pk=self.pk)
I did trying get_context_data but I cant access pk in there..
Am I doing the update right?? How can I pass that context in there??
You shouldn't be overriding post at all. All of that logic should happen in get_context_data.
In fact, none of your overrides are needed. Everything that you do in form_valid will be done already by the standard form save. And overriding dispatch just to call the superclass is pointless.
Your view should look like this only, with no overridden methods at all:
class GeneralUserUpdateView(UpdateView):
model = GeneralUser
form_class = GeneralUserChangeForm
template_name = "general_user_change.html"
context_object_name = 'picture'
(although it seems a little odd that you want to refer to an instance of GeneralUser as "picture").
Edit to redirect to a specific URL, you can define get_success_url:
def get_success_url(self):
return reverse("user_profile", self.kwargs['pk'], self.kwargs['username'])
I have this url is http://127.0.0.1:8000/upload/picturelist/1, which makes user_id = 1,
In my urls.py
url(r'^picturelist/(?P<user_id>\d+)$', views.pictureList),
In my view.py
def pictureList(request, user_id):
if int(user_id) != request.user.id:
raise PermissionDenied
How can I make this function based view to use createview?
class pictureList(CreateView):
You could do something like this:
In urls.py: url(r'^picturelist/(?P<user_id>\d+)$', views.MakeItView.as_view()),
In views.py:
class MakeItView(CreateView):
model = myModel
template_name = 'whatever.html'
def get_context_data(self, **kwargs):
context = super(MakeItView, self).get_context_data(**kwargs)
if int(self.kwargs['user_id']) != self.request.user.id:
raise PermissionDenied
return context
I've never used CreateView, but here's what I gather from reading the docs:
You could do it by defining form_valid:
view:
class pictureList(CreateView):
model = YourModelHere
fields = ['whatever','fields','you','want','edited']
def form_valid(self, form):
record = form.save(commit = False)
# assuming the user id is associated
# to the model with fieldname user_id
if (self.request.user == record.user_id):
record.save()
return HttpResponseRedirect(self.get_success_url())
# not sure if this works:
return self.form_invalid()
Then the template would be at 'yourappname/yourmodelhere_form.html'.
See CreateView for an example.