I have built a Django app and it worked well.
When I had run an another django app in a port(localhost:8000) and tried the app I built on the port, it says error like this.
AttributeError: 'AnonymousUser' object has no attribute 'profile'
Here is my code:
class DashboardView(auth_views.LoginView):
template_name = "dashboard/home.html"
verify_email_required = 'registration/verify_email_required.html'
form_class = ProfiledAuthenticationForm
def get(self, request, *args, **kwargs):
# context = {'form': self.form_class()}
context = self.get_context_data()
context['form'] = self.form_class()
if request.user.profile.is_verified:
return render(request, self.template_name, context)
else:
return render(request, self.verify_email_required, context)
Note: Initial when I built the app, it worked well, but for now it takes error. when user does not log in, the homepage was redirected to login page.
When I fixed like this, it runs well.
class DashboardView(auth_views.LoginView):
template_name = "dashboard/home.html"
verify_email_required = 'registration/verify_email_required.html'
form_class = ProfiledAuthenticationForm
def get(self, request, *args, **kwargs):
# context = {'form': self.form_class()}
context = self.get_context_data()
context['form'] = self.form_class()
if self.request.user.is_authenticated:
if request.user.profile.is_verified:
return render(request, self.template_name, context)
return render(request, self.verify_email_required, context)
return render(request, self.template_name, context)
Related
I am trying to convert my Form which is laid out in a function to be in a class based view:
Here is what I have reach out.
Function:
def add_business_plan(request):
info = Info.objects.all()
if request.method == 'POST':
form = infoForm(request.POST)
if form.is_valid():
form.save()
business_name = form.cleaned_data.get('businessName')
info_id = form.instance.id
messages.success(request, f'PDF created for {business_name}!, No.({info_id})')
return render(request, 'businessplan/businessplan.html', {'form': form, 'successful_submit': True})
else:
form = infoForm()
print(form.errors)
return render(request, 'businessplan/businessplan.html',
{
'form': form,
'successful_submit': False,
"Info": info
}
)
here is form
class infoForm(forms.ModelForm):
class Meta:
model = Info
fields = [
'businessName',
]
widgets = {
'problem_summary': RichTextFormField(),
}
You may try the following:
class AddBusinessPlan(View):
template_name = 'businessplan/businessplan.html'
form_class = infoForm
def get(self, request, *args, **kwargs):
form = self.form_class
print(form.errors)
return render(request, template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
form.save()
business_name = form.cleaned_data.get('businessName')
info_id = form.instance.id
messages.success(request, f'PDF created for {business_name}!, No.({info_id})')
return render(request, self.template_name, {'form': form, 'successful_submit': True})
else:
return render(request, self.template_name, {'form': form})
I am trying to change all my Function Based View to Class based view, i’ve been fairly successful except for this view, it’s a detail view that contains paystack payment gateway. Any help will be hugely appreciated.
def car_rent_detail_view(request, pk):
object = get_object_or_404(CarRent, id=pk)
paystack = PaystackAccount(
settings.PAYSTACK_EMAIL,
settings.PAYSTACK_PUBLIC_KEY,
object.total_cost
)
context = {'object': object, 'pk_public': settings.PAYSTACK_PUBLIC_KEY, 'currency': 'NGN', 'paystack': paystack,
}
if request.method == 'POST':
if paystack.verify_transaction(request.POST['reference']):
messages.success(request, "payment successfull")
…
car_rented.save()
…
rent_activation.save()
messages.success(request, "Rent successfully updated")
return render(request, 'app/CarRent_detail.html', context=context)
I will like to convert the CBV below to FBV so i can add payment functionality to it.
class ContestantDetail(DetailView, FormMixin):
model = Contestant
context_object_name = 'contestants'
template_name = 'contest/contestant_detail.html'
form_class = VoteForm
def get_success_url(self):
return reverse('contest:contestant-detail', kwargs={'pk': self.object.pk})
def get_context_data(self, *args, **kwargs):
context = super(ContestantDetail, self).get_context_data(*args, **kwargs)
context['vote_contestant'] = Contestant.objects.get(pk=self.kwargs.get('pk'))
return context
def post(self, request, *args, **kwargs):
form = self.get_form()
self.object = self.get_object()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form, *args, **kwargs):
contestant = Contestant.objects.get(pk=self.kwargs['pk'])
...
contestant.save()
messages.success(self.request, f'You have successfully casted {vote_count} vote.')
return super().form_valid(form)
The Class based View above can be converted to a Function based view as demonstrated below.
def contestant_detail_view(request, pk):
get_object_or_404(Contestant, pk=pk)
form = VoteForm()
context = {'contestants': get_object_or_404(Contestant, pk=pk),
'vote_contestant': Contestant.objects.get(pk=pk),
'form': form}
if request.method == 'POST':
form = VoteForm(request.POST)
if form.is_valid():
con = Contestant.objects.get(pk=pk)
...
con.save()
else:
form = VoteForm()
return render(request, 'contest/contestant_detail.html', context)
I have a class that gets the data from the form, makes some changes and save it to the database.
I want to have several method inside.
Get
Post
And some other method that will make some changes to the data from the form
I want the post method to save the data from the form to the database and pass the instanse variable to the next method. The next method should make some changes, save it to the databese and return redirect.
But I have an error. 'Site' object has no attribute 'get'
Here is my code:
class AddSiteView(View):
form_class = AddSiteForm
template_name = 'home.html'
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, { 'form': form })
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# Get website url from form
site_url = request.POST.get('url')
# Check if the site is in DB or it's a new site
try:
site_id = Site.objects.get(url=site_url)
except ObjectDoesNotExist:
site_instanse = form.save()
else:
site_instanse = site_id
return site_instanse
return render(request, self.template_name, { 'form': form })
def get_robots_link(self, *args, **kwargs):
# Set veriable to the Robot Model
robots = Robot.objects.get(site=site_instanse)
# Robobts Link
robots_url = Robots(site_url).get_url()
robots.url = robots_url
robots.save()
return redirect('checks:robots', robots.id, )
I need to pass site_instanse from def post to def get_robots_link
Here is the traceback:
Internal Server Error: /add/
Traceback (most recent call last):
File "/home/atom/.local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/atom/.local/lib/python3.8/site-packages/django/utils/deprecation.py", line 96, in __call__
response = self.process_response(request, response)
File "/home/atom/.local/lib/python3.8/site-packages/django/middleware/clickjacking.py", line 26, in process_response
if response.get('X-Frame-Options') is not None:
AttributeError: 'Site' object has no attribute 'get'
[14/Jul/2020 10:36:27] "POST /add/ HTTP/1.1" 500 61371
Here is the place where the problem is:
If I use redirect inside the post method. Everything works good. Like so:
class AddSiteView(View):
form_class = AddSiteForm
template_name = 'home.html'
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, { 'form': form })
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# Get website url from form
site_url = request.POST.get('url')
# Check if the site is in DB or it's a new site
try:
site_id = Site.objects.get(url=site_url)
except ObjectDoesNotExist:
site_instanse = form.save()
else:
site_instanse = site_id
# Set veriable to the Robot Model
robots = Robot.objects.get(site=site_instanse)
# Robobts Link
robots_url = Robots(site_url).get_url()
robots.url = robots_url
robots.save()
return redirect('checks:robots', robots.id, ) ## HERE
return render(request, self.template_name, { 'form': form })
But if remove the line return redirect('checks:robots', robots.id, ) from the post method and put return self.site_instance there. and add the def get_robots_link. It give the error: 'Site' object has no attribute 'get'
class AddSiteView(View):
form_class = AddSiteForm
template_name = 'home.html'
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, { 'form': form })
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# Get website url from form
site_url = request.POST.get('url')
# Check if the site is in DB or it's a new site
try:
site_id = Site.objects.get(url=site_url)
except ObjectDoesNotExist:
site_instanse = form.save()
else:
site_instanse = site_id
self.site_instance = site_instanse #See this
return site_instanse
return render(request, self.template_name, { 'form': form })
def get_robots_link(self, *args, **kwargs):
# Set veriable to the Robot Model
robots = Robot.objects.get(site=self.site_instance)
# Robobts Link
robots_url = Robots(site_url).get_url()
robots.url = robots_url
robots.save()
return redirect('checks:robots', robots.id, )
Use self to encode the data within the object
One must return a response from the post method. This code returns a Site instance on these lines. Not sure what is the intended behavior, either a redirect or render should be used.
try:
site_id = Site.objects.get(url=site_url)
except ObjectDoesNotExist:
site_instanse = form.save()
else:
site_instanse = site_id
return site_instanse
I'd like to redirect to a detail view after I successfully submitted a form and created the object.
My view.py
class ObjectCreateView(CreateView):
model = Object
form_class = ObjectCreateForm
template_name = 'frontend/base/object_create.html'
def get(self, request, *args, **kwargs):
form = ForecastConfigurationCreateForm()
form.fields['status'] = ModelChoiceField(queryset=ObjectStatus.get_object_status_list(self))
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
self.fcc_form = form.save(commit=True)
messages.add_message(self.request, messages.INFO, 'Good job!')
return render_to_response(reverse(viewname='object_detail', kwargs={'uuid': self.fcc_form.uuid}))
else:
messages.add_message(self.request, messages.ERROR, 'Error!')
return render(request, self.template_name, {'form': form})
The error message is:
TemplateDoesNotExist at /object_create/
/object_detail/3a3d6279-1531-45d4-9ba9-b691886facf4/
And the URL that's calling is:
http://test.com:8000/object_create/?next=/object_detail/a5b2a693-6f90-4b98-b9a2-fc2fe6a90995/
what I want it to be is
http://test.com:8000/object_detail/a5b2a693-6f90-4b98-b9a2-fc2fe6a90995/
Thanks!
Instead of trying to render the page, use HttpResponseRedirect instead:
class ObjectCreateView(CreateView):
...
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
self.fcc_form = form.save(commit=True)
messages.add_message(self.request, messages.INFO, 'Good job!')
return HttpResponseRedirect(reverse('object_detail', kwargs={'uuid': self.fcc_form.uuid}))
else:
messages.add_message(self.request, messages.ERROR, 'Error!')
return render(request, self.template_name, {'form': form})
just stumbled across the answer. The return should be:
return redirect(reverse('object_detail', kwargs={'uuid': self.fcc_form.uuid}))
I have this URL
path('private/productores/<pk>', views.Productor_Private.as_view()),
Views.py
class Productor_Private(generic.DetailView):
model = Productor
template_name = 'firstpage/productor_private.html'
def get(self, request, pk):
form = RepartoForm()
return render(request, self.template_name, {'form': form})
def post(self, request, pk):
form = RepartoForm(request.POST)
if form.is_valid():
return render(request, self.template_name, args)
I want to retrieve the pk from the URL to use it as a filter inside the forms.py, to do something like this:
class RepartoForm(forms.Form):
productos = forms.ModelMultipleChoiceField(queryset=Producto.objects.filter(productor=pk))
So in other words, I need to check what the current user's "productor" id is in order to only retrieve the "productos" that belong to this "productor"
You will need to "patch" the form constructor, and manually set the queryset in the __init__ function:
class RepartoForm(forms.Form):
productos = forms.ModelMultipleChoiceField(queryset=Producto.objects.all())
def __init__(self, *args, productor_pk=None, **kwargs):
super(forms.Form, self).__init__(*args, **kwargs)
if productor_pk is not None:
self.fields['productos'].queryset = Producto.objects.filter(
productor=productor_pk
)
Or for older versions of Python that does not implement more advanced parameter unpacking, one can implement it like:
class RepartoForm(forms.Form):
productos = forms.ModelMultipleChoiceField(queryset=Producto.objects.all())
def __init__(self, *args, **kwargs):
productor_pk = kwargs.pop('productor_pk', None)
super(forms.Form, self).__init__(*args, **kwargs)
if productor_pk is not None:
self.fields['productos'].queryset = Producto.objects.filter(
productor=productor_pk
)
In case no product_pk is given, the queryset are all the Productos (in case you do not want that, you can alter the form, and for example by default use an empty QuerySet like Producto.objects.none()).
Then in the view, you can construct the form with a named productor_pk parameter:
class Productor_Private(generic.DetailView):
model = Productor
template_name = 'firstpage/productor_private.html'
def get(self, request, pk):
form = RepartoForm(productor_pk=pk)
return render(request, self.template_name, {'form': form})
def post(self, request, pk):
form = RepartoForm(request.POST, productor_pk=pk)
if form.is_valid():
return render(request, self.template_name, args)
Note: you also need to cover the case where the form is invalid: right now post will return None for that, but you should return a HTTP response for all codepaths.