Django Model form don't update database records - python

I am new in django and I want to create a form to update some database entries.
this is a simple form where I have a simple input text where I write the id of the record that I want to update:
main.html
<form method='post' action='/config/{{ idprov }}' >
<input type="text" class="form-control" name="idprov" id="idprov" value ="{{ idprov }}" />
<input class="btn btn-danger" type="submit" value="Config">
</form>
forms.py
from django import forms
from .models import Proveedor, Estado, Config
class ConfigForm(forms.ModelForm):
class Meta:
model = Config
this is my views.py:
def configView(request,idprov):
prov = Config.objects.get(idproveedor=idprov)
if request.method == 'POST':
form = ConfigForm(request.POST or None, instance=prov)
if form.is_valid():
form.save(commit=false)
return HttpResponseRedirect('/monitor/')
else:
form = ConfigForm( instance=prov)
return render_to_response('config.html',
{'form':form})
my template config.html:
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-4">
<form method='POST' action='' >
<div class="form-group">{% csrf_token %}
{{ form.as_p }}
</div>
<button type='submit' class="btn btn-primary">Grabar</button>
</form>
</div>
</div>
</div>
{% endblock %}
my urls.py:
from django.conf.urls import patterns, include, url
from prov.views import home
from prov.views import proveedores
from prov.views import estado
from prov.views import monitorViewV2
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
url(r'^$', 'prov.views.home', name='home'),
url(r'^proveedores/$', 'prov.views.proveedores', name='proveedor'),
url(r'^estado/$', 'prov.views.estado', name='estado'),
url(r'^monitor/$', 'prov.views.monitorView', name='monitor'),
url(r'^monitorv/$', 'prov.views.monitorViewV2', name='monitorv2'),
url(r'^config/(?P<idprov>\d+)/$', 'prov.views.configView',name='config'),
url(r'^admin/', include(admin.site.urls)),
)
But I receive the error Page not found.
I try to follow other snippets and always raise different errors.
I think the error is in the urls.py and in the way I pass the argument from the main.html.
Any advice or snippet will be very appreciated
Thanks in advance

First you have a form.save(commit=false) in your view without saving it later, thats mean the data is never saved into the model.
Second in your template config.html the form action is empty <form method='POST' action=''> change for <form method='POST' action='.'>
I hope that help to you.

Related

Fill out the form and save it in db base

I am working on a Django project and I want to fill out a form and save the data in the db database and then be able to show it on another page, I managed to create the form, following some tutorials, but it does not write me anything in the database. Here's how I currently have things:
forms.py
from django import forms
from .models import AusenciasForm
from django.contrib.auth.models import User
class AusenciasForm(forms.ModelForm):
class Meta:
model = AusenciasFormulario
fields = '__all__'
widgets = {'fecha': forms.DateInput(attrs={'type': 'date'})}
models.py
from django.db import models
from django.utils import timezone
import datetime
from django.contrib.auth.models import User
from django.urls import reverse
class AusenciasFormulario(models.Model):
#razon = models.ModelChoiceField(label="Razón", queryset=razones.object.all())
fecha = models.DateField(("Date"),default=datetime.date.today)#label="Fecha", required=True
razon = [
('Estudios/Examen','Estudios/Examen'),
('Enfermedad','Enfermedad'),
('Lesión','Lesión'),
('Motivos personales','Motivos personales'),
('Motivos familiares','Motivos familiares'),
('Otros','Otros')
]
motivo = models.CharField(max_length=100, choices=razon, default='Otros')
comentarios= models.CharField(max_length=200,blank=True)
jugador = User
views.py
class FormularioAusenciaView(HttpRequest):
def index(request):
ausencias_formulario = AuForm.objects.all()
return render(request, 'blog/ausencias.html', {'ausencias_formulario':ausencias_formulario})
def procesar_formulario(request):
#if request.method == 'POST':
form = AusenciasForm(request.POST)
if form.is_valid():
form.save()
form = AusenciasForm()
return HttpResponseRedirect('ausencias/') #Add your route name, where you want to go after form save
else:
form = AusenciasForm()
return render(request, 'blog/formularioAusencia.html', {'form':form})
Urls.py
from django.urls import path
from .views import PostListView, PostDetailView, PostCreateView, PostUpdateView, PostDeleteView,UserPostListView, FormularioAusenciaView, ausencias
from .import views
from django.contrib.auth.decorators import login_required
urlpatterns = [
path('', login_required(PostListView.as_view()), name='blog-home'),
path('user/<str:username>',login_required( UserPostListView.as_view()), name='user-posts'),
path('post/<int:pk>/',login_required( PostDetailView.as_view()), name='post-detail'),
path('post/new/',login_required( PostCreateView.as_view()), name='post-create'),
path('post/<int:pk>/update/',login_required( PostUpdateView.as_view()), name='post-update'),
path('post/<int:pk>/delete/',login_required( PostDeleteView.as_view()), name='post-delete'),
path('about/', views.about, name='blog-about'),
path('formularioAusencia/',login_required( FormularioAusenciaView.index), name='formularioAusencia'),
#path('asistencia_done/',formularioAusencia, name='asistencia_done'),
path('ausencias/',login_required( views.ausencias), name='ausencias'),
]
the template
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">{{ user.email }}</p>
</div>
</div>
{% if user.is_authenticated %}
<p></p><a class="mr-2">Rellenar si no vas a poder acudir a un próximo entrenamiento o partido</a></p>
<!--<label><input type="checkbox" id="cbox1" value="first_checkbox"></label><br>-->
<form method="POST" action="{% url 'ausencias' %}">{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-danger btn-sm mt-1 mb-1" type="submit">Enviar</button>
</form>
</div>
<div class="form-group">
</div>
{% endif %}
</div>
{% endblock content %}
In forms.py:
You have imported wrong model name:
change this
from .models import AusenciasForm
To this:
from .models import AusenciasFormulario
And in views.py file:
You have not added any orm query so that's why it is not saving in db.
views.py :
Do this:
def index(request):
ausencias_formulario = AusenciasFormulario.objects.all() #Here i have retrieved data using orm
return render(request, 'blog/formularioAusencia.html', {'ausencias_formulario':ausencias_formulario})
def procesar_formulario(request):
if request.method == 'POST':
form = AusenciasForm()
if form.is_valid():
form.save()
return HttpResponseRedirect('/home/') #Add your route name, where you want to go after form save
else:
form = AusenciasForm()
return render(request, 'blog/formularioAusencia.html', {'form':form})
And in your templates:
formularioAusencia.html
<form method='post'>
{{form}}
<input type="submit" /> #Added new code here
</form>
After submitting above form, using below code, you will get that fields.
Add below code after the form tag.
To display all the fields to templates add the below code in template:
{% for field in ausencias_formulario %}
{{field.fecha}}
#Add remaining fields here to display
{% endfor %}

HTML form data not posting to url but shows up in django model

brand new to django and webapps here.
I am experimenting with models and forms, and I have been able to successfully post data to my site using text fields and input buttons.
My hang is that my second form does not post anything and does not throw an error either.
I queried the class CustID and the set came back with all the data I had posted.
Here is the code and HTML:
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Data Input</title>
</head>
<body>
<h1>Subscription Update</h1>
<h2></h2>
<form action="/addID/" method="post">{% csrf_token %}
<input type="text" name="content"/>
<input type="submit" value="Add"/>
</form>
<form action="/getCust/" method="post">{% csrf_token %}
<input type="text" name="cid"/>
<input type="submit" value="Customer Look Up"/>
</form>
<ul>
{% for SubID_item in all_items %}
<li>{{ SubID_item.content }}
<form action="/deleteID/{{SubID_item.id}}/"
style="display: inline;"
method="post">{% csrf_token %}
<input type="submit" value="Delete"/>
</form>
</li>
{% endfor %}
</ul>
</body>
</html>
Model:
from django.db import models
# Create your models here.
class SubID(models.Model):
content = models.TextField()
class CustID(models.Model):
cid = models.TextField()
views:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .models import SubID, CustID
import stripe
import json
# Create your views here.
def StrpFormView(request):
all_subid_items = SubID.objects.all()
return render(request, 'STRP_FORM.html',
{'all_items': all_subid_items})
def addID(request):
new_item = SubID(content=request.POST['content'])
new_item.save()
return HttpResponseRedirect('/STRP_Input/')
def getCust(request):
new_item = CustID(cid=request.POST['cid'])
new_item.save()
return HttpResponseRedirect('/STRP_Input/')
def deleteID(request, SubID_id):
del_items = SubID.objects.get(id=SubID_id)
del_items.delete()
return HttpResponseRedirect('/STRP_Input/')
def basere(request):
return HttpResponseRedirect('/STRP_Input/')
urls:
from django.contrib import admin
from django.urls import path
from STRP_FORM.views import StrpFormView, addID, deleteID, getCust, basere
urlpatterns = [
path('admin/', admin.site.urls),
path('STRP_Input/', StrpFormView),
path('addID/', addID),
path('deleteID/<int:SubID_id>/', deleteID),
path('getCust/', getCust),
path('', basere),
]
Thanks for taking the time to help me out!
NEW CODE:
def StrpFormView(request):
all_subid_items = SubID.objects.all()
all_custid_items = CustID.objects.all()
return render(request, 'STRP_FORM.html',
{'sub_items': all_subid_items},
{'cust_items': all_custid_items})
<ul>
{% for CustID_item in cust_item %}
<li>{{ cust_item.cid }}</li>
{% endfor %}
</ul>

Can't be redirected after form action in Django

I created a form for creating a new item in Django. The app should be redirected to item_new but it's not working. This below error occurs.
Page not found
http://127.0.0.1.8000/item/new
show.html
<form
action="{% url 'item_new' %}"
method="POST"
enctype="multipart/form-data"
>
{% csrf_token %}
<div class="formItem">
<label>Name</label>
<input type="name" name="name" />
</div>
<div class="formBtn">
<input type="submit" class="btn btnPrimary" value="Submit" />
</div>
</form>
urls.py
urlpatterns = [
path('item/<slug:slug>/', views.item_detail, name='item_detail'),
path('item/new/', views.item_new, name='item_new'),
]
views.py
def item_detail(request, slug):
item = get_object_or_404(Item, slug=slug)
return render(request, 'item/show.html', {'item': item})
def item_new(request):
return redirect('home')
In your urls.py file, change the order of lines. Like this:
urlpatterns = [
path('item/new/', views.item_new, name='item_new'),
path('item/<slug:slug>/', views.item_detail, name='item_detail'),
]
The order of urls, does matter. In your current situation, requests made to http://127.0.0.1.8000/item/new will be sent to item_detail view function instead of item_new.

Trying to update the post in database.But getting Page not found (404)?And want to know how to update the data in database?

I'm trying to create a blog app with django.When clicked on a post it displays that post in separate page.In that i created edit and delete option.When i click on edit it returns edit option.But when i change some content and click on update it returns page not found error.
#urls.py
from django.urls import path,include
from . import views
urlpatterns=[
path('',views.homepage),
path('register',views.register,name='register'),
path('login',views.login,name='login'),
path('logout',views.logout,name='logout'),
path('newpost',views.newpost,name="newpost"),
path('<int:pk>', views.post_detail, name='post_detail'),
path('<int:pk>/edit', views.edit, name='edit'),
path('update', views.update, name='update'),
]
<!---update.html page--->
{% extends 'layout.html' %}
{% block content %}
<div class="box">
<form action="updated" method="POST">
{% csrf_token %}
<h3>Title of Post</h3>
<input type="text" maxlength="100" name="title" class="inputvalues"
value={{post.title}}>
<h3>Description</h3>
<textarea name="desc" style="width: 500px;margin: 0 auto;padding:
5px;height:40%" >{{post.desc}}</textarea>
<button type="submit" id="lg" >Update</button>
</a>
</form>
</div>
{% endblock %}
#views.py
def edit(request,pk):
post=Post.objects.get(pk=pk)
return render(request,'update.html',{'post': post})
def update(request):
post=Post.objects.get(pk=pk)
title=request.POST['title']
desc=request.POST['desc']
update =
Post(title=title,desc=desc,author_id=request.user.username)
update.title= title
update.desc= desc
update.save();
return redirect('indpost.html')
the url for displaying individual post is http://127.0.0.1:8000/48 where 48 is pk_id
the url when i click on edit is http://127.0.0.1:8000/48/edit
the url when i click on update is http://127.0.0.1:8000/48/updated
Your urlpattern has a typo:
urlpatterns=[
path('',views.homepage),
path('register',views.register,name='register'),
path('login',views.login,name='login'),
path('logout',views.logout,name='logout'),
path('newpost',views.newpost,name="newpost"),
path('<int:pk>', views.post_detail, name='post_detail'),
path('<int:pk>/edit', views.edit, name='edit'),
path('update', views.update, name='update'),
]
The last path() should be like this:
path('updated', views.update, name='update'),
OR
You can change the action attribute on the HTML form:
{% extends 'layout.html' %}
{% block content %}
<div class="box">
<form action="update" method="POST">
{% csrf_token %}
<h3>Title of Post</h3>
<input type="text" maxlength="100" name="title" class="inputvalues"
value={{post.title}}>
<h3>Description</h3>
<textarea name="desc" style="width: 500px;margin: 0 auto;padding:
5px;height:40%" >{{post.desc}}</textarea>
<button type="submit" id="lg" >Update</button>
</a>
</form>
</div>
{% endblock %}
Where did you get the pk in this line?
def update(request):
post=Post.objects.get(pk=pk)
#
you should first update the path like this:
path('<int:pk>/update', views.update, name='update') #I STRONGLY RECOMMEND USING A SLUG INSTEAD OF PK
and then update the method like this:
def update(request, pk):
in the return part, change it to :
return redirect('post_detail')
change the form action to:
{% url 'update' pk=post.pk %} #change post.pk to your pk
now you should be ok for the 404, but you are not updating the post, you created a new one, you can do:
post=Post.objects.get(pk=pk)
title=request.POST['title']
desc=request.POST['desc']
post.title= title
post.desc= desc
post.save()
and why do you even have a semicolon, lol

Django context processor and csrf_token

I have a login form that I want to be available in all my views, so I created a context processor to add this form to every loaded context.
The problem is that {% csrf_token %} on the form template won't render the hidden input tag with the CSRF token value.
This is the context_processor order in settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'django.core.context_processors.request',
'django.core.context_processors.csrf',
'absolute.context_processors.absolute',
'myproject.app.context_processors.base',
)
And then the processor itself on app/context_processors.py:
from django.contrib.auth.forms import AuthenticationForm
def base(request):
context = dict()
if not request.user.is_authenticated():
context['login_form'] = AuthenticationForm()
return context
The form template:
{% load i18n %}
<form method="post" action="{% url "django.contrib.auth.views.login" %}">
{% csrf_token %}
<input type="hidden" name="next" value="{% if request.GET.next %}{{ request.GET.next }}{% else %}{{ request.get_full_path }}{% endif %}" />
{{ login_form.as_p }}
<input type="submit" class="button success expand" value="{% trans 'Login' %}" />
</form>
The HTML output for this form:
<form action="/accounts/login/" method="post">
<input type="hidden" value="/" name="next">
<p><label for="id_username">Usuário:</label> <input type="text" name="username" maxlength="254" id="id_username"></p>
<p><label for="id_password">Senha:</label> <input type="password" name="password" id="id_password"></p>
<input type="submit" value="Login" class="button success expand">
</form>
And the error I get when submitting it:
CSRF verification failed. Request aborted.
However, and as I'm only using class-based views, if I add a csrf_protect decorator the form will work, but like this I would have to declare the dispatch method in all my views:
from django.views.decorators.csrf import csrf_protect
class HomeView(TemplateView):
template_name = 'home.html'
#method_decorator(csrf_protect)
def dispatch(self, *args, **kwargs):
return super(HomeView, self).dispatch(*args, **kwargs)
Problem status
I gave up from putting the AuthenticationForm on all my views by creating a login form page. Anyway, it would still be awesome if someone could help me find a solution for this problem.
I've spent a couple of hours fighting an issue similar to the one you've described here. The {% csrf_token %} wasn't rendering anything and I was seeing this when in debug mode:
defaulttags.py:66: UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value. This is usually caused by not using RequestContext.
I was using a simple view that inherited from a TemplateView:
class MenuIndexView(TemplateView):
template_name = 'menu/index.html'
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
session = self.request.session
kwargs['zip_code'] = session.get('zip_code')
kwargs['calendar'] = helpers.get_menu_calendar(date.today() + timedelta(days=1), timedelta(days=14))
kwargs['forms'] = {'zip_code': forms.ZipCodeForm({'zip_code': session.get('zip_code')})}
return kwargs
After fussing around a bit under Django's I realized that pretty much no context at all was available where the tag was being generated (CsrfTokeNode on Django's defaulttags.py file):
class CsrfTokenNode(Node):
def render(self, context):
csrf_token = context.get('csrf_token', None)
if csrf_token:
if csrf_token == 'NOTPROVIDED':
return format_html("")
else:
return format_html("<input type='hidden' name='csrfmiddlewaretoken' value='{}' />", csrf_token)
else:
# It's very probable that the token is missing because of
# misconfiguration, so we raise a warning
if settings.DEBUG:
warnings.warn(
"A {% csrf_token %} was used in a template, but the context "
"did not provide the value. This is usually caused by not "
"using RequestContext."
)
return ''
In this point of the code I was only seeing an item within the context, with a zip_code key.
I opened up the main template file and realized that I was making a rookie mistake - this was my main template menu/index.html:
{% extends 'base.html' %}
{% block content %}
<div class="menu-order-meta zip_calendar">
<div class="ink-grid align-center">
<div class="column-group gutters half-vertical-padding medium">
{% include 'partials/menu/zip-code.html' with zip_code=zip_code only %}
</div>
</div>
</div>
{% endblock %}
I was including the form through a partial template and I was explicitly restricting the available context within that partial template - notice the with zip_code=zip_code only declaration - (and by doing so, implicitly turning the csrf_token context processor unavailable).
Maybe are you missing django.middleware.csrf.CsrfViewMiddleware in MIDDLEWARE_CLASSES ?
MIDDLEWARE_CLASSES = (
....
'django.middleware.csrf.CsrfViewMiddleware',
....
)

Categories

Resources