Django : HTML form action directing to view (or url?) with 2 arguments - html

Started learning django about a week ago and ran into a wall. Would really appreciate any enlightenment...
models.py
class data(models.Model):
course = models.CharField(max_length = 250)
def __str__(self):
return self.course
html
Converted the objects in models.course to schlist
<link rel="stylesheet" type="text/css" href="{% static '/chosen/chosen.css' %}" />
<form action={% views.process %} method="GET">
<div>
<h4 style="font-family:verdana;">First Course: </h4>
<select data-placeholder="Course" style="width:350px;" class="chosen-select" tabindex="7">
<option value=""></option>
{% for item in schlist %}
<option> {{ item }} </option>
{% endfor %}
</select>
</div>
</br>
<div>
<h4 style="font-family:verdana;">Second Course:</h4>
<select data-placeholder="Course" style="width:350px;" class="chosen-select" tabindex="7">
<option value=""></option>
{% for item in schlist %}
<option> {{ item }} </option>
{% endfor %}
</select>
</div>
</br>
<input type="submit" value="Compare!" />
</form>
urls.py (having my doubts if this works..)
urlpatterns = [
url(r'^(\d+)/(\d+)$',views.process, name = 'process'),
]
view.py
def process(request,q1 ,q2):
obj1= get_object_or_404(Schdata, course = q1)
obj2= get_object_or_404(Schdata, course = q2)
........
Was wondering if it is possible for the form action to direct the action to
(1) view.py or (2) url.py (and eventually to a view.py) with 2 arguments selected?
If so how should the form action be? {{view ?}} or {{url ?}}. Am I missing out the definition of my arguments in my HTML?
Directing to views.py:
User input is CharField, could use get_object_or_404 to get the model pk. However when defining my urls.py I would get a Noreverse error as my url arguments is the primary key.
Directing to urls.py:
Url arguments is primary key. From the way I see it, I need to magically convert my User input Charfield to a pk before passing it to urls.py
Is there a (or) function for get() in django? E.g get_object_or_404(pk = q1 or course = q1)?
Would really appreciate any advice. Been staring at this for hours.

You are trying to use the reverse resolution of urls in Django.
In your html file correct form action url to the following and method should be POST:
<form action={% url 'process' %} method="POST">
In case you are trying to pass parameters along then use this:
<form action={% url 'process' request.user.id 4 %} method="POST">
Reference:
https://docs.djangoproject.com/en/1.10/topics/http/urls/

Yes i'm late but it can help others for better understanding how Django processes the request.
Django 3.0 pattern
How Django processes the request
Basic :
First Django check the matching URL.
If URL is matched then calling the defined view to process the request. (Success)
If URL not matched/found the Django invokes error Page Not Found
In detail reading :
Official Django Documentations How Django processes a request
These are your URL patterns :
urlpatterns = [ path('profile/edit/<int:pk>/',views.editprofile, name='editprofile'),]
Third argument in urlpatterns is for if you want to change the url pattern from current to this :
urlpatterns = [ url('profile/edit/user/id/<int:pk>',views.editprofile, name = 'editprofile'),]
You don't need to redefine url pattern in all Templates where you using url name.
For Example :
This is my template profile.html where i used the url name instead of hard coded url.
<a class="item" href="{% url 'editprofile' user.id %}" >Edit profile </a>
Solution of your problem :
.html
Only use url name instead of hard coded url in your templates and pass arguments.
<form action={% process no_of_arguments %} method="POST">
views.py
Here you can process your request
def process(request,no_of_arguments):
Become good django developer
You can also use Django ModelForms for your model.
Using model forms or simple form you can do multiple things
Modular approach
Write server side validation in related form instead of doing in views.py
Readable code - Clean code

Related

Form not submitting to correct url in django

Im making a web app in django and im having a problem with a form which isnt submitting to the correct place
searcc.html
<form method='POST', action='/saveApply'">
{% csrf_token %}
<div class="JobSub">
<input value="{{user.id}}" name="usrid">
<input value="{{comp.id}}" name="compid">
<button type="submit">Submit</button>
</div>
</form>
views.py
def saveApply(request):
current_user = request.user
if request.method == 'POST': # Foreign key to User is just the username
savedApply.objects.create(
user = request.POST.get('usrid'),
company = request.POST.get('company')
)
return render('main/profile.html') # Change later
return redirect('login')
The confusing thing is, when I press on the submit button Im not even getting sent to the login view. I am getting sent to the home page. I think the problem has something to do with the fact that this html page is getting included in another.
main.html
{% include 'main/search.html' %}
{% endblock %}
Main.html is also inheriting from another file
Urls.py
path('saveApply/', views.saveApply, name="saveApply"),
path('feed/', views.feed, name='feed'),

How do I access a single field while using For Loop to iterate through all the fields of a ModelForm in Django Template?

I have a model which has four ForeignKey fields, so they are dropdown fields in the form.
class Package(models.Model):
patient=models.ForeignKey(Patient, on_delete=CASCADE)
diagnosis=models.ForeignKey(Diagnosis, on_delete=CASCADE)
treatment=models.ForeignKey(Treatment, on_delete=CASCADE)
patient_type=models.ForeignKey(PatientType, on_delete=CASCADE)
date_of_admission=models.DateField(default=None)
max_fractions=models.IntegerField(default=None)
total_package=models.DecimalField(max_digits=10, decimal_places=2)
The forms.py:
class PackageForm(ModelForm):
class Meta:
model=Package
fields='__all__'
widgets={
"patient_type" : forms.Select(attrs={"onblur":"mf();"}),
"max_fractions" : forms.NumberInput(attrs={"onfocus":"mf();", "onblur":"tp();"}),
"total_package" : forms.NumberInput(attrs={"onfocus":"tp();", "onblur":"onLoad();"}),
'date_of_admission': DateInput(attrs={'type': 'date'}),
The views.py:
def package_view(request):
if request.method=='POST':
fm_package=PackageForm(request.POST, prefix='package_form')
if fm_package.is_valid():
package=fm_package.save()
IpdReport.objects.create(patient=package.patient, package=package)
fm_package=PackageForm(prefix='package_form')
return render (request, 'account/package.html', {'form5':fm_package})
else:
fm_package=PackageForm(prefix='package_form')
return render (request, 'account/package.html', {'form5':fm_package})
The Template:
<form action="" method="post" novalidate>
{% csrf_token %}
{{form5.non_field_errors}}
{% for fm in form5 %}
<div>
{{fm.label_tag}}
{{fm}}
<span>{{fm.errors|striptags}}</span><br><br>
</div>
{% endfor %}
<button type="submit" id="savebtn">Save</button>
</form>
Now, what I want is to insert an Anchor Tag next to all the foreign_key fields, in the template, to add a new object into the original table. For example, an Add Patient option next to the Patient's dropdown field, when clicked, a new, small window would show up with Patient form. The user enters the new patient's data, saves it and the same name shows up in the dropdown.
But as I am using a For Loop in the template, how would I be able to access those foreign key fields and apply the options? Any suggestions, please?
If it isn't a problem I would move away from rendering all of the fields with the 'forloop'. Instead I would use notation: form.field to render different fields. So it would look like:
{{ form.patient.label_tag }}
{{ form.patient }}
It should be much easier to navigate through fields this way, but of course it will require more typing :)

How to render a field request without refreshing the page?

I have a form with a few fields, the first being where a person enters their ID #, which is tied to a separate model for verification. I made this function get_employee_name, which returns the name based on the ID from the other model, but I'm not sure how to display it in the page, right on the top, without refreshing after the person tabs/clicks out? I'm not too familiar with html, but I was reading an ajax GET request would do the trick, but I'm not sure how to approach this.
This is basically so the person knows that the ID # they entered matches their name before proceeding to fill the rest out.
views.py
class EnterExitArea(CreateView):
model = EmployeeWorkAreaLog
template_name = "enter_exit_area.html"
form_class = WarehouseForm
def form_valid(self, form):
emp_num = form.cleaned_data['adp_number']
area = form.cleaned_data['work_area']
station = form.cleaned_data['station_number']
if 'enter_area' in self.request.POST:
form.save()
return HttpResponseRedirect(self.request.path_info)
elif 'leave_area' in self.request.POST:
form.save()
EmployeeWorkAreaLog.objects.filter(adp_number=emp_num, work_area=area, station_number=station).update(time_out=datetime.now())
return HttpResponseRedirect(self.request.path_info)
def get_employee_name(request):
adp_number = request.POST.get('adp_number')
employee = Salesman.objects.get(adp_number=adp_number)
employee_name = employee.slsmn_name
return employee_name
models.py
class EmployeeWorkAreaLog(TimeStampedModel, SoftDeleteModel, models.Model):
employee_name = models.CharField(max_length=25)
adp_number = models.ForeignKey(Salesman, on_delete=models.SET_NULL, help_text="Employee #", null=True, blank=False) #(max_length=50, help_text="Employee #", blank=False)
...
def __str__(self):
return self.adp_number
forms.py
class WarehouseForm(AppsModelForm):
class Meta:
model = EmployeeWorkAreaLog
widgets = {
'adp_number': ForeignKeyRawIdWidget(EmployeeWorkAreaLog._meta.get_field('adp_number').remote_field, site),
}
fields = ('adp_number', 'work_area', 'station_number')
enter_exit_area.html
{% extends "base.html" %}
{% block main %}
<form id="warehouseForm" action="" method="POST" data-stations-url="{% url 'operations:ajax_load_stations' %}" novalidate >
{% csrf_token %}
<div>
<div>
{{ form.adp_number.help_text }}
{{ form.adp_number }}
</div>
<div>
{{ form.work_area.help_text }}
{{ form.work_area }}
</div>
<div>
{{ form.station_number.help_text }}
{{ form.station_number }}
</div>
</div>
<div>
<div>
<button type="submit" name="enter_area" value="Enter">Enter Area</button>
<button type="submit" name="leave_area" value="Leave">Leave Area</button>
</div>
</div>
</form>
{% endblock main %}
We'll use ajax, with jQuery so be sure you have jQuery before you read.
first, you've to create an endpoint to GET, go to urls.py & add an endpoint say
path('/myserver/getID/', views.get_employee_name, name="whatever")
now, this calls get_employee_name right? Let's now call it in JS without refreshing.
here's the basic syntax ->
$.ajax({THIS IS A SIMPLE DICT})
ajax takes parameters
type which is the request type
url which is the request URL which we just made above (not the full url, you're specifying the endpoint from where you're located on the website so you just use /myserver/getID/)
it also takes data which is a dictionary with your posted data (yes a dictionary inside the bigger ajax dictionary
it CAN take success which is a function to call after getting the response with status 200 (success) and that success function can have the parameter response which is your response
it CAN take error which is a function that gets called after an error & takes error as argument
enough talking...
$.ajax({
url: 'myserver/getID',
type: 'GET',
data: // don't specify this, we're not posting any data,
success: function (response) {console.log(response.data)}, //this will be what returned from python
error: function (error){console.log(error)}
})
this is a simple ajax request
NOTE, if you return a redirect from python & accept it from ajax, it won't work, ajax can't redirect, be sure to remember that because most of the time people ask why redirect('mylink') doesn't work after I return it from ajax.
Another NOTE is the when dealing with post requests with ajax, you must include the csrf token which can be included by
csrfmiddlewaretoken: '{%csrf_token%}'
You can use Fetch API too if you want, or even normal XMLhttprequest.
Sounds like you have a few questions and should split them up but just to answer the main question in your title, "How to render a field request without refreshing the page?", this is how you do that part with some DOM manipulation. This is basic HTML and JavaScript you would need to fit into your project.
Once you get the name back from your lookup, you just need to insert the value into the DOM and that will render it, not requiring a refresh. Here's a simple example:
var clickMe = function() {
var element = document.getElementById('heading');
// Do your AJAX and lookup something...
element.textContent = "Name Lookup From Server Request";
}
<div>
<h1 id="heading"></h1>
<button onclick="clickMe()">Click Me</button>
</div>

Working with links in Django

I am working in a small blog application using Django. Sorry if the question is obvious, but I am a newbie. Actually it is my third since I started an online course. I have the following Queryset:
def all(request):
allTiles = Post.objects.values('title')
allPosts = Post.objects.all()[:3]
context = {'Posts': allPosts,"Titles":allTiles}
template = "home.html"
return render(request, template, context)
and the follwing html code:
<ol class="list-unstyled">
{% for singleTile in Titles %}
<li>{{singleTile.title}}</li>
{% endfor %}
</ol>
As you can see every title creates an link. Lets assume a person decides to read one of the posts. How can I use the title name and send a request back to the database to get the content of the post.
It is better to use the id or slug field for such task.
But if you surely want to use the title as the GET parameter then apply the urlencode filter to the field's value:
<a href="{% url 'post_detail' %}?title={{ singleTile.title|urlencode }}">
{{ singleTile.title }}
</a>
And the view will be something like this:
def post_detail(request):
post = get_object_or_404(Post, title=request.GET.get('title'))
return render(request, 'post_detail.html', {'post': post})
UPDATE: If you decide to go with the id/slug option then you can use the generic DetailView:
<a href="{% url 'post_detail' singleTile.id %}">
{{ singleTile.title }}
</a
urls.py:
from django.views.generic.detail import DetailView
from app.models import Post
url(r'^post/(?P<pk>\d+)/$', DetailView.as_view(model=Post),
name='post_detail')
You have to configure url first like
{% url 'app.views.post_id' singleTile.id %}</li>
In your urls
url(r'^post/(?P<post_id>\d+)/$', views.by_id, name='post_id'),
And in your views
def post_id(request, post_id):
allTiles = Post.objects.get(id=post_id)
return render(request, template, context)

Django 'ManagementForm data is missing or has been tampered with' when saving modelForms with foreign key link

I am rather new to Django so this may be an easy question. I have 2 modelForms where there is a ForeignKey to another. My main goal is to save Indicators with a link to Disease (FK), such that for a particular disease, you can have multiple indicators.
With the code below, I get an error when I hit submit that says 'ManagementForm data is missing or has been tampered with'. Also, the code in views.py does not seem to be validating at the 3rd 'if' statement where there is a return HttpResponseRedirect. However, when I check my database, the values from the form have been written. Any ideas on why the error has been raised? and how to fix it?
My code is below:
models.py
#Table for Disease
class Disease(models.Model):
disease = models.CharField(max_length=300)
#Tables for Indicators
class Indicator(models.Model):
relevantdisease = models.ForeignKey(Disease)
indicator = models.CharField(max_length=300)
forms.py
class DiseaseForm(forms.ModelForm):
class Meta:
model = Disease
class IndicatorForm(forms.ModelForm):
class Meta:
model = Indicator
DiseaseFormSet = inlineformset_factory(Disease,
Indicator,
can_delete=False,
form=DiseaseForm)
views.py
def drui(request):
if request.method == "POST":
indicatorForm = IndicatorForm(request.POST)
if indicatorForm.is_valid():
new_indicator = indicatorForm.save()
diseaseInlineFormSet = DiseaseFormSet(request.POST, request.FILES, instance=new_indicator)
if diseaseInlineFormSet.is_valid():
diseaseInlineFormset.save()
return HttpResponseRedirect('some_url.html')
else:
indicatorForm = IndicatorForm()
diseaseInlineFormSet = DiseaseFormSet()
return render_to_response("drui.html", {'indicatorForm': indicatorForm, 'diseaseInlineFormSet': diseaseInlineFormSet},context_instance=RequestContext(request))
template.html
<form class="disease_form" action="{% url drui %}" method="post">{% csrf_token %}
{{ indicatorForm.as_table }}
<input type="submit" name="submit" value="Submit" class="button">
</form>
You have neither diseaseFormSet nor diseaseFormSet's management form in your template, yet you try to instantiate the formset. Formsets require the hidden management form which tells django how many forms are in the set.
Insert this into your HTML
{{ diseaseFormSet.as_table }}
{{ diseaseFormSet.management_form }}