I looked at similar questions but they do not seem to apply. I have a very simple django form which does not show on the website, I only see the Submit button. Here are the relevant files:
models.py
from django.db import models
from django.urls import reverse
import uuid
# Create your models here.
class Job(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False)
job_name = models.CharField(max_length=200)
#One to many relationship requires on_delete
email = models.EmailField()
def __str__(self):
return self.job_name
forms.py
from django import forms
class JobForm(forms.Form):
job_name = forms.CharField(max_length=200)
email = forms.EmailField()
views.py
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import JobForm
from .models import Job
class HomePageView(TemplateView):
template_name = 'index.html'
class SubmitPageView(TemplateView):
template_name = 'submit.html'
def submit_job(request):
# Retrieve post by id
if request.method == 'POST':
# Form was submitted
form = JobForm(request.POST)
if form.is_valid():
#Form fields passed validation
#If the form is valid, we retrieve the validated data accessing
#form.cleaned_data. This attribute is a dictionary of form fields and their values.
cd = form.cleaned_data
my_model = Job()
my_model.job_name = cd.get('job_name')
my_model.email = cd.get('email')
# Save the job to the database
my_model.save()
else:
form = JobForm()
return render(request, SubmitPageView(), {'form': form})
And in my template I have
<form method="POST" action=".">
<table>
{% csrf_token %}
{{ form.as_table }}
</table>
which gets rendered as:
<form method="POST" action=".">
<table>
<input type="hidden" name="csrfmiddlewaretoken" value="I7yL9XAUhEPiriKVHKtqh9UfhsLWoJrBo68uguqMecX8gmuNoJV7gykvsPc7FtQ2">
</table>
OK, I found the solution by following https://docs.djangoproject.com/en/3.0/topics/class-based-views/intro/
Basically, as I was using class-based views, the functions to get and post the form need to be subsumed into the class-based view for that page. Here is the current version
of views.py:
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import JobForm
from .models import Job
class HomePageView(TemplateView):
template_name = 'index.html'
class SubmitPageView(TemplateView):
form_class = JobForm
template_name = 'submit.html'
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
#Form fields passed validation
#If the form is valid, we retrieve the validated data accessing
#form.cleaned_data. This attribute is a dictionary of form fields and their values.
cd = form.cleaned_data
my_model = Job()
my_model.job_name = cd.get('job_name')
my_model.email = cd.get('email')
# Save the job to the database
my_model.save()
else:
form = JobForm()
return render(request, self.template_name, {'form': form})
Try code below:
# if a GET (or any other method) we'll create a blank form
else:
form = JobForm()
return render(request, 'submit.html', {'form': form})
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form.as_table }}
<input type="submit" value="Submit">
</form>
Does it make a difference if you define the form as a modelForm and explicitly state the model and fields?
Add/modify the following to your Forms.py:
class JobForm(forms.ModelForm):
class Meta:
model = Job
fields = ('job_name', 'email')
job_name = forms....
Related
This my Django code:
forms.py
from django import forms
class MyForm(forms.Form):
name = forms.CharField()
location = forms.CharField()
views.py
class MyFormView(FormView):
template_name = 'form.html'
form_class = MyForm
success_url = 'home'
def get(self, request, *args, **kwargs):
form = self.form_class
return render(request, 'form.html', {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
return render(request, self.template_name, {'form': form})
template form.html
<form method="post" action="{% url 'form' %}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-primary btn-block py-2" value="OK">
</form>
models.py
class MyModel(models.Model):
# ...
name = models.OneToOneField(Person, on_delete=models.CASCADE))
location = models.ForeignKey(Location, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
# ...
I want both two fields (name, location) to be drop-downs (combobox-es) not CharFields, and I want to populate their entries / values with data coming from db (django models). How can I do that? I am completely new to CBV idea.
You should use ModelChoiceField instead of CharField so:
from django import forms
from .models import YourModelName
class ReleaseForm(forms.Form):
name = forms.ModelChoiceField(queryset=YourModelName.objects.all())
location = forms.ModelChoiceField(queryset=YourModelName.objects.all())
Form class doesn't have a save() method unlike modelforms so you should manually save the form using cleaned_data in form_valid() method as:
from django.shortcuts import render, redirect
from django.urls import reverse_lazy
from django.views.generic import FormView
from .forms import MyForm
from .models import MyModel
class MyFormView(FormView):
template_name = 'form.html'
form_class = MyForm
success_url = reverse_lazy('home')
def form_valid(self, form):
name = form.cleaned_data['name']
location = form.cleaned_data['location']
MyModel.objects.create(name=name, location=location)
return super().form_valid(form)
The form I created is not inserting the data into my database table. As far as I can tell I've done everything correctly but it still refuses to do so instead it "post" in the console and clears the form fields without creating nothing in the database. None of the data that entered is saved anywhere? Here are the files below hopeful someone can see something I'm missing.
ps. I've connected my database, ran migrations and created a superuser as well but still nothing.
models.py
from django.db import models
Media_Choices = (
("TV", "TV"),
("Radio", "Radio"),
("Youtube", "Youtube"),
("Podcast", "Podcast"),
)
class Appear(models.Model):
Show = models.CharField(max_length=100)
Media = models.CharField(max_length=30, blank=True, null=True, choices=Media_Choices)
Episode = models.IntegerField()
Date = models.DateField(max_length=100)
Time = models.TimeField(auto_now=False, auto_now_add=False)
Producer = models.CharField(max_length=100)
Producer_Email = models.EmailField(max_length=254)
def __unicode__(self):
return self.Show + ' ' + self.Producer_Email
forms.py
from django import forms
from django.core.exceptions import ValidationError
from django.forms import ModelForm
from .models import Appear
class AppsForm(ModelForm):
class Meta:
model = Appear
fields = '__all__'
def clean_Producer_Email(self):
Producer_Email = self.cleaned_data.get('Producer_Email')
if (Producer_Email == ""):
raise forms.ValidationError('field cannot be left empty')
for instance in Appear.objects.all():
if instance.Producer_Email == Producer_Email:
raise forms.ValidationError('Please fill in correct email')
return Producer_Email
views.py
from django.shortcuts import redirect, render
from django.http import HttpResponse
from .forms import AppsForm
from .models import Appear
def AppS(request):
if request == 'POST':
form = AppsForm(request.POST)
if form.is_valid():
Apps = form.save(Commit=False)
Apps.save()
else:
form = AppsForm()
return render(request, 'AppsForm.html', {'form': form})
def results(request):
return render(request, 'Results.html')
AppsForm.html
<body>
{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
<form action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="submit">
</form>
{% endblock %}
enter code here
You might be missing form errors due to which the form is not saving. Try printing if there are any form errors.
if form.is_valid():
Apps = form.save(Commit=False)
Apps.save()
else:
print(form.errors)
What I want to do: I want to have a login form that when details are entered they are saved on the admin side.
My problem: the forms are not showing up on my local host page. See image below:
Here is the code from the login form app:
admin.py:
from django.contrib import admin
# Register your models here.
from .models import Contact
admin.site.register(Contact)
from apps.py:
from django.apps import AppConfig
class ContactConfig(AppConfig):
name = 'contact'
from forms.py
from .models import Contact
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ('username', 'password')
from models.py:
class Contact(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(
max_length=100,
)
def __str__(self):
return f'{self.username} {self.password}'
from views.py:
# Create your views here.
from .forms import ContactForm
def contact(request):
template = "home2.html"
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
form.save()
else:
form = ContactForm()
context = {
'form': form,
}
return render(request, template, context)
Then finally from the login page:
{% load static %}
<form method="post" class="form">
{% csrf_token %}
{{ form }}
<button type="submit" class="btn">Log In</button>
</form>
Another thing: forms are connected to the admin side but just do not appear on the login page
The error that Django throws at me when I fill in the form is: 'GetSessionName' object has no attribute 'name' and I have never worked with sessions before so I don't know how to solve this problem. The idea of the site is to have a small Login screen where you type your name then move to the chat.
views.py
from django.shortcuts import render, redirect
from django.utils import timezone
from .models import *
from .forms import Chat, GetSessionName
def chat(request):
Messages = Message.objects.all().order_by('-created')
form = Chat()
if request.method == "POST":
form = Chat(request.POST)
if form.is_valid():
form.save()
return redirect ("chat")
name = request.session['name']
context = {"Message": Messages, "form": form, 'name': name}
return render(request, 'chat/chat_messages.html', context)
def login(request):
form = GetSessionName()
if request.method == "POST":
form = GetSessionName(request.POST)
if form.is_valid():
request.session['name'] = form.name
return redirect('chat')
context={'form': form}
return render(request, 'chat/chat_login.html', context)
forms.py
from django import forms
from django.forms import ModelForm
from .models import Message
from .models import *
class Chat(forms.ModelForm):
class Meta:
model = Message
fields = "__all__"
class GetSessionName(forms.Form):
name = forms.CharField(max_length=30)
chat_login.html
{% extends 'chat/base.html' %}
{% block content %}
<form method="POST" action="">
{% csrf_token %}
{{form}}
</form>
{% endblock content %}
you clearly right used sessions but the problem is getting field name in dicts of forms.
You just should add 'cleaned_data'
def login(request):
form = GetSessionName()
if request.method == "POST":
form = GetSessionName(request.POST)
if form.is_valid():
request.session['name'] = form.cleaned_data['name']
return redirect('chat')
context={'form': form}
return render(request, 'chat/chat_login.html', context)
Best regards
as my first project in Django I am creating a todo app, that lets people log in and see their own tasks that they created. For that, I need to save author info in single task data.
From what I learned reading the documentation and doing lots of google-searching, the current approach is to use the get_user_model function from django.contrib.auth.
The problem is, that whenever I try to use it in my model, it seems to not get the username from the currently logged in user. While printing the form.errors to my console, the output is:
<ul class="errorlist"><li>added_by<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
Seems like the get_user_model is not returning any value. Can anyone recommend a better approach for me to do that? Or is there something obvious that I missed?
Here are the code snippets:
models.py
from django.db import models
from django.contrib.auth import get_user_model
class Task(models.Model):
title = models.CharField(max_length=35)
completed = models.BooleanField(default=False)
created_date = models.DateTimeField(auto_now_add=True)
added_by = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
def __str__(self):
return self.title
forms.py
from django import forms
from .models import *
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = '__all__'
widgets = {
'title': forms.TextInput(attrs={'class': 'new_task_text', 'placeholder': 'Add new task'}),
}
views.py
#login_required
def list_homepage(request):
tasks = Task.objects.all()
form = TaskForm()
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save()
print(form.cleaned_data)
else:
print(form.errors)
return redirect('/list/home')
context = {
'page_title': 'Todo list',
'tasks': tasks,
'form': form,
}
return render(request, 'tasks/list.html', context)
form in template:
<form method="POST", action="#"> {% csrf_token %}
{{ form.title }}
<input class="submit" type="submit", value="Create task">
</form>
Thank you in advance for any help!
Your form template only includes the title field, you either need to add the added_by field to this form, or add it in the view handling
{{ form.added_by }}
or
if request.method == 'POST':
form = TaskForm({**request.POST, **{"added_by": request.user}})