I am creating a webapp in which a user can create a project, inside each project he can answer a set of question(in my app, I call them secondquestions).
I am trying to use ModelForm to ease the creation of the form by following this guide: https://docs.djangoproject.com/en/2.2/topics/forms/modelforms/
Howver I do not understand how I can display in my html my form.
secondquestions/views.py
def secondquestionstoanswer(request, project_id):
project = get_object_or_404(Project, pk=project_id)
if request.method == "POST":
form = SecondquestionForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'secondquestions/secondquestionstoanswer.html', {'project':project})
secondquestions/models.py
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from projects.models import Project
from django.db import models
from django.forms import ModelForm
class Secondquestion(models.Model):
second_one = models.TextField()
second_two = models.TextField()
second_three = models.TextField()
second_four = models.TextField()
second_five = models.TextField()
second_six = models.TextField()
second_seven = models.TextField()
second_eighth = models.TextField()
second_nine = models.TextField()
developer = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
project = models.OneToOneField(Project, on_delete=models.CASCADE)
class SecondquestionForm(ModelForm):
class Meta:
model = Secondquestion
fields = ['second_one', 'second_two', 'second_three', 'second_four', 'second_five', 'second_six', 'second_seven', 'second_eighth', 'second_nine']
secondquestions/secondquestionstoanswer.html
{% extends 'base.html' %}
{% block title %}First set{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
{% endblock %}
My problem:
In my html I just see the Submit button, not the form.
You never constructed a form that you passed to the template engine.
from django.shortcuts import redirect
def secondquestionstoanswer(request, project_id):
project = get_object_or_404(Project, pk=project_id)
if request.method == "POST":
form = SecondquestionForm(request.POST)
if form.is_valid():
form.instance.project = project
form.save()
return redirect('some_view')
else:
form = SecondquestionForm()
return render(
request,
'secondquestions/secondquestionstoanswer.html',
{'project':project, 'form': form}
)
With 'some_view', the name of the view to where you want to redirect in case the submission is successful.
In your <form> you specify in the action="..." attribute where what endpoint should be triggered, like:
<form method="post" action="{% url 'view_name_of_second_question' project.pk %}">
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>
You need a forms.py file that will contain your Model Form
secondquestions/forms.py
from django import forms
from .models import Secondquestion
class SecondquestionForm(forms.ModelForm):
class Meta:
model = Secondquestion
fields = ['second_one', 'second_two', 'second_three', 'second_four', 'second_five', 'second_six', 'second_seven', 'second_eighth', 'second_nine']
Related
models.py
from django.db import models
# Create your models here.
class Subscriber(models.Model):
"""A subscriber Model"""
email = models.CharField(max_length=255, blank=False, null=False, help_text="Subscriber Email Address", unique=True)
full_name = models.CharField(max_length=100, blank=False, null=False, help_text="First and Last Name")
class Meta:
verbose_name = "Subscriber"
verbose_name_plural = "Subscribers"
forms.py
from django.forms import ModelForm
from .models import Subscriber
class SubscriberForm(ModelForm):
class Meta:
model = Subscriber
fields = ["email", "full_name"]
views.py
from django.shortcuts import render
from .forms import SubscriberForm
from django.http import HttpResponseRedirect
from django.contrib import messages
# Create your views here.
def subscriber(request):
if request.method == "POST":
subscriber_form = SubscriberForm(request.POST or None)
if subscriber_form.is_valid():
subscriber_form.save()
messages.success(request, "")
return HttpResponseRedirect("/")
else:
subscriber_form = SubscriberForm()
context = {
"form_subscriber": subscriber_form
}
return render(request, "subscriber/subscriber_form.html", context)
subscriber_form.html
{% block content %}
<div>
<form method="POST">
{% csrf_token %}
{{ subscriber_form.as_ul }}
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
Only my submit button is publishing, however the form is never showing up for me.
I have followed the django docs exactly and still am not getting any good results.
It should be form_subscriber not subscriber_form so:
{% block content %}
<div>
<form method="POST">
{% csrf_token %}
{{ form_subscriber.as_ul }}
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
Additionally, I'd recommend you to only use SubscriberForm(request.POST) in views without using None for GET request as it is already being handled in else condition so:
views.py:
def subscriber(request):
if request.method == "POST":
subscriber_form = SubscriberForm(request.POST)
...
I am attempting to submit a form to populate the database. I can't get the POST working. It doesn't look valid, but I can't figure out what I need to do to correct it.
I have put some debugging on to see what happens when I click submit & the POST gets sent. I can't figure out how to send created_at or created_by. I assume these are the reason why the POST is not valid and the database is not populating.
models.py
from django.db import models
from django.contrib.auth.models import User
from django.forms import ModelForm
class Order(models.Model):
order_name = models.CharField(max_length=100, unique=True, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, related_name='Project_created_by', on_delete=models.DO_NOTHING)
def __str__(self):
return self.order_name
class Ce_Base(models.Model):
ce_hostname = models.CharField(max_length=15)
new = models.BooleanField()
location = models.TextField()
order_reference = models.ManyToManyField(Order)
forms.py
from django.forms import ModelForm
from .models import Order
class OrderForm(ModelForm):
class Meta:
model = Order
fields = ['order_name']
views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from .models import Order
from .models import Ce_Base
from .forms import OrderForm
#login_required
def home(request):
form = OrderForm()
if request.method == 'POST':
form = OrderForm()
form.instance.created_by = request.user
print(request.POST)
if form.is_valid():
form.save()
context = {
'order': Order.objects.all(),
'form': form,
}
return render(request, 'orchestration/order_create.html', context)
#login_required
def orderprocessing(request):
context = {
'ce_base': Ce_Base.objects.all()
}
return render(request, 'orchestration/order_processing.html', context)
html
{% extends "orchestration/base.html" %}
{% block content %}
<h1>Input Form</h1>
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" >
</form>
<h1>Orders</h1>
{% for each_order in order %}
<p>Order Name: {{ each_order.order_name }}</p>
<p>Created On: {{ each_order.created_at }}</p>
<p>Created By: {{ each_order.created_by }}</p>
{% endfor %}
{% endblock content %}
Here is my terminal output when i hit the submit button
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
May 12, 2022 - 16:15:40
Django version 4.0.2, using settings 'dcn_automation.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
<QueryDict: {'csrfmiddlewaretoken': ['MQVrDwqyT8Y6ARAF9CCyuCSwavz5BAVmi2GdxMgvxFlHmiD1M8Cq6y0VRVummR82'], 'order_name': ['test']}>
If don't pass the data in the form, the validation fails.
form = OrderForm(request.POST)
So I want to let a user message another user. I want the 'sender' field automatically to be 'request.user' and the receiver field to be the user whom the sender clicked on through their profile page. How would I go about passing those into the form?
matches.html
<div class="container">
<p>Username: {{ profile }}</p>
<h5>Your Matches:</h5>
{% for item in match %}
<br>
<p>Username: <br>{{ item.username}}</p>
<img src="{{ item.photo.url }}" width="300">
<p>Bio: <br>{{ item.description }}</p>
<br>
{% endfor %}
</div>
forms.py/InstantMessageForm
class InstantMessageForm(forms.ModelForm):
class Meta:
model = InstantMessage
fields = ('receiver','sender','message')
def save(self, commit=True):
user = super(InstantMessageForm, self).save(commit=False)
user.receiver = cleaned_data['receiver']
user.sender = cleaned_data['sender']
user.message = cleaned_data['message']
if commit:
user.save()
return user
views.py/instant_message
def instant_message(request):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
models.py
class InstantMessage(models.Model):
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'sender',on_delete=models.CASCADE )
message = models.TextField()
class InstantMessage(models.Model):
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'sender',on_delete=models.CASCADE )
message = models.TextField()
instant_message_form.py
{% extends "dating_app/base.html" %}
{% load bootstrap4 %}
{% block content %}
<h1>Start chatting now!</h1>
<div class='container'>
<form method="post" action="{% url 'dating_app:instant_message' %}" >
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
</div>
{% endblock content %}
You can create a form without the sender field:
class InstantMessageForm(forms.ModelForm):
class Meta:
model = InstantMessage
fields = ('receiver', 'message')
Then in the view, you can inject the request.user as the .sender of .instance wrapped in the form:
from django.contrib.auth.decorators import login_required
#login_required
def instant_message(request):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.instance.sender = request.user
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
In order to set the receiver, your url should for example contain the a primary key of the receiver. You can then remove the receiver from the form as well, and thus use:
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
#login_required
def instant_message(request, receiver_id):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.instance.sender = request.user
form.instance.receiver = get_object_or_404(get_user_mode(), pk=receiver_id)
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
You of course need then to alter the urls.py accordingly and the action url, such that it includes the primary key of the receiver.
I am trying to send a form with an image, I select the image but I always get: "this field is required" when I send the form.
here is my code:
models.py:
from django.db import models
from django.contrib.auth.models import User
class Picture(models.Model):
created_at = models.DateField(auto_now_add=True)
update_at = models.DateField(auto_now=True)
image = models.ImageField()
caption = models.CharField(max_length=50)
author = models.ForeignKey('auth.user', on_delete=models.CASCADE, related_name='pictures')
forms.py:
from django import forms
class PictureForm(forms.Form):
image = forms.ImageField()
caption = forms.CharField(max_length=50)
views.py:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .models import Picture
from .forms import PictureForm
from django.contrib.auth.models import User
def pictures_view(request):
pictures = Picture.objects.all()
context = {'pictures': pictures}
return render(request, 'pictures/pictures.html', context)
def picture_form_view(request):
if request.method == 'POST':
form = PictureForm(request.POST, request.FILES)
if form.is_valid():
clean_data = form.cleaned_data()
Picture.objects.create(clean_data)
return HttpResponseRedirect('/')
else:
form = PictureForm()
return render(request, 'pictures/picture_form.html', {'form': form})
HTML:
{% extends 'pictures/base.html' %}
{% block title %}publish{% endblock %}
{% block content %}
<form class="form" action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
{% endblock %}
And a Little question, how can I complete the field author automaticly with the actual user?
first of all ImageField in model takes one compulsory argument upload_to so in your models
class Picture(models.Model):
###
image = models.ImageField(upload_to='upload/to/path')
###
now in your view
def picture_form_view(request):
if request.method == 'POST':
form = PictureForm(request.POST, request.FILES)
if form.is_valid():
clean_data = form.cleaned_data()
Picture.objects.create(**clean_data)
return HttpResponseRedirect('/')
else:
form = PictureForm()
return render(request, 'pictures/picture_form.html', {'form': form})
and to save current logged in user as default override form_valid()
method in Form class like
def form_valid(self, form):
form.instance.created_by = self.request.user
return super().form_valid(form)
Try to set enctype to "multipart/form-data" in the form tag.
<form action="#" method="post" enctype="multipart/form-data">
input here ...
</form>
I am new to django. am using django==1.11
am trying to create a form which inputs details of users.
my
views.py
from django.shortcuts import render, render_to_response, redirect
from django.template import loader, Template, Context, RequestContext
from forms import UserForm
from django.http import HttpResponse, HttpResponseRedirect
from django.views.decorators import csrf
def action(request):
if request.POST:
form = UserForm(data = request.POST)
if form.is_valid():
form.save(commit = False)
return HTTPResponseRedirect('/rfid/index')
else:
form = UserForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('reg.html', args)
forms.py
from django import forms
from models import UserDetails
class UserForm(forms.ModelForm):
class Meta:
model = UserDetails
fields = '__all__'
reg.html
{% extends "rfid/header.html" %}
{% block content %}
<div class="container">
<form action = "/" method="post">{% csrf_token %}
<ul>
{{ form.as_ul }}
</ul>
<input type="submit" name="submit" class="btn btn-default" value="Add User">
</form>
</div>
{% include "rfid/includes/htmlsnippet.html" %}
{% endblock %}
models.py
from django.db import models
# Create your models here.
class UserDetails(models.Model):
GENDER_CHOICES = (('M', 'Male'), ('F', 'Female'))
user_id = models.IntegerField(primary_key = True)
name = models.TextField(max_length = 50)
gender = models.CharField(max_length = 1, choices = GENDER_CHOICES)
dob = models.DateTimeField()
address = models.TextField(max_length = 200)
phone = models.IntegerField()
email = models.EmailField(max_length=254)
photo_url = models.CharField(max_length = 200)
def __str__(self):
return self.name
But it is only showing the submit button. Model-based fields are not displaying. I had gone through some Questions here but was not able to trace out what was the problem. can anyone help me out.
Hope all required details are given. pls, ask if I miss anything.
regards.
Check out the line with form.save(commit=False).
Except you want to give that line a name and later save the name like saved_form=form.save(commit=False) then saved_form.safe, then the commit=False line isn't necessary. I don't know if that is the problem, but will check and revert