Display a confirmation message on template from backend(python/Django) - python

Hi I have JSONResponseMixin View, the main function of this view is to change the status to confirmed once the user click confirms in the GUI. I want to display a pop-up stating that it's confirmed. How can I do that from the django views.py?
The following is my view
class ConfirmView(JSONResponseMixin, View):
def post(self, request, *args, **kwargs):
status = 'error'
msg = "this is from me"
post_body = json.loads(self.request.body)
fab_value = post_body['fab']
mast_value = post_body['mast']
comment = post_body.get('comment')
try:
object = Forecast.objects.get(fab=fab_value, mast=mast_value, type='XC')
except ObjectDoesNotExist:
object = []
else:
if object.status == 'notified(created)' or 'notified(updated)':
object.status = 'confirmed'
object.comment = second_po_comment
object.confirm = self.request.user
object.modified_by =User.objects.get(username=self.request.user.username)
object.save()
return self.render_json_response(dict(status=status, msg=msg))

Related

test return redirect("account_login") in django use pytest

i using pytest and coverage for testing django project But I don't know how to test the else block that has return redirect("account_login") and fix the red part that says coverage.
In your opinion, how can I write a test for that else piece and fix the red part that says coverage?
views.py
#verified_email_required
def profile_view(request, username):
# We check if the user is logged in?
if request.user.is_authenticated:
try:
profiles = Profile.objects.all()[:4]
# get user profile by username
profile = Profile.objects.get(user__username__iexact=username)
user = User.objects.get(username=username)
user_following = following(user)
user_followers = followers(user)
logged_in_user_following = following(request.user)
logged_in_user_followers = followers(request.user)
# if user not found raise 404 error
except ObjectDoesNotExist:
raise Http404
# context data
context = {
"user": user,
"profile": profile,
"profiles": profiles,
"following": user_following,
"followers": user_followers,
}
return render(request, "user_profile/profile.html", context)
# if a user is not login in redirecting to login page
else:
return redirect("account_login")
test_view.py
#pytest.mark.django_db
class TestProfileView:
#pytest.fixture
def user(self):
user, created = User.objects.get_or_create( # created user
username="test_username",
first_name="test_first_name",
last_name="test_last_name",
email="test#test.com",
is_active=True,
is_superuser=False,
)
(
user_email_address,
created,
) = EmailAddress.objects.get_or_create( # user email confirmation
email=user.email, user=user
)
user_email_address.verified = True
user_email_address.primary = True
user_email_address.save()
return user
def test_profile_view_when_user_is_authenticated_return_correct_profile(
self, user, client
):
client.force_login(user) # user logged in
response = client.get(user.profile.get_absolute_url())
content = response.content.decode(response.charset)
assert response.status_code == 200
assert (
'<h1 class="text-3xl md:text-4xl font-semibold">Test_first_name test_last_name</h1>'
in str(content)
)
response = client.get("/user_not_exist", follow=True)
assert response.status_code == 404
response = client.post("/accounts/logout/")
assert response.status_code == 302
def test_profile_view_when_user_is_anonymous_return_login_page(self, user, client):
response = client.get("/test_username/", follow=True)
content = response.content.decode(response.charset)
assertRedirects(response, "/accounts/login/?next=/test_username/")
assert response.status_code == 200
assert response.template_name[0] == "account/login.html"
assert '<h1 class="text-3xl font-semibold text-center">Login</h1>' in str(
content
)
assert response.resolver_match.url_name == "account_login"
assert response.resolver_match.view_name == "account_login"
I suspect you won't be able to as your decorator #verified_email_required will prevent any unlogged in people from reaching that line of code.
My assumption here is that you are using allauth as it provides a decorator of that precise name. See https://django-allauth.readthedocs.io/en/stable/decorators.html which states: If the user isn’t logged in, it acts identically to the login_required decorator.

How can I pass a model id from the url to a class based view?

I have a class-based view:
class Create(View):
note_id = None
http_method_names = ['post', 'patch']
default_title = "You fool! This was left empty"
default_body = "Why did you leave this blank :("
def dispatch(self, *args, **kwargs):
method = self.request.POST.get('_method', '').lower()
print('method = ', method)
if method == 'patch':
return self.patch(*args, **kwargs)
elif method == 'post':
self.post(*args, **kwargs)
return super(Create, self).dispatch(*args, **kwargs)
def post(self, note_id):
date = datetime.date.today()
title = self.request.POST.get('title', '')
body = self.request.POST.get('note', '')
# check for blank attributes
if title == "":
title = Create.default_title
if body == "":
body = Create.default_body
note = Note(note_title=title, note_body=body, publish_date=date, edit_date=None)
note.save()
return HttpResponseRedirect(reverse('notes:note'))
def patch(self, note_id):
note = Note.objects.get(id=note_id)
title = self.request.POST.get('title', '')
body = self.request.POST.get('note', '')
# if something changed
if title != note.note_title or body != note.note_body:
# check for blank attributes
if title == "":
title = Create.default_title
if body == "":
body = Create.default_body
note.note_title = title
note.note_body = body
note.edit_date = datetime.date.today()
note.save()
return HttpResponseRedirect(reverse('notes:note'))
and in url.py I have
urlpatterns = [
path('<int:note_id>/create/', views.Create.as_view(), name='create'),
path('<int:note_id>/edit/', views.Create.as_view(), name='edit')
]
Previously, with function-based views the note_id would just be passed to the function automatically. I can not figure out the equivalent of this in class based views. I've tried explictiely passing note_id to each function, but that did not work. I tried included Create.as_view(note_id=note_id) in my url.py, but to no avail.
Currently, running this code I get:
post() got multiple values for argument 'note_id'
As mentioned in the comment above, you need to access these values through self.kwargs. e.g:
class Create(View):
note_id = None # Delete this line
...
# delete the dispatch method - no need to overwrite this.
# Don't include note_id as an argument, but request should be an argument
def post(self, request):
note_id = self.kwargs['note_id']
....
def put(self, request): # Likewise here
note_id = self.kwargs['note_id']
....
It doesn't look like you need to write a custom dispatch method. If all you are doing is calling the appropriate method, then the dispatch method that comes for free with View is just fine :)

EncodeError at (POST Method ) in django python. Post respose 500

I have my python class below. My question is what this error actually means EncodeError at /api/v1/jobs/apply/
> is not JSON serializable. What is it trying to point based on my code below ? can anyone give an idea? . The new_email is at below also.
def new_application(self, data):
try:
def new_application(self, data):
try:
html = render_to_string("email_templates/new_application.tpl",data)
name = "testt"
data["subject"] = "test"
if env == "localhost":
msg = EmailMessage(data["subject"], html, name, dev_emails)
msg.content_subtype = "html" # Main content is now text/html
msg.attach_file(data["resume"])
msg.send()
else:
msg = EmailMessage(data["subject"], html, name, [data["company_email"]])
msg.content_subtype = "html" # Main content is now text/html
msg.attach_file(data["resume"])
msg.send()
except Exception as e:
print(str(e))
error
EncodeError at /api/v1/jobs/apply/
<bound method Email.new_application of <v1.lib.emails.Email object at 0x7f6cbe44e908>> is not JSON serializable
Code
class ApplyJob(APIView):
def email(self, data):
email_ins = Email()
c_task.delay(email_ins.new_application, data)
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,IsApplicant)
def post(self, request, format=None):
data = request.data
job_applicant_ser = JobApplicantSerializer(data=data)
applicant = get_applicant_ins(request)
if applicant.profile_completeness <= 60:
return Response("You have not complete filling up your profile yet. Please complete it atleast 80% and above percentage..", status=status.HTTP_400_BAD_REQUEST)
if not applicant.resume:
return Response("Sorry, Please upload your resume.", status=status.HTTP_400_BAD_REQUEST)
job = data.get("job" , None)
cover_letter = data.get("cover_letter", None)
if not cover_letter or cover_letter == "":
return Response("Sorry, please fill your cover letter.", status=status.HTTP_400_BAD_REQUEST)
apply_job_checker_ins = JobApplicant.objects.filter(job=job,applicant=applicant).count()
if apply_job_checker_ins > 0:
return Response("Sorry but you cant apply to this company, it appears that you have already applied.", status=status.HTTP_400_BAD_REQUEST)
if job:
job = JobModel.objects.get(pk=job)
else:
return Response("Sorry but there is a problem with the application, please refresh page.", status=status.HTTP_400_BAD_REQUEST)
if job_applicant_ser.is_valid(raise_exception=True):
job_applicants = job_applicant_ser.save(applicant=applicant,job=job)
data = {}
data["job"] = job_applicants.job.title
data["account_url"] = APP_URL+"/account/job_applicants"
data["email"] = job_applicants.job.company.user.email
data["resume"] = STATIC_ROOT+"/uploads/resume/"+str(job_applicants.applicant.resume)
data["company_email"] = job_applicants.job.company.user.email
self.email(data)
return Response("You have applied to the jo
b. Please make sure your line is always open.", status=status.HTTP_200_OK)

some troubles with CreateView in the Django

class Biochemical_analysis_of_blood(CreateView):
model = BiochemicalAnalysisOfBlood
form_class = BiochemicalAnalysisOfBloodForm
template_name = "biochemical_analysis_of_blood.html"
success_url = reverse_lazy("patients")
def get_context_data(self, **kwargs):
context = super(Biochemical_analysis_of_blood, self).get_context_data(**kwargs)
patient = Patient.objects.get(id=1)
context["patient"] = patient
return context
def post(self, request, *args, **kwargs):
analysis = Analyzes()
sid = transaction.savepoint()
analysis.name = request.POST["name"]
analysis.patient_id = Patient.objects.get(id=1)
analysis.who_send = request.POST["who_send"]
analysis.who_is_doctor = request.POST["who_is_doctor"]
analysis.lab_user_id = Doctor.objects.get(id=request.POST["lab_user_id"])
analysis.additional_lab_user = request.POST["lab_user_add"]
analysis.date = '2017-06-18'
analysis.type = 3
analysis.date_analysis = '2017-06-18'
analysis.save()
return super(Biochemical_analysis_of_blood, self).post(request, *args, **kwargs)
I have next algorithm:
Render BiochemicalAnalysisOfBloodForm to the user
When he fills fields and presses button "save" I create a new instance of Analyzes() and fill it programmatically and when in the post method I call super().post() then users data will be written to the model BiochemicalAnalysisOfBlood automatically? But I have next error:
NOT NULL constraint failed:
laboratory_biochemicalanalysisofblood.analysis_id
How can I in hand mode add to the model to the field "analysis" the early created instance of Analyzes()? I don't understand this class to the end where I can find information about all it's opportunities
The main part of your algorithm should reside in your form, because you want to pass the analysis_id to the instance being saved
class BiochemicalAnalysisOfBloodForm(ModelForm):
def save(self, commit=True):
analysis = Analyzes()
sid = transaction.savepoint()
analysis.name = self.data["name"]
analysis.patient_id = Patient.objects.get(id=1)
analysis.who_send = self.data["who_send"]
analysis.who_is_doctor = self.data["who_is_doctor"]
analysis.lab_user_id = Doctor.objects.get(id=self.data["lab_user_id"])
analysis.additional_lab_user = self.data["lab_user_add"]
analysis.date = '2017-06-18'
analysis.type = 3
analysis.date_analysis = '2017-06-18'
analysis.save()
# Your analysis is created, attach it to the form instance object
self.instance.analysis_id = analysis.id
return super().save(commit)
Before doing the super().post you can modify the request.POST data to include your analysis id:
request.POST['analysis_id'] = analysis.id
that might help.
Also note that if the form validation fails in super().post, you will still have created an Analysis object which might not be useful. You could use override the form_invalid method of the CreateView to handle this.

Django multiple forms on one view

I have a Django template that has data from a few different model types combining to make it. A dashboard if you will. And each of those has an edit form.
Is it best to process all those forms in one view as they are posted back to the same place and differentiating between them by a unique field like below?
Or if having lots of different dedicated avenues is the way forward? Thanks for any guidance
class ProjectDetail(DetailView):
template_name = 'project/view.html'
def get_object(self):
try:
return Project.objects.filter(brief__slug=self.kwargs['slug']).filter(team=get_user_team(self.request)).first()
# add loop to allow multiple teams to work on the same brief (project)
except Exception as e:
project_error = '%s (%s)' % (e.message, type(e))
messages.error(self.request, 'OH NO! %s' % project_error)
return redirect('home')
def get_context_data(self, **kwargs):
project = self.get_object()
context = dict()
context['project'] = project
context['milestone_form'] = MilestoneForm(initial={'project': project})
context['view'] = self
return context
def post(self, request, *args, **kwargs):
# get the context for the page
context = self.get_context_data()
try:
# switch for each of the form types on the team profile page (shown if member)
if 'milestone_form_submit' in request.POST:
project=self.get_object()
# set date arbitrarily to half way to brief deadline
brief = Brief.objects.get(project=project)
last_milestone = self.milestones().last()
milestone_del_date = last_milestone.del_date + timedelta(days=7)
new_milestone = Milestone(
project=project,
title_text=request.POST.get('title_text'),
del_date=milestone_del_date,
)
try:
new_milestone.save()
messages.success(self.request, "Excellent! New delivery popped on the bottom of the list")
except Exception as e:
# pass the erroring form back in the context if not
form = MilestoneForm(request.POST)
context['milestone_form'] = form
messages.error(self.request, "OH NO! Deadline didn't save. Be a sport and check what you entered")
elif 'milestone-edit-date-form-submit' in request.POST:
# get object from db
milestone = Milestone.objects.get(pk=request.POST['id'])
# update del_date field sent
milestone.del_date = request.POST['del_date']
# save back to db
milestone.save()
messages.success(self.request, "Updated that delivery right there!")
elif ...
except Exception as e:
messages.error(self.request, "OH NO! Deadline didn't save. Be a sport and check what you entered")
return render(request, self.template_name, context)
You can use mixins in order to solve your problem.
Example from the gist https://gist.github.com/michelts/1029336
class MultipleFormsMixin(FormMixin):
"""
A mixin that provides a way to show and handle several forms in a
request.
"""
form_classes = {} # set the form classes as a mapping
def get_form_classes(self):
return self.form_classes
def get_forms(self, form_classes):
return dict([(key, klass(**self.get_form_kwargs())) \
for key, klass in form_classes.items()])
def forms_valid(self, forms):
return super(MultipleFormsMixin, self).form_valid(forms)
def forms_invalid(self, forms):
return self.render_to_response(self.get_context_data(forms=forms))
As you can see, when you inherit from this class, you can handle multiple forms simultaneously. Look at the gist's code and adapt it to your problem.
Look at this answer

Categories

Resources