Having trouble in creating forms in django - django

This is my models.py file
from django.db import models
# Create your models here.
class Blog(models.Model):
name = models.CharField(max_length=120)
created_on = models.DateTimeField(auto_now_add=True)
class Article(models.Model):
blog = models.ForeignKey(Blog,
on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=120)
body = models.TextField()
draft = models.BooleanField(default=False)
This is my forms.py file
from blog.models import Article
from django import forms
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'body', 'draft']
Here is the views.py file
from django.shortcuts import render
from django.http import HttpResponse
from blog.forms import ArticleForm
# Create your views here.
def add_article(request):
if request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
form.save()
return HttpResponse("Article created")
else:
context = {'form': ArticleForm()}
return render(request, 'add_article.html', context)
context = {'form': ArticleForm()}
return render(request, 'add_article.html', context)
Can someone tell me how do I insert the first attribute of class Article which is blog in class Articleform?
I am learning django and some help will be appreciated.

You can check these steps:
be sure you added {{form}} in your add_article.html.
be sure you added method="POST" in your <form> tag.
e.g.:
<form method="POST">
{{form}}
<input type="submit">Post</input>
</form>

Related

saving forms via TemplateView

I am trying to save forms via Post by TemplateView, but when def Post calls, forms are not saved.
using inline formset . Book Title is saved by Author,1 author can have multiple books .
Codes below are what I am using:
This is the view , Posting content of Inlineformset , if it is get , shows the form , if it is post it must save the data .
#view.py
from django.shortcuts import render
# Create your views here.
from django.views.generic import TemplateView,UpdateView
from django.forms import inlineformset_factory
from .models import Author,Book
from django.shortcuts import redirect
class BookView(TemplateView):
template_name ="index.html"
def get(self, request, *args, **kwargs):
return self.render_preview(request)
def post(self,request,*args,**kwargs):
return self.save_book(request)
def save_book(self,request,**kwargs):
BookFormSet = inlineformset_factory(Author, Book, fields=('title',),can_delete=False)
author = Author.objects.get(name='John')
formset = BookFormSet(instance=author)
if formset.is_valid():
formset.save()
return redirect('/')
context = super(BookView, self).get_context_data(**kwargs)
context['formset'] = formset
return self.render_to_response(context)
def render_preview(self, request, **kwargs):
BookFormSet = inlineformset_factory(Author, Book, fields=('title',),can_delete=False)
author = Author.objects.get(name='John')
formset = BookFormSet(instance=author)
context = super(BookView, self).get_context_data(**kwargs)
context['formset'] = formset
return self.render_to_response(context)
#Models
This is the models.py
# Create your models here.
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
def __str__(self):
return self.title
index.html
<form action="" method="post" >
<div class="html">
{% csrf_token %}
{% for form in formset %}
{{form }}
{%endfor %}
<button type="submit">save</button>
</form>
</div>
I was having this same issue not so long ago and I solved it a bit different than by using a FormSet (which I am not so familiar with), hope it helps you out:
Models.py
from django.db import models
class Author(models.Model)
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Book(models.Model)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
def __str__(self):
return self.title
Forms.py
from django import forms
from Appname.models import Author, Book
class Author(forms.ModelForm):
class Meta:
model = Author
fields = ['name']
class Book(forms.ModelForm):
class Meta:
model = Book
fields = ['author', 'title']
Views.py
class BookView(TemplateView):
template_name ="index.html"
author_form_class = Author
def get_context_data(self, **kwargs):
context = super(BookView, self).get_context_data(**kwargs)
context['author_form'] = self.author_form_class
context['book_form'] = self.book_form_class
return context
def post(self, request):
author_form_class = Author(request.POST or None)
book_form_class = Book(request.POST or None)
if author_form_class.is_valid():
author_form_class.save()
return redirect('/')
if book_form_class.is_valid():
book_form_class.save()
return redirect('/')
index.html
<form method="post">
{{ csrf_token }}
{{ author_form}}
<input type="submit" value="submit">
</form>

Django Image field doesn't update image

I recently got a problem that my django image field in my django app doesn't update the image after pressing "Post". In admin panel everything works fine. Maybe I missed something... Let me know.
models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
categories = models.ManyToManyField('Category', related_name='posts')
image = models.ImageField(upload_to='images', default="images/None/no-img.jpg")
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Category(models.Model):
name = models.CharField(max_length=20
)
views.py
from django.shortcuts import render, get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from .models import Post
from django.contrib.auth.models import User
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
def home(request):
content = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', content)
def blog_category(request, category):
posts = Post.objects.filter(categories__name__contains=category).order_by('-date_posted')
content = {
'category': category,
'posts': posts
}
return render(request, 'blog/blog_category.html', content) #<--(didn't add content block) bug found 05.11.19
def upload_pic(request):
if request.method == 'POST':
form = ImageUploadForm(request.POST, request.FILES)
if form.is_valid():
m = ExampleModel.objects.get(pk=course_id)
m.model_pic = form.cleaned_data['image']
m.save()
return HttpResponse('image upload success')
return HttpResponseForbidden('allowed only via POST')
...
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content', 'categories', 'image']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['title', 'content', 'categories', 'image']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
I just have recently added Category and Image section in my web-application, the Category section works fine, but the image field just post default even if I'm selecting the current image. In the admin field it works well, so I decided to ask community about this annoying problem.
Make sure the form in your template has enctype set correctly:
Note that request.FILES will only contain data if the request method was POST and the that posted the request has the attribute enctype="multipart/form-data". Otherwise, request.FILES will be empty.

How to use ModelMultipleChoiceField

I am trying to create a website that allows users to follow certain stocks and read articles based on what they follow. I am having trouble creating a form for them to follow stocks as a user's Profile and Stocks have a many to many relationship, I believe I am supposed to use ModelMultipleChoiceField but cannot get it to work.
models.py
from django.db import models
from django.contrib.auth.models import User
from django.dispatch import receiver
from django.db.models.signals import post_save
class Stock(models.Model):
name = models.CharField(max_length = 50)
ticker = models.CharField(max_length = 50)
def __str__(self):
return self.name
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
followed_stocks = models.ManyToManyField(Stock, blank=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
class Article(models.Model):
stock = models.ForeignKey(Stock, on_delete=models.CASCADE, default = 0 )
title = models.CharField(max_length = 200)
url = models.URLField()
description = models.TextField()
def __str__(self):
return self.title
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Stock
from django.forms import ModelMultipleChoiceField
class ProfileRegistrationForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'password1', 'password2', 'email', 'first_name' ,'last_name')
class StockFollowForm():
stocks = forms.ModelMultipleChoiceField(queryset=Stock.objects.all())
views.py
def test(request):
if request.method == "POST":
form = StockFollowForm(request.POST)
if form.is_valid():
request.user.profile.followed_stocks = form.cleaned_data.get('stocks_selected')
request.user.save()
return redirect('index')
else:
form = StockFollowForm()
return render(request, 'core/test.html',{'form': form})
template:
{% block body %}
<div class = "container">
<h2 class = "text-center">Register</h2>
<form method = 'post'>
{% csrf_token %}
{{ form }}
<div class = "text-center">
<br/>
<button class="btn btn-primary" type = 'submit'>Login</button>
</div>
</form>
</div>
{% endblock %}
When I run this code no form is displayed. Thanks in advance for your help!
I think your form class has to inherit from djangos form, like the docs show.
Change
class StockFollowForm():
to
from django import forms
class StockFollowForm(forms.Form):

Django Forms: Cannot get to data to save from ModelForm

I am creating a job board site. Right now I can successfully register an Employer but when I try to create a job listing while logged in as an Employer, the data from the form does not save to the database. I have the following models.py:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.http import HttpResponse
# Create your models here.
class Employer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.user.first_name
#receiver(post_save, sender=User)
def create_employer(sender, instance, created, **kwargs):
if created:
Employer.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_employer(sender, instance, **kwargs):
instance.employer.save()
class Job(models.Model):
poster = models.ForeignKey(Employer, on_delete=models.CASCADE)
job_title = models.CharField(max_length=50)
establishment_name = models.CharField(max_length = 50)
details = models.TextField(max_length = 2000)
salary = models.CharField(max_length = 20)
address = models.CharField(max_length = 50)
state = models.CharField(max_length = 20)
zip_code = models.CharField(max_length = 10)
def __str__(self):
return self.job_title + " - " + self.establishment_name \
+ ", " + self.poster.user.first_name + " " +self.poster.user.last_name
A user can register as an employer just fine, but I am having problems getting Jobs to save to the database. Once a user registers/logs in as an employer they are redirected to employer_home.html, where an employer can post a job:
{% extends 'core/base.html' %}
{% block body %}
<h1>Post a Job</h1>
<form>
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Post</button>
</form>
{% endblock %}
Here is my forms.py:
from django.forms import ModelForm
from .models import Job
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class EmployerSignupForm(UserCreationForm):
class Meta:
model = User
fields = ('first_name',
'last_name',
'email',
'username',
'password1',
'password2',)
class JobPostForm(ModelForm):
class Meta:
model = Job
fields= ('job_title',
'establishment_name',
'salary',
'address',
'state',
'zip_code',
)
and here is my employer_view(view to handle Job form):
def employer_home(request):
if request.method == 'POST':
form = JobPostForm(request.POST)
if form.is_valid():
form.save()
return HttpResponse('Working!')
else:
form = JobPostForm()
return render(request, 'core/employer_home.html', {'form': form})
employer_home.html displays a form with no problem, but when the form is submitted none of the data is saved to the database and the return HttpResponse('Working!') is never executed, it simply reloads the empty form. Does anyone know how to fix this?
Add method="POST" in your form. In your view do this:
def employer_home(request):
if request.method == 'POST':
form = JobPostForm(request.POST)
if form.is_valid():
job_object = form.save(commit=False)
job_object.poster = poster_object
job_object.save()
return HttpResponse('Working!')
else:
form = JobPostForm()
return render(request, 'core/employer_home.html', {'form': form})
A good example is shown here: example
Try <form method="post"> in your html template.
By default, the method is get.

Add model relation to ModelForm before saving

models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=32)
class Article(models.Model):
author = models.ForeignKey(Author, on_delete=models.SET_NULL, null=True)
content = models.TextField()
forms.py
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['content']
In my web application, the author logs in and writes an article. So clearly, when the author is presented with an ArticleForm, he/she does not need to fill in the author field in the ArticleForm because the application already knows who the author is through the use of session variables.
This is the way I tried to add the author:
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from .models import Article
from .forms import ArticleForm
#login_required
def new_article(request):
author_name = request.session['author_name']
author = Author.objects.get(name=author_name)
if request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
form.save(commit=False)
form.author = author # I suspect the mistake is here
# I also tried form.author = author.id
form.save()
return redirect('success')
else:
form = ArticleForm()
return render(request, 'writings/new_article.html', {'form': form})
When I look at the database table, the author_id column is always NULL. What is wrong with my approach? How do I add a model relation before saving a ModelForm?
Capture the object returned from form.save(commit=False) and modify that rather than the form. EG:
if form.is_valid():
article = form.save(commit=False)
article.author = author
article.save()
return redirect('success')