Django image:this field is required - django

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>

Related

How to pass request.user / user to message in Django

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.

Django saving data with form

I already saw many Stack overflow posts, but cannot find any problem on my code, but this code doesn't save any piece of data.
models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=50, blank=True)
content = models.CharField(max_length=200, blank=True)
post_date = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.title
forms.py
from django.forms import ModelForm
from .models import Post
class PostForm(ModelForm):
class Meta:
model = Post
fields = ['title', 'content', 'post_date']
views.py
from django.shortcuts import render
from django.template import loader
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.http import Http404
from .models import Post
from .forms import PostForm
# Create your views here.
def index(request):
latest_post_list = Post.objects.order_by('-post_date')[:5]
template = loader.get_template('form/index.html')
context = {'latest_post_list':latest_post_list}
return render(request, 'form/index.html', context)
def posts(request, post_id):
post = get_object_or_404(Post, pk=post_id)
return render(request, 'form/posts.html', {'post':post})
def posting(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
return HttpResponseRedirect('/')
else:
print(form.errors)
else:
form = PostForm()
return render(request, 'form/posting.html', {'form' : form})
posting.html
<form action="/form/" method="post">
{% csrf_token %}
{{ form }}
<input type='submit' value='Submit'>
</form>
<script src="" async defer></script>
I swear I saw many questions about it, but still I'm in trouble :/
I thought form.save in the views.py would make it work but no.
Try removing action in your 'posting.html' and instead of creating <input type='submit'>try the below code for submit button.
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Submit</button>
</form>

Diplay ModelForm in html

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']

Using Django, how do I set a default value for a foreign key select when creating a new item

I've come to the end of the DjangoGirls tutorial and have been trying to add some extra functionality of my own
I have a new model called Subject. Each blog post now has a subject such as cookery, gardening, astrophysics, general, etc. When a blogger writes a new post, I want to force the Subject dropdown to default to 'General', but my template (post_edit.html) doesn't give me access to the SELECT so I can't set a default value
post_edit.html:
{% extends 'blog/base.html' %}
{% block content %}
<div>
<h1>New post</h1>
<form method="POST" class="post-form">{% csrf_token %}
{% if form.non_field_errors %}
<ul>
{% for error in form.non_field_errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{% for field in form %}
<div id="{{ field.auto_id }}_container"> {{ field.help_text }}
<div>
<span class="staticdata">{{ field.label_tag }}</span>
<span class="staticdata">{{ field }}</span>
</div>
<div id="{{ field.auto_id }}_errors">
{{ field.errors }}
</div>
</div>
{% endfor %}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</div>
{% endblock %}
forms.py
from django import forms
from .models import Post, Subject
from django.contrib.auth.models import User
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'text', 'subject', 'author')
models.py
from django.db import models
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey('auth.User')
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
subject = models.ForeignKey('Subject')
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
class Subject(models.Model):
description = models.CharField(max_length=200)
def __str__(self):
return self.description
views.py
from django.shortcuts import render, get_object_or_404
from django.shortcuts import redirect
from django.contrib.auth.models import User
from django.contrib.auth import authenticate,logout,login
from django.utils import timezone
from .models import Post, Subject
from .forms import PostForm
def post_list(request):
posts = Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
#... post.author = request.user
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})
def subject_list(request):
subjects = Subject.objects.all().order_by('description')
return render(request, 'blog/subject_list.html', {'subjects': subjects})
How can I set a default value for this so that the dropdown is populated with a default option when the user navigates to the page?
Try setting an initial value, in the following way
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.published_date = timezone.now()
post.save()
return redirect('post_detail', pk=post.pk)
else:
# Get the default subject.
# Perhaps you want to give your subject a name, or use an id here,
# but assuming your default subject's description is 'General' for
# this example
default_subject = Subject.objects.get(description="General")
# Set the default value
form = PostForm(initial={"subject":default_subject})
return render(request, 'blog/post_edit.html', {'form': form})

javascript for Django inline formset factory

I just want to add fields dynamically like Django admin . ( + ) and ( - ) button must perform add and delete img_formset using javascript
The below code is taken from a tutorial I got from web and its working fine. But for now I just need to know how to extend this code do the above.
models.py
from django.db import models
class Pet(models.Model):
name = models.CharField(max_length=100)
breed = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class PetImage(models.Model):
image = models.ImageField(upload_to='pets')
pet = models.ForeignKey(Pet)
created = models.DateTimeField(auto_now_add=True)
#Delete Path
def delete(self, *args, **kwargs):
self.image.delete(False)
super(PetImage, self).delete(*args, **kwargs)
forms.py
from django.forms.models import inlineformset_factory
from django import forms
from .models import Pet, PetImage
class PetForm(forms.ModelForm):
class Meta:
model = Pet
PetImageFormset = inlineformset_factory(Pet, PetImage,
fields=('image',), can_delete=True)
urls.py
from django.conf.urls import *
urlpatterns = patterns('pets.views',
url(r'^add/$', 'add_pet', name='add_pet'),
url(r'^update/(\d+)/$', 'update_pet', name='update_pet'),
)
views.py
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from .forms import PetForm, PetImageFormset
from .models import Pet, PetImage
def add_pet(request):
form = PetForm()
img_formset = PetImageFormset(instance=Pet())
if request.method == 'POST':
form = PetForm(request.POST)
if form.is_valid():
pet = form.save()
img_formset = PetImageFormset(request.POST,
request.FILES, instance=pet)
if img_formset.is_valid():
img_formset.save()
return HttpResponseRedirect(reverse('pets:home'))
return render(request, "form.html", {
'form': form,
'img_formset': img_formset,
'action': "Create"
})
def update_pet(request, pet_id):
pet = get_object_or_404(Pet, pk=pet_id)
form = PetForm(instance=pet)
img_formset = PetImageFormset(instance=pet)
if request.method == 'POST':
form = PetForm(request.POST, instance=pet)
if form.is_valid():
pet = form.save(commit=False)
img_formset = PetImageFormset(request.POST,
request.FILES, instance=pet)
if img_formset.is_valid():
pet.save()
img_formset.save()
return HttpResponseRedirect(reverse('pets:home'))
return render(request, "form.html", {
'form': form,
'img_formset': img_formset,
'action': "Update"
})
form.html
{% extend "base.html" %}
{% block title %}Pet{% endblock title %}
{% block content %}
<h4>{{ action }}</h4>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
{{ img_formset.as_p }}
</form>
{% endblock content %}