I'm relatively new to django and building my first app.
Tried searching through the site, but for the life of me cannot find the relevant information needed.
I'm looking to have a confirmation email sent to the entered email address on a contact form. I've seen examples of sending to a chosen address, or to user, but I can't seem to work out how to send mail to the email entered on the form.
Any help is greatly appreciated!
models.py:
from django.db import models
class Quote(models.Model):
name = models.CharField(max_length=200, blank=False, null=False, verbose_name="your name")
email = models.EmailField(max_length=255, blank=False, null=False)
created_at = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.name
forms.py:
class QuoteForm(forms.ModelForm):
class Meta:
model = Quote
views.py:
class QuoteView(CreateView):
model = Quote
form_class = QuoteForm
template_name = "quote/quote.html"
success_url = "/quote/success/"
def form_valid(self, form):
super(QuoteView,self).form_valid(form)
return HttpResponseRedirect(self.get_success_url())
class QuoteSuccessView(TemplateView):
template_name = "quote/quote-complete.html"
You can access validated form data (coerced to the fields respective types) via the cleaned_data attribute as shown in the form docs
https://docs.djangoproject.com/en/dev/topics/forms/#processing-the-data-from-a-form
from django.core.mail import send_mail
def form_valid(self, form):
super(QuoteView,self).form_valid(form)
send_mail("Foo", "bar", 'from#example.com', [form.cleaned_data['email']])
return HttpResponseRedirect(self.get_success_url())
Related
I'm trying to save a user post data through a modelform in django. Unfortunately, I stumbled to NOT NULL constraint failed:statussaver_post.user_id. Here's my post model.
class post(models.Model):
content=models.TextField(null=True,blank=True)
title = models.CharField(max_length=200,null=True,blank=True)
vedio = models.FileField(upload_to='vedios', blank=True, null=True)
img = models.ImageField(upload_to='images', null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return self.title
I handle the request in views.py as shown below.
def userpost(request):
if request.method=='POST':
form=uploadform(request.POST,request.FILES)
if form.is_valid():
form.save()
return redirect('home')
else:
form=uploadform()
return render(request,'statussaver/u.html',{'form':form,})
The form in the code above is called from forms.py as presented below.
from django import forms
from .models import post
class uploadform(forms.ModelForm):
class Meta:
model=post
fields= '__all__'
What should I do to fix this error ?
I'm learning django and I made the tutorial on django site. I thought that I could link user to poll that he created but I'm struggling with it. When I'm logged in and creating a poll I can't see user name. In database column author_id has value null. I would appreciate every help.
Here is my code
from django.db import models
from django.utils import timezone
import datetime
from django.contrib import auth
# Create your models here.
User = auth.get_user_model()
class Question(models.Model):
question_text = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=False)
def __str__(self):
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
class User(auth.models.User, auth.models.PermissionsMixin):
def __str__(self):
return "#{}".format(self.username)
forms.py:
class UserCreateForm(UserCreationForm):
class Meta:
fields = ('username', 'email', 'password1', 'password2')
model = get_user_model()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].label = 'Display Name'
self.fields['email'].label = 'Email Address'
class CreatePollForm(forms.ModelForm):
class Meta:
model = Question
fields = ('question_text',)
and views.py
class CreatePoll(LoginRequiredMixin, generic.CreateView):
form_class = forms.CreatePollForm
success_url = reverse_lazy('pollapp:index')
template_name = 'polls/createPoll.html'
Since your CreatePollForm only assigns the question_text field, you need to assign the author in code. A CreateView is a FormView which does the saving of the form in its form_valid() method. So in your CreateView, you want to override that method:
# in class CreatePoll
def form_valid(self, form):
question = form.save(commit=False) # fetch the new question, don't save
question.author = self.request.user # assign the user
question.save() # now save
return super().form_valid(form)
It isn't clear how you could end up with a null value for the author_id, that should have raised an IntegrityError. Are you sure you ran makemigrations and migrate in the current state?
I'm making a site in Django using django-allauth for authentication.
I've created a custom user class in accounts.models to add a custom field, FavouriteTeam.
The issue I have is that the form renders fine and submits formdata for fav_team fine (as inspected in Chrome dev tools) but the fav_team entry doesn't get stored to user.FavouriteTeam and I can't figure out why.
I can go into the Django shell, import my User class from accounts.models, query for a user, add a .FavouriteTeam, and save just fine. It's just that the form doesn't seem to save the data into the new User instance for some reason.
I'm guessing it's due to the way django-allauth interacts with custom user models but I can't figure it out for the life of me. I've seen some similar posts but none have a situation like this or have a solution that seems to work for me.
Any ideas?
accounts.models: -
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
FavouriteTeam = models.ForeignKey('predictor.Team', on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return self.email
accounts.forms: -
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import User
from allauth.account.forms import SignupForm
from predictor.models import Team
from django.contrib.auth import get_user_model
class CustomSignupForm(SignupForm):
first_name = forms.CharField(max_length=30, label='First Name')
last_name = forms.CharField(max_length=30, label='Last Name')
fav_team = forms.ModelChoiceField(queryset=Team.objects.all(), empty_label=None, label='Favourite Team')
class Meta:
model = get_user_model()
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.FavouriteTeam = self.cleaned_data['fav_team']
user.save()
return user
predictor.models: -
class Team(models.Model):
ShortName = models.CharField(max_length=4, primary_key=True)
Town = models.CharField(max_length=20)
Nickname = models.CharField(max_length=20)
Conference = models.CharField(max_length=3, null=True, blank=True)
Division = models.CharField(max_length=5, null=True, blank=True)
ConfDiv = models.CharField(max_length=9, null=True, blank=True)
Logo = models.ImageField(default='football.png', upload_to='logos')
def __str__(self):
return('{} {}'.format(self.Town, self.Nickname))
def save(self, *args, **kwargs):
self.ConfDiv = str(self.Conference)+" "+str(self.Division)
super(Team, self).save(*args, **kwargs)
For anyone looking at this and suffering the same issue, I eventually found the solution to be as below.
Firstly, I had to create adpaters.py within my accounts app and fill in the below: -
from allauth.account.adapter import DefaultAccountAdapter
class AccountAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=False):
data = form.cleaned_data
user.email = data['email']
user.first_name = data['first_name']
user.last_name = data['last_name']
user.FavouriteTeam = data['fav_team']
if 'password1' in data:
user.set_password(data['password1'])
else:
user.set_unusable_password()
self.populate_username(request, user)
user.save()
return user
Then I had to referenced the new account adapter in my project's settings.py file as below: -
ACCOUNT_ADAPTER = "accounts.adapters.AccountAdapter"
Hope that helps someone in the future.
I am creating a user using OneToOne relationship , when I enter the data in the form and submit it, I'm getting no null constraint error
view.py
def registerUser(request):
if request.method=='POST':
form=UserCreationForm(request.POST)
form_class=ProfileForm(request.POST)
if form.is_valid() and form_class.is_valid():
form.save()
form_class.save()
return redirect('/home/')
else:
form=UserCreationForm()
form_class = ProfileForm()
return render(request,'register.html',{'form':form,'form_class':form_class})
form.py
class Registerform(UserCreationForm):
class Meta:
model=User
fields= ['username','first_name','last_name','password1','password2']
def save(self, commit=True):
user=super(Registerform, self).save(commit=False)
user.first_name=self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
if commit:
user.save()
return user
class ProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = [ 'location']
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
description = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
salary=models.CharField(max_length=120)
def __str__(self):
return self.location
Your UserProfile model requires a salary but your form only has a location field. So when your form is submitted with a location, it's valid, but the underlying model cannot be saved because salary will be None.
Add the salary field to your form, or make salary a nullable field.
Also, you need to assign the user field before saving the profile, since that also is not nullable. One way to do that is:
user = form.save() # this is the UserForm so when saving it returns the user
profile = form_class.save(commit=False)
profile.user = user
profile.save()
I would recommend you carefully read the Django documentation on model forms. The section on the save method in particular would explain you how to properly handle these cases.
What a want to do: When a user is logged in, and he or she makes a post, the name of that user should automatically be assigned in my database posts.
What it's doing: It's not adding a user automatically, but i am able to assign a user manually, so I'm accessing the user database, and seeing whom i can attach to a newly made post.
My question is then, how can i get this process done automatically?
Here is my code from the model.py in the posts app:
from __future__ import unicode_literals
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.contrib.auth.models import User
User = settings.AUTH_USER_MODEL
class Post(models.Model):
title = models.CharField(max_length=120)
content = models.TextField()
#email = models.EmailField(null=True, blank=True, default=None)
user = models.ForeignKey(User, null=True,)
#upload = models.FileField(null=True, blank=True, default=None)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True, auto_now_add=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"id":self.id})
class Meta:
ordering = ["-timestamp", "-updated"]
I am getting the user class via User = settings.AUTH_USER_MODEL and the AUTH_USER_MODEL is referring in settings.py to a class called MyUser in another models.py who originates from an app called accounts.
here is the code from that class:
class MyUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
is_admin = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
USERNAME_FIELD = 'email'
Here is the code from views.py in the posts app:
def post_create(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
# Message succes
messages.success(request, "Succesfully Created ")
return HttpResponseRedirect(instance.get_absolute_url())
else:
messages.error(request, "Not Succesfully created")
context = {
'form': form,
}
return render(request, app_name+"/post_form.html", context)
Here is the forms.py in the posts app:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = {
"title",
"content",
"user",
#"email",
#"upload",
}
Here are two pictures to illustrate my problem:
The post create site
The django administration
Let me now if any more code is needed, appreciate any feedback as well.
I don't have a lot of rep on stack overflow so please let me know if this is poorly explained, and i shall re right it.
Simply change:
instance = form.save(commit=False)
instance.save()
to
instance = form.save(commit=False)
if request.user.is_authenticated():
instance.user = request.user
instance.save()
If user is logged in, i think the Combobox should not
appear, so you can do that on forms.py
forms.py
class PostForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(PostForm, self).__init__(*args, **kwargs)
if not self.user.is_authenticated():
self.fields['user'] = forms.ModelChoiceField(
required=True,
queryset=User.objects.all())
class Meta:
model = Post
fields = {
"title",
"content",
# "user",
#"email",
#"upload",
}
on views.py
def post_create(request):
form = PostForm(request.POST or None, user = request.user)
if form.is_valid():
if request.user.is_authenticated():
form.instance.user = request.user
form.save()
...
return render(request, app_name+"/post_form.html", context)
If you want the Combobox has selected with the user logged in, you can pass initial data on views.py, like this:
def post_create(request):
if request.method == 'GET':
form = PostForm(initial = {'user' : request.user})