How can I access my sqlite3 database through the html template using Django? - html

I have a Django application where most of my backend code is in views.py. In the frontend, I'm using an html template, but currently I have hardcoded options that the user can choose from a drop down menu. Those hardcoded options are all available in the sqlite3 database which is used extensively in views.py. Is there a way that I read those fields of database from the html file directly instead of hardcoding them?

Yes, if you have a model that will store the data from the fields you defined in your template then you can create a form that will store the data about that models fields, then you can just pass the form to the template, for example:
models.py
class Person(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField(default=1)
forms.py
from django import forms
from .models import Person
class PersonForm(forms.ModelForm)
class Meta:
model = Person
fields = '__all__' # or pass an iterable with your model field names as strings
views.py
from .models import Person
from .forms import PersonForm
def create_person(request):
if request.method == 'POST':
form = PersonForm(request.POST)
if form.is_valid():
person = form.save() # creates and saves a new Person instance
return redirect('person', pk=person.pk) # redirect to the view that displays the person
else:
form = PersonForm()
return render(request, 'create_person.html', {'form': form}) # pass the form to the view in a context dictionary
def person(request, pk): # pass the primary key of a person to the view
person = Person.objects.get(pk=pk)
return render(request, 'person.html', {'person': person})
create_person.html ( this is the view that will have the form )
<form method="post">
{% csrf_token %}
{{ form.as_p }} <!-- render form fields inside <p> tags ( you can also use table or list ) -->
<button type="submit" value="Save"></button>
</form>
person.html
<p>This is the page that belongs to the {{ person.name }}</p>
<p>The {{ person.name }} is {{ person.age }} years old.</p>
And finally set up the urls.py for your views:
from django.urls import path
from . import views
urlpatterns = [
path('create_person', views.create_person, name="create_person"),
path('person/<int:pk>/', views.person, name="person") # pass the pk argument into the url path here
]

Related

How to get value attribute in views

Hello is there a way to get 'value' attribute from HTML template into views.py and use it there??
HTML:
<form class="card__delete" method="POST"> {% csrf_token %}
<button value="{{item.id}}" class="card__delete__button" name="delete" type="submit">&#10008</button>
</form>
views.py
class TodoView(UserPassesTestMixin, CreateView):
model = Item
template_name = 'home/todo.html'
form_class = ItemCreationForm
def test_func(self):
return self.request.user.username in self.request.path
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['card'] = Card.objects.get(user=self.request.user, pk=self.kwargs.get('pk'))
return context
def post(self, request, pk, username):
if 'delete' in self.request.POST:
Item.objects.get(id=pk).delete()
print('deleted')
return redirect('home-page')
The value is in request.POST, so you should be able to access it with
value = self.request.POST.get('delete', None)
Take care to validate that value before using the id of an object to do anything catastrophic to it (such as .delete()). It's not being validated through a form, and a random hacker on the internet might try posting back random numbers which might be the id of other objects
Added after reading comment:
Data pulled out of request.POST is raw data. I don't think CSRF token can protect against a person who uses inspect object in his browser and changes the value of that button before clicking it. I may be wrong.
Anyway, if you can check the value using a queryset of the object type with a filter for objects that this user is permitted to delete, then do. For example,
value = request.POST.get("delete", None)
if value:
obj = Card.objects.filter(
user=self.request.user ).get( pk=value)
# will raise CardDoesNotExist if value isn't one of user's objects,
# because it's been filtered out
obj.delete()

How to call in django index.html fle for "GET" "POST" method for get data from id (fields)?

In django I have create query like wise if someone want information:
In district parameter select Pune, then output gives data for pune district only.
for example :
http:127.0.0.1/api/?district=Pune
htt:127.0.0.1:8000/?crop = groundnut
and so on.
Next,I want to create a Html page for my starting django page(index.html)
if I runserver http:127.0.0.1:8000/
display my html file , where Our models fields(paramter) is id and then user submit the question "if" condition will be trigger and searching information for that parameters.
like wise:
District = __________ submit
gives data only for selected district name only
also
Crop = ______________ submit
gives data only for selected crop name only
likewise run this query
http:/api/?crop=groundnut
if user choose crop name is groundnut,
if use choose crop name is guava, then http:/api/?crop=guava query will be run.
So,now I want to create index.html file multiple parameters works.(AND query will apply)
http:/api/district=Pune&crop=groundnut
So, I want to create html page which call to this query and its show me this type
Distrcit : ________ Crop : __________ submit
here is my models.py
from django.db import models
from mongoengine import Document, fields
class Tool(Document):
crop = fields.StringField(required=True)
district = fields.StringField(required=True)
def __str__(self):
return self.crop
def save(self,*args, **kwargs):
super().save(*args, **kwargs)
class Meta:
verbose_name_plural ='tool'
project/urls.py
from django.conf import settings
from django.conf.urls.static import static
from django.conf.urls import include, url
from django.contrib import admin
from app.views import *
from routers import HybridRouter
router = HybridRouter()
router.register(r'tool', ToolViewSet, r"tool")
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^api/', include(router.urls, namespace='api')),
url(r'^$', index_view, {}, name='index'),
]
app/views.py
from django.template.response import TemplateResponse
from rest_framework_mongoengine.viewsets import ModelViewSet as MongoModelViewSet
from app.serializers import *
class ToolViewSet(MongoModelViewSet):
serializer_class = ToolSerializer
my_filter_fields = ('crop', 'district',) # specify the fields on which you want to filter
def get_kwargs_for_filtering(self):
filtering_kwargs = {}
for field in self.my_filter_fields: # iterate over the filter fields
field_value = self.request.query_params.get(field) # get the value of a field from request query parameter
if field_value:
filtering_kwargs[field] = field_value
return filtering_kwargs
def get_queryset(self):
queryset = Tool.objects.all()
filtering_kwargs = self.get_kwargs_for_filtering() # get the fields with values for filtering
if filtering_kwargs:
queryset = Tool.objects.filter(**filtering_kwargs) # filter the queryset based on 'filtering_kwargs'
return queryset
from .models import Tool
from django.shortcuts import render
def index_view(request):
questions=None
if request.GET.get('crop'):
crop = request.GET.get('crop')
questions = Tool.objects.filter(crop__icontains=crop)
district = request.GET.get('district')
query = Tool.object.create(crop=crop, district=district)
query.save()
return render(request, 'index.html',{
'questions': questions,
})
what I have to change in views.py file for index.html to get parameter and gives exact information after user click on submit button ?
index.html
<form method="GET">
Crop: <input type="text" name="crop"><br/>
Taluka: <input type="text" name="taluka"><br/>
<input type="submit" value="Submit" />
</form><br/><br/>
{% for question in questions %}
<p>{{question}}</p>
{% endfor %}
can you help me how to get data and run the query ?
where I need to changes ?
Its a TYPO error in this line :
query = Tool.object.create(crop=crop, district=district)
object should be objects ,like this :
query = Tool.objects.create(crop=crop, district=district)
Update your code like this :
from .models import Tool
from django.shortcuts import render
def index_view(request):
questions=None
if request.GET.get('crop'):
crop = request.GET.get('crop')
questions = Tool.objects.filter(crop__icontains=crop)
district = request.GET.get('district')
query = Tool.objects.create(crop=crop, district=district)
query.save()
return render(request, 'index.html',{
'questions': questions,
})
And, Update the save method of your Tool model like this :
class Tool(Document):
crop = fields.StringField(required=True)
district = fields.StringField(required=True)
def __str__(self):
return self.crop
def save(self,*args, **kwargs):
super(Tool, self).save(*args, **kwargs)
In your index.html file, change {{question}} to {{question.crop}}. You have to refer to the field (in your case crop) on the model you want to render on your page.
Also, the default manager is located at Tool.objects not Tool.object.
In your models.py, super should be super(Tool, self). Also model Tool should inherit from django.db.models.Model. Your fields must be from django.db.models
class Tool(Model):
crop = models.CharField()

Django Rest - Create method, returns error 405 Method Not Allowed

I created a view to create a new object. In the DRF default page everything works fine, but when I try to create an simple HTML page as a user interface (by adding renderer_classes and template_name to the view), the following error occurs: 405 Method Not Allowed.
I created an html page to retrieve/update a client detail information, and it works fine. However, I was unable to do so to create a new client.
models.py
class Client(models.Model):
client_rut = models.CharField(max_length=12, unique=True, verbose_name="RUT")
client_name = models.CharField(max_length=250, verbose_name="Nombre Cliente")
client_region = models.CharField(max_length=50, verbose_name="Region")
client_tel = models.CharField(max_length=20, blank=True, verbose_name="Telefono")
client_email = models.EmailField(blank=True, verbose_name="E-mail")
is_active = models.BooleanField(default=True, verbose_name="Activo")
class Meta:
ordering = ['client_rut']
def __str__(self):
return self.client_rut + ' - ' + self.client_name
urls.py
urlpatterns = [
# /clients/
url(r'^$', views.ClientView.as_view(), name='clients'),
url(r'^(?P<pk>[0-9]+)/$', views.ClientDetailView.as_view(), name='clientdetail'),
url(r'^create/$', views.ClientCreateView.as_view(), name='clientcreate')
]
urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html', 'xml'])
serializers.py
class ClientListSerializer(ModelSerializer):
url = HyperlinkedIdentityField(view_name='clients:clientdetail',)
class Meta:
model = Client
fields = '__all__'
class ClientDetailSerializer(ModelSerializer):
class Meta:
model = Client
fields = '__all__'
views.py
#this view works fine
class ClientDetailView(views.APIView):
queryset = Client.objects.all()
serializer_class = ClientDetailSerializer
renderer_classes = [TemplateHTMLRenderer]
template_name = 'clientdetail.html'
def get(self, request, pk):
client = get_object_or_404(Client, pk=pk)
serializer = ClientDetailSerializer(client)
return Response({'serializer': serializer, 'client': client})
def post(self, request, pk):
client = get_object_or_404(Client, pk=pk)
serializer = ClientListSerializer(client, data=request.data)
if not serializer.is_valid():
return Response({'serializer': serializer, 'client': client})
serializer.save()
return redirect('clients:clients')
# this one does not
class ClientCreateView(generics.ListCreateAPIView):
queryset = Client.objects.all()
serializer_class = ClientListSerializer
renderer_classes = [TemplateHTMLRenderer]
template_name = 'clientcreate.html'
def post(self, request):
Client.objects.create()
return redirect('clients:clients')
clientcreate.html
{% load rest_framework %}
<html><body>
<form action="{% url 'clients:clientcreate' %}" method="POST">
{% csrf_token %}
<div class="col-xs-6 ">
{% render_form serializer %}
</div>
<div>
<input type="submit" value="Grabar">
</div>
</form>
</body></html>
clientdetail.html is almost identical to clientcreate.html, save for this:
<form action="{% url 'clients:clientdetail' pk=client.pk %}" method="POST">
I think I've seen all 405 related questions and I just couldn't solve my problem (doesn't necessarily mean the answer's not out there though).
Hope someone can help me with this one.
Thanks!

Django-Filter Form Displaying All Filters?

I've just started working with Django Filter. When I test, the filter.form shows filters for all fields and I can't get it to show only the desired filters.
Here's the filter:
class EmployeeFilter(django_filters.FilterSet):
hire_date = django_filters.DateFilter(name='hireDate', lookup_expr='hireDate__year')
hire_date__gte = django_filters.DateFilter(name='hireDate', lookup_expr='hireDate__gte')
hire_date__lte = django_filters.DateFilter(name='hireDate', lookup_expr='hireDate__lte')
class Meta:
model = models.Employee
fields=['hireDate']
Here's the view:
def test_filters(request, template_name='filter-test.html'):
from . import filters
f = filters.EmployeeFilter(request.GET, queryset=models.Employee.objects.all())
return render_to_response(template_name, locals(), context_instance=RequestContext(request))
Has anyone ever run into this? How'd you fix?
I had the same issue but I was able to solve
class EmployeeFilter(django_filters.FilterSet):
class Meta:
model = Employee
fields=['hireDate']
In Views.py
def filters(request):
employee = Employee.objects.all()
myFilter = EmpoyeeFilter(request.GET, queryset=employee)
employee = myFilter.qs
context = {
'myFilter': myFilter,
'employee': employee,
}
return render(request, 'templates/index.html', context)
index.html file
<html>
<form method="get">
{{myFilter.form}}
</form>
</html>
The filter set's form plays both of Django Form's two roles:
It enables you to display the form in your template
It validates the incoming values.
The second of these is (arguably) the more important — certainly for Django Filter: if you remove fields from the form they will not be filtered against.
Your best bet is probably to just define less fields on the filter set. (If you need all fields in some cases just define two filter sets, one for each need.)
(The other option would be to define a separate Django Form with just the fields you need and use that in your template, leaving the filter set's form to do the actual validation.)
I hope that helps.
models.py
class Employee(models.Model):
hire_date = models.DateField()
name = models.CharField(max_length=128)
filters.py
class EmployeeFilter(django_filters.FilterSet):
hire_date = django_filters.DateFilter(field_name='hire_date', lookup_expr='gt')
hire_date__gte = django_filters.DateFilter(field_name='hire_date', lookup_expr='gt')
hire_date__lte = django_filters.DateFilter(field_name='hire_date', lookup_expr='gt')
name__icontains = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
class Meta:
model = Employee
fields = {}
views.py
def employee_view(request):
f = EmployeeFilter(request.GET, queryset=Employee.objects.all())
return render(request, 'product/employee.html', {'filter': f})
templates/my-app/employee.html
<h1>Employee</h1>
<form method="get">
{{ filter.form.as_p }}
<input type="submit"/>
</form>
<ul>
{% for employee in filter.qs %}
{{ employee.hire_date }}<br/>
{% endfor %}
</ul>
The field_name specifies the name of the field in the model ie Employee and lookup_expr is a string which specifies the filter to use on the column of table for eg gt, gte, lt, lte, exact, iexact, contains, icontains
If you want to filter against a field, but do not want it in the form, you can do the following:
import django_filters
from django import forms
class MyFilter(django_filters.FilterSet):
field = django_filters.CharFilter(
widget=forms.HiddenInput()
)
class Meta:
model = MyModel
fields = ['other_field', 'field']
The only downside is, it will show as an empty parameter in the URL, when you submit the form. But it won't affect your results, since its an empty value.

Django how to ManyToManyField show in template as Select widget

My models.py:
class Model2(models.Model)
choice_field = models.ManyToManyField(to=Model)
my views.py:
def func(request):
if request.method == 'POST':
form = ModelForm(request.POST)
if form.is_valid:
form.save()
return.........................................
And so what I need to do with form request?
my template.html:
<div>
{{ form.choice_field }}
</div>
I get a values list and can a scroll and choose what I want. But i want to use Select with options for this values in template.
You can define widget for each field of your model manually. Assuming you using built-in ModelForm your code in forms.py can be something like this:
from django.forms import ModelForm, Select
class Model2Form(ModelForm):
class Meta:
model = Model2
fields = [
'choice_field',
]
widgets = {
'choice_field': Select(),
}