This question already has an answer here:
Django forms: "This field is required" when file POSTed to file field
(1 answer)
Closed 11 months ago.
i don't have any problem in submiting char fields but when i put an image field i get this message -> "This field is required" while im filling the form .
models.py :
class Home(models.Model):
image = models.ImageField(upload_to='image')
titr = models.CharField(max_length=200)
description = models.TextField()
created = models.DateField(auto_now_add = True)
updated = models.DateField(auto_now = True)
class Meta:
ordering = ['created']
def __str__(self):
return str(self.titr)
views.py :
def craethome(request):
form = HomeForm()
if request.method == "POST":
form = HomeForm(request.POST,request.FILES)
if form.is_valid():
form.save()
return redirect("home")
return render(request, 'home/home_form.html', {"form":form})
forms.py :
from django.forms import ModelForm
from .models import Home
class HomeForm(ModelForm):
class Meta():
model = Home
fields = "__all__"
my html file:
{% extends 'main.html' %}
{% block content %}
<img src="{{home.image.url}}">
<h1>{{home.titr}}</h1>
<p>{{home.description}}</p>
{% endblock content %}
The form should contain enctype="multipart/form-data" [mdn] to encode the file data such that it can be uploaded to the view:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
</form>
You need to add enctype="multipart/form-data" into your form tag in html.
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
</form>
If you want to submit without an image you can add null, blank, or you can add a default image.
class Home(models.Model):
image = models.ImageField(upload_to='image', default='pic.png')
image2 = models.ImageField(upload_to='image', blank=True, null=True)
Related
I want to display only upload field on my project but need to save in my models(db): email address, file and date_time(this data was read from openpgp key)
It's works like: User uploads file(openpgp public key) on website and my script reads email and date_time from file.
I'm a newbie in django
Source code:
models.py:
class Users_Keys(models.Model):
email = models.EmailField(max_length=255)
file_key = models.FileField(max_length=255)
date_time = models.DateField()
forms.py:
from django import forms
from .models import Users_Keys
class KeyForm(forms.ModelForm):
class Meta:
model = Users_Keys
fields = ('email', 'file_key', 'date_time')
view.py:
def upload_key(request):
if request.method == 'POST':
form = KeyForm(request.POST, request.FILES, request.POST)
if form.is_valid():
form.save()
return render(request, 'index.html')
else:
form = KeyForm()
return render(request, 'upload.html',{
'form':form
})
upload.html:
{% extends 'background.html' %}
{% block content %}
<h2>Add KEY</h2>
<form method="POST" enctype="multipart/form-data">
<button class="btn btn-outline-success" type="submit">Upload</button>
{% csrf_token %}
{{ form }}
</form>
{% endblock %}
Read data from openPGP key:
def gpg_data():
gpg = gnupg.GPG(gnupghome="/home/user/.gnupg")
path = '/home/user/path_to_public.asc'
import_result = gpg.scan_keys(path)
key_info = dict(import_result[0])
time_expire = datetime.datetime.fromtimestamp(int(key_info['expires']))
email_address = str(key_info['uids']).split()[2].strip("<").replace(">","").replace("'","").replace(']',"")
I've got a project where users can enter topics and have the option to make the topic public or private. I want all public topics to be visible to everyone, and private topics to only be visible by the owner of that topic (Project is from Python Crash Course exercise 20-5).
I'm not getting any errors when I click through my project, but when I create a new topic and select the "public" option, it is still not showing up for public viewing.
I've researched similar problems and followed all the suggestions here
How to make a topic public to all users in django? and here Django - How to make the topics, that you create public? Learning Log Project with no luck.
I'm guessing my queryset is not rendering data correctly? I've read the Django documentation on querysets as well, but nothing I've tried has worked. I'm really new to programming so any help would be appreciated. Thank you!
Here's my models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Topic(models.Model):
"""A topic the user is learning about"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
public = models.BooleanField(default=False)
def __str__(self):
"""Return a string representation of the model"""
return self.text
class Entry(models.Model):
"""Something specific learned about a topic"""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
"""Retrun a string representation of the model"""
if len(self.text) < 50:
return f"{self.text}"
else:
return f"{self.text[:50]}..."
views.py:
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.http import Http404
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
# Create your views here.
def index(request):
"""The home page for Learning Log"""
return render(request, 'learning_logs/index.html')
#Checks whether logged in user has access to topic
def check_topic_owner(request, topic):
if topic.owner != request.user:
raise Http404
def topics(request):
"""Shows all topics"""
#Gets public topics
public_topics = Topic.objects.filter(public=True).order_by('date_added')
#Gets private topics
if request.user.is_authenticated:
private_topics = Topic.objects.filter(owner=request.user).order_by('date_added')
topics = public_topics | private_topics
else:
topics = public_topics
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
def topic(request, topic_id):
"""Show a single topic and all its entries"""
topic = get_object_or_404(Topic, id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
#login_required
def new_topic(request):
"""Add a new topic"""
if request.method != 'POST':
#No data submitted; create a blank form.
form = TopicForm()
else:
#POST data submitted; process data
form = TopicForm(data=request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
return redirect('learning_logs:topics')
#Display a blank or invalid form
context = {'form': form}
return render(request, 'learning_logs/new_topic.html', context)
#login_required
def new_entry(request, topic_id):
"""Add a new entry for a particular topic"""
topic = get_object_or_404(Topic, id=topic_id)
check_topic_owner(request, topic)
if request.method != 'POST':
#No data submitted, create a blank form
form = EntryForm()
else:
#POST data submitted; process data
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
if new_entry.topic.owner == request.user:
new_entry.save()
else:
return Http404
return redirect('learning_logs:topic', topic_id=topic_id)
#Display a blank or invalid form
context = {'topic': topic, 'form': form}
return render(request, 'learning_logs/new_entry.html', context)
#login_required
def edit_entry(request, entry_id):
"""Edit an existing entry"""
entry = get_object_or_404(Entry, id=entry_id)
topic = entry.topic
check_topic_owner(request, topic)
if request.method != 'POST':
#Initial request; prefill with the current entry
form = EntryForm(instance=entry)
else:
#POST data submitted; process data
form = EntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return redirect('learning_logs:topic', topic_id=topic.id)
context = {'entry': entry, 'topic': topic, 'form': form}
return render(request, 'learning_logs/edit_entry.html', context)
new_topic.html:
{% load bootstrap4 %}
{% block page_header %}
<h3>Add a new topic:</h3>
{% endblock page_header %}
{% block content %}
<form method="post" action="{% url 'learning_logs:new_topic' %}" class="form">
{% csrf_token %}
{% bootstrap_form form %}
<div class="form-check">
<input class="form-check-input" type="checkbox" value=True id="public" />
<label class="form-check-label" for="public">
<p>Make post public?<p/>
</label>
</div>
{% buttons %}
<button name="submit" class="btn btn-primary">Add topic</button>
{% endbuttons %}
</form>
{% endblock content %}
And forms.py:
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
And topics.html:
{% block page_header %}
<h1>Topics</h1>
{% endblock page_header %}
{% block content %}
<ul>
{% for topic in topics %}
<li><h4>
{{ topic }}
</h4></li>
{% empty %}
<li><h4>No topics have been added yet.</h4></li>
{% endfor %}
</ul>
<h4>Add a new topic</h4>
{% endblock content %}
Edit:
I've gotten the project to work as expected now with the help from hasnain095. Here is my updated new_topic.html. I still don't understand how the checkbox is being generated since I've deleted the html which I thought was specifically generating it, but since it's still working, I'm content.
{% extends "learning_logs/base.html" %}
{% load bootstrap4 %}
{% block page_header %}
<h3>Add a new topic:</h3>
{% endblock page_header %}
{% block content %}
<form method="post" action="{% url 'learning_logs:new_topic' %}" class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary">Add topic</button>
{% endbuttons %}
</form>
{% endblock content %}
I think the issue is that you've only specified the field 'text in your Topic Form:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
but in new_topic.html file, you have only one checkbox input, no place to enter the text
<div class="form-check">
<input class="form-check-input" type="checkbox" value=True id="public" />
<label class="form-check-label" for="public">
<p>Make post public?<p/>
</label>
</div>
{% buttons %}
<button name="submit" class="btn btn-primary">Add topic</button>
{% endbuttons %}
Your checkbox for "Make post public?" is getting mapped to the field "text" of your Topic.
To fix do:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text', 'public']
labels = {'text': ''}
and
<div class="form-check">
<input class="form-check-input" type="checkbox" value=True id="public" />
<label class="form-check-label" for="public">
<p>Make post public?<p/>
</label>
<input class="form-input" type="input" value=True id="text1" />
<label class="form-label" for="text1">
<p>Text<p/>
</label>
</div>
Use unions to add to a queryset:
def topics(request):
"""Shows all topics"""
# Gets public topics (renamed to topic_set to not shadow function name)
topic_set = Topic.objects.filter(public=True).order_by('date_added')
# Add private topics, if any. We save some work by not including the public
# topics.
if request.user.is_authenticated:
topic_set = topic_set.union(
Topic.objects.filter(public=False, owner=request.user)
)
context = {'topics': topic_set}
return render(request, 'learning_logs/topics.html', context)
Side note: add indexes to fields you filter on:
class Topic(models.Model):
"""A topic the user is learning about"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
public = models.BooleanField(default=False, db_index=True)
def __str__(self):
"""Return a string representation of the model"""
return self.text
It's working for me after use union to append private topics to public topic, but there maybe some different. list below, hope will help:
views.py
def check_topic_owner(topic, request):
if not topic.public:
if topic.owner != request.user:
raise Http404
def topics(request):
#Gets public topics
public_topics = Topic.objects.filter(public=True)
#Gets private topics and append the public topic
if request.user.is_authenticated:
private_topics = Topic.objects.filter(owner=request.user)
topics = public_topics.union(private_topics).order_by('date_added')
else:
topics = public_topics
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
models.py
class Topic(models.Model):
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
public = models.BooleanField(default=False)
def __str__(self):
return self.text
I am trying to update a userprofile model that i used to save additional information over the inbuilt User model, now when i am trying to update it , the image does not gets saved. I need help to resolve this issue
# In views.py
#login_required(login_url=LOGIN_REDIRECT_URL)
def update_user_profile(request):
userobj = get_object_or_404(UserProfile, user=request.user)
form = UserProfileForm(data = request.POST or None,files= request.FILES or None, instance=userobj)
if request.method=='POST':
print(form.is_valid())
if form.is_valid():
profile = form.save(commit=False)
profile.picture = form.cleaned_data['picture']
profile.about = form.cleaned_data['about']
profile.save()
else:
print("NO picure")
return HttpResponseRedirect("/blog/profile/")
return render(request, "blog/post_update.html", {'form':form})
#models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
about = models.CharField(max_length=200, null=True, blank=True)
picture = models.ImageField(upload_to="profile_images/", blank=True)
def __str__(self):
return str(self.user)
#In forms.py
class UserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
self.fields['about'].widget.attrs.update({'class': 'form-control '})
self.fields['picture'].widget.attrs.update({'class': 'form-control-file'})
class Meta:
model = UserProfile
fields = ('about', 'picture')
# userprofileform.html
{% extends 'base.html' %}
{% block content %}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn btn-primary" value="Create Profile">
</form>
{% endblock %}
please take a look at the code and help. while registering if the image was uploaded it get's saved , but when i try to update the userprofile directly in profile section image does not get changed and shows the same as one saved while user registration else it shows None.
I did some changes on templates in settings.py and got my project runnning. Issue was that i was not mentioning the Templates directory properly
I'm trying to create a form in Django template but it is just not showing the fields
here is my files
models.py where i created the desired table
class ReportMessage(models.Model):
sender = models.ForeignKey(UserModel, related_name="report_message_sender", on_delete='CASCADE')
message = models.ForeignKey(Message, on_delete='CASCADE')
created_at = models.DateTimeField(auto_now=True)
reason = models.TextField(max_length=1500)
is_read = models.BooleanField(default=False)
forms.py where i created the form to edit only one field in the table
class ReportMessageForm(forms.Form):
class Meta:
model = ReportMessage
fields = ['reason', ]
views.py where i created the view for the form
#login_required
def report_message(request, pk):
current_user = request.user
reported_message = get_object_or_404(Message, pk=pk)
if request.method == "POST":
report_message_form = ReportMessageForm(request.POST)
if report_message_form.is_valid():
model_instance = report_message_form.save(commit=False)
model_instance.sender = current_user
model_instance.message = reported_message
model_instance.save()
return redirect('report_confirm')
else:
report_message_form = ReportMessageForm()
context = {
'report_message_form': report_message_form,
}
return render(request, 'fostania_web_app/report_message.html', context)
def report_confirm(request):
return render(request, 'fostania_web_app/report_confirm.html')
and urls.py where the urls i used for the views
path('report/messages/<int:pk>/', views.report_message, name="report_message"),
path('report/confirm', views.report_confirm, name="report_confirm"),
and finally that is how i used the form in the html template
{% extends 'fostania_web_app/base.html' %}
{% block content %}
{% load static %}
<form action="" method="post" name="ReportMessageForm" align="right">
{% csrf_token %}
{{ report_message_form }}
<input type="submit" class="btn btn-success" style="width: 100px;" value="إرسال" />
</form>
{% endblock %}
and then all what i see in the html page is the submit button and there is no form labels or input or anything.
In your forms.py if you are not using ModelForm then you have to explicitly declare the fields for the forms
reason = forms.Charfield()
Or you can use ModelForm which inherits from the model you specify.
You should specify the model in the Meta class while using ModelForm.You can also specify required fields from the Model in the fields list in Meta class
Class myform(forms.ModelForm)
Class Meta:
model = your_model_name
fields= [reason,]
Cheers
:)
I think that your problem is in your model form because you are using forms.Form and you need to use forms.ModelForm
class ReportMessageForm(forms.ModelForm):
class Meta:
model = ReportMessage
fields = ['reason', ]
def report_confirm(request):
return render(request, 'fostania_web_app/report_confirm.html', context) #add the context
You need to pass in the "context" so that it shows in the template
I am having some issues with a (model)form consisting of just a single button. When I try to submit the form this message is displayed:
user
This field is required.
The ModelForm looks like this:
from django.forms import ModelForm
from .models import HulpOproep
class HulpOproepForm(ModelForm):
class Meta:
model = HulpOproep
fields = ['user', ]
The Model looks like this:
class HulpOproep(models.Model):
user = models.ForeignKey(User)
time = models.DateTimeField(auto_now_add=True, verbose_name='Tijd')
def __str__(self):
return '%s %s' % (self.user.username, str(self.time))
def username(self):
return self.user.username
def first_name(self):
return self.user.first_name
def last_name(self):
return self.user.last_name
class Meta:
verbose_name = 'Hulp Oproep'
verbose_name_plural = 'Hulp Oproepen'
The View looks like this:
def verzend_oproep(request):
if request.method == 'POST':
form = HulpOproepForm(request.POST)
if form.is_valid():
oproep = form.save(commit=False)
oproep.user = request.user
oproep.save()
return redirect('portal/index/')
else:
form = HulpOproepForm()
return render(request, 'portal/verzend_oproep.html', {'form': form})
The Template:
{% extends "base.html" %}
{% block head %}
<title>Zorggroep | Hulp Oproep</title>
{% endblock %}
{% block body%}
<h1>Verstuur Hulpoproep</h1>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_P }}
{{ form.errors }}
<button type="submit" class="save btn btn-default">Verstuur</button>
</form>
{% endblock %}
The 'user' in the HulpOproep model is a ForeignKey and should be the currently logged in user's User object. I tried to specify this using the line:
oproep.user = request.user
So what should happen is:
Get the current user's 'User' object and use it as the 'HulpOproepForm.user'. This way the 'HulpOproepForm.user' is the 'HulpOproep.user' and a Foreign Key.
I have followed multiple tutorials and have searched around, but I cannot find a solution. I'm sorry if the answer is logical, but I have been using Django for only 5 days and have 1.5 months of programming experience under my belt.
Thank you!
Thanks PatNowak and Radek!
I did not know the form was waiting for user input instead of code input. I managed to fix it by adding exclude to the ModelForm.
class HulpOproepForm(ModelForm):
class Meta:
model = HulpOproep
exclude = ['user', 'time']