HttpResponseRedirect not working in django - python

HttpResponseRedirect not working it shows error as 'context must be dict rather than response'
class FooterLinksView(TemplateView):
template_name = 'pages/footerlinks.html'
model = FooterLink
def get_context_data(self, **kwargs):
context = super(FooterLinksView,self).get_context_data(**kwargs)
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type == 'page':
try:
context['page_obj'] = obj
return context
except:
pass
else:
pass
print(obj.url_name)
return HttpResponseRedirect(str(obj.url_name))

get_context_data() is the method for return context, so it must return context object. If you want to redirect, do it in get().
like below
class FooterLinksView(TemplateView):
template_name = 'pages/footerlinks.html'
model = FooterLink
def get(self, request, *args, **kwargs):
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type != 'page':
return HttpResponseRedirect(str(obj.url_name))
else:
return super().get(*args, **kwargs)
# if python2
# return super(FooterLinksView, self).get(*args, **kwargs)
def get_context_data(self, **kwargs):
context = super(FooterLinksView,self).get_context_data(**kwargs)
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type == 'page':
try:
context['page_obj'] = obj
return context
except:
pass
return context
or you can just use extra_context in TemplateView.
class FooterLinksView(TemplateView):
template_name = 'pages/footerlinks.html'
model = FooterLink
def get(self, request, *args, **kwargs):
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type != 'page':
try:
self.extra_context = {
'page_obj': obj
}
except:
pass
return HttpResponseRedirect(str(obj.url_name))
else:
return super().get(*args, **kwargs)
# if python2
# return super(FooterLinksView, self).get(*args, **kwargs)

You must always return a dict from your get_context_data function. If you want to redirect, you should override dispatch too:
class FooterLinksView(TemplateView):
...
def dispatch(self, request, *args, **kwargs):
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
if obj.link_type != 'page':
return HttpResponseRedirect(str(obj.url_name))
return super(FooterLinksView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(FooterLinksView,self).get_context_data(**kwargs)
string_name = self.kwargs['string']
obj = FooterLink.objects.get(link_url=string_name)
context['page_obj'] = obj
return context

The code in your get_context_data is trying to retrieve a single object and passing it to the context dictionary. This functionality is already built-in the DetailView and seems to be a better fit here than the TemplateView.
from django.views.generic import DetailView
class FooterLinksView(DetailView):
model = FooterLink
template_name = 'pages/footerlinks.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if self.object.link_type == 'page':
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
return HttpResponseRedirect(str(obj.url_name))
Now the only thing we need to add is how the FooterLink object is retrieved in the get_object method. If your link_url field of FooterLink is the primary key we can simply add pk_url_kwarg = 'link_url' in the top of the class. Otherwise you should use the slug_field and slug_url_kwarg.
class FooterLinksView(DetailView):
model = FooterLink
pk = 'link_url' # if link_url is the primary key
slug_field = 'link_url' # if link_url is not the primary key
slug_url_kwarg = 'string' # if link_url is not the primary key
template_name = 'pages/footerlinks.html'
...
Note: You should now use the object variable inside your template (instead of obj) or override yet another option: context_object_name.

class FooterLinksView(TemplateView):
template_name = 'pages/footerlinks.html'
model = FooterLink
def get(self, request, args, *kwargs):
context = self.get_context_data(**kwargs)
string_name = self.kwargs['string']
obj = get_object_or_404(FooterLink, link_url=string_name)
if obj.link_type == 'page':
context['page_obj'] = obj
return render(request, self.template_name, context)
else:
a = obj.url_name
return HttpResponseRedirect(a)

Related

Prevent repetition code in methods get and post in django class vase view

There are several lines of code in the get method that are also used in the post method. How can I prevent code repetition in this view?
class ProductDetail(View):
def get(self, request, *args, **kwargs):
products = Product.objects.get(id=self.kwargs['pk'])
related_products = products.tags.similar_objects()[:4]
comments = Comment.objects.filter(is_reply=False, product_id=self.kwargs['pk'])
change = Chart.objects.filter(product_id=self.kwargs['pk'])
context = (
{'products': products, 'related_products': related_products, 'comments': comments,
'change': change})
return render(request, 'home/details.html', context)
def post(self, request, *args, **kwargs):
products = Product.objects.get(id=self.kwargs['pk'])
related_products = products.tags.similar_objects()[:4]
comments = Comment.objects.filter(is_reply=False, product_id=self.kwargs['pk'])
change = Chart.objects.filter(product_id=self.kwargs['pk'])
context = ({'products': products, 'related_products': related_products, 'comments': comments,
'change': change})
return render(request, 'home/details.html', context)
Does this work ?
class ProductDetail(View):
def dostuff(id):
self.products = Product.objects.get(id)
self.related_products = self.products.tags.similar_objects()[:4]
self.comments = Comment.objects.filter(is_reply=False, product_id=id)
self.change = Chart.objects.filter(product_id=id)
def get(self, request, *args, **kwargs):
dostuff(self.kwargs['pk'])
context = (
{'products': self.products, 'related_products': self.related_products, 'comments': self.comments,
'change': self.change})
return render(request, 'home/details.html', context)
def post(self, request, *args, **kwargs):
dostuff(self.kwargs['pk'])
context = ({'products': self.products, 'related_products': self.related_products, 'comments': self.comments,
'change': self.change})
return render(request, 'home/details.html', context)
You can simply use DetailView from DGCBV.
class ProductDetail(DetailView):
model = Product
template_name = 'home/details.html'
def post(self, request, *args, **kwargs):
return self.get(request, *args, **kwargs)
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
obj = context['products'] = context['product']
context['related_products'] = obj.tags.similar_objects()[:4]
context['comments'] = Comment.objects.filter(is_reply=False, produc=obj)
context['change'] = Chart.objects.filter(product=obj)
return context
if you rename you template to product_detail.html, you can remove template name attribute.
By the way: if you have only single product, why you named it "products" ?

How to work with the formset in CBV at the Django?

I have a form ProductCreateForm. It is necessary to insert the form SpeciallyPriceForm inside it.
I have a view for ProductCreateForm. But I don’t know how to process SpeciallyPriceForm in it either.
class ProductsCreate(CreateView):
model = Product
form_class = ProductCreateForm
http_method_names = ['get', 'post']
def get_form_kwargs(self):
print('form')
kwargs = super(ProductsCreate, self).get_form_kwargs()
kwargs['request'] = self.request
return kwargs
def get(self, request, *args, **kwargs):
self.object = None
...
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
self.object = None
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
product = form.save(commit=False)
product.user = self.request.user
product.save()
if self.request.is_ajax():
return JsonResponse({'success': True, 'location': location})
else:
return redirect(location)
def form_invalid(self, form):
....
upd.
class ProductsCreate(CreateView):
model = Product
form_class = ProductCreateForm
# template_name = 'products/product_form.html'
http_method_names = ['get', 'post']
def get_form_kwargs(self):
kwargs = super(ProductsCreate, self).get_form_kwargs()
kwargs['request'] = self.request
return kwargs
def get_context_data(self, *args, **kwargs):
print('ok')
ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs)
ctx['special_form'] = SpeciallyPriceForm()
return ctx
def get(self, request, *args, **kwargs):
self.object = None
if kwargs.get('slug'):
category = Category.objects.filter(slug=kwargs.get('slug')).first()
self.initial.update({'category': category})
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
self.object = None
form = self.get_form()
special_form = SpeciallyPriceForm(self.request.POST)
if form.is_valid() and special_form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
product = form.save(commit=False)
I need the template as
<form ... >
{{ form }} /*product_form
{{ formset }} /* specially_price_form
</form>
upd2
models
class Product(models.Model):
category = models.ForeignKey(
Category, related_name='product',
verbose_name=_('category'), on_delete=models.SET_NULL, null=True,
)
forms
self.fields['category'] = ModelMultipleChoiceField(queryset=provider.category.all())
def clean(self):
cleaned_data = super(ProductCreateForm, self).clean()
cd_category = cleaned_data.get('category')
views
form = self.get_form() #Error
I believe a formset is really to show the same form several times with different instances. What you want here is 2 forms. Add get_context data
def get_context_data(self, *args, **kwargs):
ctx=super().get_context_data(*args, **kwargs)
ctx['special_form'] = SpeciallyPriceForm()
return ctx
def form_valid(self, form):
special_form = SpeciallyPriceForm(self.request.POST)
if special_form.is_valid():
...
else: error code and return to screen

Django: object has no attribute 'object'

I have to implement several forms, therefore I need the combination of SingleObjectMixin, TemplateView. I always receive 'AssignAttendee' object has no attribute 'object'. Do you see why I get that error?
class AssignAttendee(SuccessMessageMixin, SingleObjectMixin, TemplateView):
template_name = 'attendees/front/assign_attendee.html'
success_message = _("Attendee has been successfully updated.")
def get_object(self):
return get_object_or_404(
Attendee,
ticket_reference=self.kwargs['ticket_reference'],
ticket_code=self.kwargs['ticket_code'],
)
#cached_property
def attendee_form(self):
return AssignAttendeeForm(
prefix='attendee',
data=self.request.POST or None,
# instance=self.attendee_contact,
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context = {
'attendee_form': self.attendee_form,
}
The problem was that it was missing:
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super().get(request, *args, **kwargs)

including extra context value django rest framework

I am using django rest framework. I need to pass some extra context value in response but not getting extra_value in response.
class ResultRowView(generics.ListAPIView):
serializer_class = ResultRowSerializer
permission_classes = (AccountPermission, )
def get_serializer(self, *args, **kwargs):
context = {'extra_value': 5000}
return self.serializer_class(*args, context=context, **kwargs)
def get_queryset(self):
qs = ResultRow.objects.none()
pk = self.kwargs.get('pk', None)
try:
route = IncomingRoute.objects.get(account=self.request.user.account, pk=pk)
qs = route.app_module.rows.all()
except Exception, e:
print 'result_row_query: ', e
return qs
What is missing here ?
you can do this by overriding the list method like:
def list(self, request, *args, **kwargs):
response = super(ResultRowView, self).list(request, args, kwargs)
response.data[ 'extra_value' ] = 5000
return response
You will have to override the get_context_data method and then add context to it
def get_context_data(self, **kwargs):
context = super(PropertyListView, self).get_context_data(**kwargs)
context['some_key'] = some_value
return context

How to pass a variable from a get_context_data def __init__?

There are UpdateView and ModelForm, you need to pass a variable from view to form, here is view:
class EditBranchView(UpdateView):
model = Branches
template_name = 'branches/edit.html'
form_class=EditBranchForm
def get_context_data(self, *args, **kwargs):
context = super(EditBranchView, self).get_context_data(**kwargs)
if self.request.POST:
context['form'] = EditBranchForm(self.request.POST, instance=self.object, request=self.request, pk = self.kwargs['pk'])
context['phones_form'] = BranchPhonesFormSet(self.request.POST, instance=self.object)
else:
context['form'] = EditBranchForm(instance=self.object, request=self.request, pk = self.kwargs['pk'])
context['phones_form'] = BranchPhonesFormSet(instance=self.object)
return context
and my form:
class EditBranchForm(forms.ModelForm):
regions=forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple)
owner = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Profiles.objects.all())
def __init__(self, request, pk, *args, **kwargs):
super(EditBranchForm, self).__init__(*args, **kwargs)
self.pk = pk
self.request = request
self.fields['owner'].queryset = Profiles.objects.filter(pid=self.request.user.id)
self.fields['regions'].choices = self.request.user.organization.organizationtoregion_set.all().values_list('region__id', 'region__region_name')
but it give error:
init() takes at least 3 arguments (1 given)
How should I do it? Thanks
Your argument handling in EditBranchForm.__init__ is wrong. It should be something like this:
def __init__(self, *args, **kwargs):
self.pk = kwargs.pop('pk', None)
self.request = kwargs.pop('request')
super(EditBranchForm, self).__init__(*args, **kwargs)
user = request.user
self.fields['owner'].queryset = Profiles.objects.filter(pid=user.id)
self.fields['regions'].choices = user.organization \
.organizationtoregion_set.all() \
.values_list('region__id',
'region__region_name')

Categories

Resources