Get Kwargs through an intermediate page - django

I have a model (grade) inside another model (homework) which is inside another model (activity) and when I submit the grade of a homework and try to get back to activty I loose the id of the activity. How do I get the right kwargs to get back to activity after submiting a grade? Or any other solution you may think about. Thanks in advance.
Views.py
def grade_homework(request, id):
if not request.user.is_authenticated:
return render(request, "auctions/login.html")
try:
activity = Activity.objects.get(id=id)
except Activity.DoesNotExist:
activity = None
try:
hw_upload = Hw_upload.objects.get(id=id)
except Hw_upload.DoesNotExist:
hw_upload = None
if request.method == 'POST':
form = Hw_gradeForm(request.POST, request.FILES or None)
if form.is_valid():
hw_grade = form.save(commit=False)
hw_grade.grader = request.user
hw_grade.hw_upload = Hw_upload.objects.get(id=id)
hw_grade.save()
url = reverse('activity', kwargs={'id': id})
return HttpResponseRedirect(url)
Urls.py
path("auction/course/module/activity/<str:id>", views.activity, name="activity"),
path("grade_hw/<int:id>", views.grade_homework, name="grade_hw"),

Related

Django returning None instead of a HTTP response

OK im probably doing this all wrong!
I am trying to run a function in a view which calls another view.
This seems to pass my request into the next function as a POST method before loading the form from the second function.
my views.py
''' This section of hte code seems to function correctly '''
#login_required()
def joinLeague(request):
if request.method == 'POST':
league = JoinLeagueQueue(user=request.user)
form = JoinLeagueForm(instance=league, data=request.POST)
if form.is_valid():
form.save()
context = int(league.id) # displays id of model, JoinLeagueQueue
return HttpResponseRedirect(confirmLeague(request, context))
else:
form = JoinLeagueForm()
context = {'form':form}
return render(request, 'userteams/joinleagueform.html', context)
This section of the views file is not working correctly.
it seems to run the POST request without displaying the GET request with the form first.
#login_required()
def confirmLeague(request, league):
# gets ID of application to join league
joinleagueid=JoinLeagueQueue.objects.get(id=league)
pin = joinleagueid.pin # gets pin from application
user = joinleagueid.user # get user from application
leagueinquestion=League.objects.get(leaguePin=pin) # gets the league record for applied league
manager=leagueinquestion.leagueManager # Gets the league manager for league applied for
leaguename=leagueinquestion.leagueName # Gets the league name for league applied for
if request.method == 'POST':
if 'accept' in request.POST:
LeaguesJoinedTo.objects.create(
leaguePin = pin,
playerjoined = user,
)
return redirect('punterDashboard')# user homepage
else:
print("Error in POST request")
else:
context = {'leaguename':leaguename, 'pin':pin, 'manager':manager}
return render(request, 'userteams/confirmleague.html', context)
I now get an error saying Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/userteams/None
Using the URLconf defined in fanfoo_proj.urls, Django tried these URL patterns, in this order:
... im skipping a list of the patterns.
10. userteams/ confirmLeague [name='confirmLeague']
Ok i think the better way would be a HttpRedirect to the second view:
return confirmLeague(request, context)
should change to something like:
return redirect(confirmLeague,args=league)
django doc to urlresolvers: https://docs.djangoproject.com/en/3.0/topics/http/shortcuts/#redirect
def joinLeague(request):
if request.method == 'POST':
league = JoinLeagueQueue(user=request.user)
form = JoinLeagueForm(instance=league, data=request.POST)
if form.is_valid():
form.save()
context = league.id
return HttpResponseRedirect( reverse("your_confirmLeague_url",kwargs={'league':context}) )
else:
form = JoinLeagueForm()
context = {'form':form}
return render(request, 'userteams/joinleagueform.html', context)
def confirmLeague(request, league):
league = get_object_or_404(JoinLeagueQueue, pk=league)
pin = league.pin
if request.method == 'POST':
if 'accept' in request.POST: # This refers to the action from my form which is waiting for a button press in a html form.
LeaguesJoinedTo.objects.create(
leaguePin = pin,
playerjoined = request.user.id,
)
return redirect('punterDashboard')
else:
context = {'league':league}
return render(request, 'userteams/confirmleague.html', context)

Django: window.onpopstate unexpected behavior with Chrome 79

EDIT
finally I use window.onpopstate event to prevent user go back
it works with Firefox but not with Chrome 79 (and other browsers?)
I have read many posts and official documentation that seems to say that this 'bug' was fixed after Chrome 34... but doesn't seems to be
to be honest, event reading the documentation, I do not really understand this event and the behavior so far...
How can I resolve this?
I know this topic has been already discuss but none of solutions resolve my problem.
I have 3 forms that update the same models.
I would like to manage/prevent user going back using back arrow.
I tried using window.location, window.onhashchange = function () {}, flag session variable but nothing works and I am lost
When user click on back arrow from 2nd form to go back to 1st form, I would like either the event is blocked (best), either user is redirected to home page
I notice that click on back arrow on the 2nd form do not call index view, reason why 'flag strategy' do not work
#login_required
#permission_required('unblind.can_unblind')
def index(request):
if request.method == "POST":
form = AveugleProcedureForm(request, data=request.POST or None)
if form.is_valid():
unblind = form.save()
# database treatment
return redirect('unblind:edit', pk = unblind.pk)
else:
form = AveugleProcedureForm(request)
return render(request, 'unblind/index.html', {'form': form})
#login_required
#permission_required('unblind.can_unblind')
def edit(request, pk):
if request.method == "POST":
form = AveugleForm(request, data=request.POST or None)
if form.is_valid():
# unblind = form.save()
# database treatment
unblind = Aveugle.objects.get(unb_ide = pk)
unblind.unb_pro = form.cleaned_data['unb_pro']
unblind.unb_nom_dem = form.cleaned_data['unb_nom_dem']
unblind.unb_nom_rea = form.cleaned_data['unb_nom_rea']
unblind.unb_dat = form.cleaned_data['unb_dat']
unblind.pat = form.cleaned_data['pat']
unblind.unb_num = form.cleaned_data['unb_num']
unblind.unb_mot = form.cleaned_data['unb_mot']
unblind.save()
# contrôler le couple numéro patient/boite de médicament
# récupération du traitement
treatment = Medicament.objects.get(med_num = unblind.unb_num).med_dru
# envoie d'un email de confirmation
if treatment == 1:
unblind_treatment = _('ASPIRIN')
else:
unblind_treatment = _('PLACEBO')
email(unblind.pat,unblind.unb_num,unblind_treatment,unblind.unb_mot)
return redirect('unblind:result', pk = unblind.pk)
else:
form = AveugleForm(request)
return render(request, 'unblind/edit.html', {'form': form,'pk': pk})
#login_required
#permission_required('unblind.can_unblind')
def result(request, pk):
# Récupération de l'enregistrement
unblind = Aveugle.objects.get(unb_ide = pk)
treatment = Medicament.objects.get(med_num = unblind.unb_num).med_dru
if request.method == "POST":
form = AveugleResultForm(request, data=request.POST or None)
if form.is_valid():
# database treatment
unblind.unb_rec = form.cleaned_data['unb_rec']
# unblind.unb_com = form.cleaned_data['unb_com']
unblind.unb_log_dat = datetime.now()
unblind.unb_log = request.user.username
unblind.unb_log_sit = request.session['selected_site']
unblind.save()
return redirect('home')
else:
form = AveugleResultForm(request)
return render(request, 'unblind/result.html', {'form': form,'unblind':unblind,'treatment':treatment})

Save and Continue in Django Forms

I have created a django form which at the moment I can only save the POST. Would like to add Save and Add another button in my templates and views function. Has anyone found a solutions.
if request.method == "POST":
form = StktxnsForm(request.POST )
if form.is_valid():
new_txns = form.save(commit=False)
new_txns.created_by = request.user
new_txns.save()
return redirect('pending_transactions')
else:
form = StktxnsForm()
return render(request,'new_transaction.html', {'form': form})
You may think use AJAX function to save and continue without reload. Send 'POST' request to save data in Ajax. It will help you.
I used like this in class-based view (vanilla method)
class PackageCreateView(View):
def get(self,request,*args,**kwargs):
return render(request,'package/create_package.html')
def post(self,request,*args,**kwargs):
if request.user.is_authenticated:
if request.method == 'POST':
data = request.POST
name = data.get('name')
detail = data.get('des')
price = data.get('price')
fname = Package.objects.all().filter(name=name)
if fname:
messages.info (request,'sorry name already exits')
return redirect ('create_package')
elif request.POST.get ('continue') :
pac = Package(name=name, detail=detail, price=price)
pac.save()
return redirect('create_package')
else:
pac = Package(name=name, detail=detail, price=price)
pac.save()
return redirect('packagelist')
else:
return redirect ('create_package')
else:
return redirect('login')
Here's one way to do it.
On your template:
<button type="submit" name="save_add" value="True">Save & Add another</button>
In your view:
if form.is_valid():
new_txns = form.save(commit=False)
new_txns.created_by = request.user
new_txns.save()
if request.POST.get('save_add'):
return redirect('create_transaction')
return redirect('pending_transactions')

Dynamic initialisation of form in Django

I am trying to initialise a form dynamically. This is my forms.py:
class MapLocalityForm(forms.Form):
def search_locs(self, location):
print("inside form")
print(location)
return Locality.objects.filter(name=location)
def __init__(self,*args, **kwargs):
self.loc = kwargs.pop('loc', None)
super(MapLocalityForm, self).__init__(*args, **kwargs)
self.fields['locality'] = forms.ModelChoiceField(queryset='',widget=forms.RadioSelect(),required=True,
initial=1)
if self.loc:
loc_term = self.loc
# print(loc_term)
loc_list = self.search_locs(loc_term)
# print(loc_list)
self.fields['locality'].queryset = loc_list
else:
self.fields['locality'].queryset = Locality.objects.none()
So I perform a check in views.py:
def map_locality(request,freq_term):
if request.method =='POST':
form = MapLocalityForm(request.POST, loc=freq_term)
if form.is_valid():
"do something"
else:
form = MapLocalityForm()
return render(request, 'maplocalities.html', {'form': form,'loc':freq_term,'alias_created':alias_created})
I am directed to this view using a redirect option, so the request is GET. Whenever I jump to this maplocalities.html, I get an empty form because the code goes to the else part and there are no arguments. Usually when we create a form which is static, a form is displayed when it goes to the else part. Any idea ow can I rectify my view to perform just like static forms.

django - how to check if model is empty

I have settings form page. If user filled the form once; it must display those values. But if there is no data [first time] I get query error. I need that query, because the form data must be written as related with current user [logged in].
here is my view part :
#login_required(login_url='/login/')
def profile_page(request,username):
query = Profile.objects.get(owner__username = username) ##error!
if request.method == 'POST':
form = profile_form(request.POST,instance=query)
form.save()
return HttpResponseRedirect('/admin/')
else:
form = profile_form(instance=query)
return render_to_response('profile_save.html',{'form':form},context_instance = RequestContext(request))
I think I need to check the model and if it is empty I should do something different.
I am stuck.
Thank you
You want to make use of the .exists() queryset option
#login_required(login_url='/login/')
def profile_page(request,username):
form = profile_form()
if Profile.objects.get(owner__username = username).exists():
query = Profile.objects.get(owner__username = username)
if request.method == 'POST':
form = profile_form(request.POST,instance=query)
form.save()
return HttpResponseRedirect('/admin/')
else:
form = profile_form(instance=query)
return render_to_response('profile_save.html',{'form':form},context_instance = RequestContext(request))
see QuerytSet API reference for more information
You just need to wrap that get query in try ... except and set instance to none, like this.
from django.core.exceptions import ObjectDoesNotExist
#login_required(login_url='/login/')
def profile_page(request,username):
try:
query = Profile.objects.get(owner__username = username)
#to be more specific you can except ProfileObjectDoesNotExist
except ObjectDoesNotExist:
query = None #Doesn't exist, set to None
if request.method == 'POST':
form = profile_form(request.POST,instance=query)
form.save()
return HttpResponseRedirect('/admin/')
else:
form = profile_form(instance=query)
return render_to_response('profile_save.html',{'form':form},
context_instance = RequestContext(request))
I think i may have use get_or_create for this purpose.
Profile.objects.get_or_create(owner__username = username)