GAE + Django Forms + Validation - google-app-engine

I have a problem with how to do validation on GAE. I have read many tutorials and I prepared django form and I wanted to validate it but I dont see eny error messages in my web page code and I dont see any errors when the values are bad.
import cgi
import os
from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext.db import djangoforms
from django import newforms as forms
class SurveyForm(forms.Form):
occupations_choices = (
('0', "Choose one..."),
('1', "Undergraduate student"),
('2', "Postgraduate student (MSc)"),
('3', "Postgraduate student (PhD)"),
('4', "Lab assistant"),
('5', "Technician"),
('6', "Lecturer"),
('7', "Other" )
)
howreach_choices = (
('0', "Choose one..."),
('1', "Typed the URL directly"),
('2', "Site is bookmarked"),
('3', "A search engine"),
('4', "A link from another site"),
('5', "From a book"),
('6', "Other")
)
boxes_choices = (
("des", "Website Design"),
("svr", "Web Server Administration"),
("com", "Electronic Commerce"),
("mkt", "Web Marketing/Advertising"),
("edu", "Web-Related Education")
)
range_choice = (
('1', '1'),
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5')
)
name = forms.CharField(label='Enter your name', max_length=50, required=True)
email = forms.EmailField(label='Your email address')
occupations = forms.ChoiceField(choices=occupations_choices, label='What is your occupation?')
howreach = forms.ChoiceField(choices=howreach_choices, label='How did you reach this site?')
# radio buttons 1-5
rating = forms.ChoiceField(choices=range_choice , label='How would you rate the content of this site?', widget=forms.RadioSelect)
boxes = forms.ChoiceField(choices=boxes_choices, label='Are you involved in any of the following? (check all that apply)', widget=forms.CheckboxSelectMultiple)
comment = forms.CharField(label=('Any other comments?'), widget=forms.Textarea(attrs={'cols': 40, 'rows': 10}), required=False)
class MainHandler(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
if user:
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
userName = user.nickname()
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
userName = ''
template_values = {
'url' : url,
'url_linktext' : url_linktext,
'userName' : userName,
'form' : SurveyForm(),
}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
def post(self):
user = users.get_current_user()
if user:
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
userName = user.nickname()
#self.response.out.write(index.html)
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
userName = ''
template_values = {
'url' : url,
'url_linktext' : url_linktext,
'userName' : userName,
'form' : SurveyForm(),
}
form = SurveyForm(self.request.POST)
if self.request.get('submit') == 'Submit the Form':
if form.is_valid():
self.response.out.write("Poprawne dane")
else:
form = SurveyForm()
template_values['form']=form
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
else:
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
Do You know maybe any tutorial - good tutorial how to do it? My index.html:
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Survey</title>
</head>
<body>
{% if userName %}
You are loged in like: {{ userName }} {{ url_linktext }}
<hr><br/><b>Fill in the form: </b><br/>
<form action="/" method="Post">
{{ form.as_p() }}
<input type="submit" name="submit" value="Submit the Form">
</form>
{% else %}
Please, log in: {{ url_linktext }}
{% endif %}
</body>
</html>
How to do it does the validation started to show me errors? And be like "normal validation"? I thought when I will use the framework it will be much more easier and faster for me but I spent 2 days and it is still not working :/ I could write my own validation in this time :/
Can You help me?

Look at {{ form.some_field.errors }}, or if you want all of them, {{ form.errors }}, or if you need non-field errors only, {{ form.non_field_errors }}.
Here is an example of how to do it: http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

Related

AttributeError: 'CharField' object has no attribute 'use_required_attribute'

I try to add a form-control class to an input field of a model-based form in Django, but I get this error message:
AttributeError: 'CharField' object has no attribute 'use_required_attribute'.
How do I fix this?
class in views.py:
class TweetCreate(LoginRequiredMixin, CreateView):
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
def get_form(self):
form = super().get_form()
form.fields['search_term'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'}))
form.fields['query_type'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'}))
form.fields['start_date'].widget = DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['end_date'].widget = DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['language'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'})),
form.fields['country'].widget = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'class': 'form-control'})),
return form
class in models.py:
class TweetSearch(models.Model):
from datetime import datetime, timedelta
search_term = models.CharField(max_length=200, default='blue bird')
QUERY_CHOICES = (
('t', 'in tweet'),
('h', 'in hashtag'),
('u', 'username'),
)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, blank=True)
query_type = models.CharField(max_length=1, choices=QUERY_CHOICES, blank=True, default='t')
start_default = datetime.now() - timedelta(days=30)
start_date = models.DateTimeField(default=start_default)
end_date = models.DateTimeField(default=datetime.now)
language = models.CharField(max_length=200, default='English')
country = models.CharField(max_length=200, default='USA')
searcher = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
def get_absolute_url(self):
return reverse('tweet_detail', kwargs={'pk': self.pk})
def __str__(self):
return f"Tweets with the word {self.search_term} from {self.start_date} till {self.end_date} written in " \
f"{self.language} in {self.country}."
HTML:
<div class="container" id="searchcontainer" style="text-align: center">
<form action="" method="POST">
{% csrf_token %}
{{form.search_term}}
{{form.query_type}}
{{form.start_date}}
{{form.end_date}}
{{form.language}}
{{form.country}}
<input class="btn btn-primary" type="submit">
</form>
</div>
You are confusing form field with widgets. You should assign a widget like TextInput, not a form field like CharField, like:
class TweetCreateView(LoginRequiredMixin, CreateView):
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
def get_form(self):
form = super().get_form()
form.fields['search_term'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['query_type'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['start_date'].widget=DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['end_date'].widget=DateTimePickerInput(attrs={'class': 'form-control'})
form.fields['language'].widget=forms.TextInput(attrs={'class': 'form-control'})
form.fields['country'].widget=forms.TextInput(attrs={'class': 'form-control'})
return form
It however here might be better to just plug in a ModelForm, so:
class TweetForm(forms.ModelForm):
class Meta:
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']
widgets = {
'search_term': forms.TextInput(attrs={'class': 'form-control'}),
'query_type': forms.TextInput(attrs={'class': 'form-control'}),
'start_date': DateTimePickerInput(attrs={'class': 'form-control'}),
'end_date': DateTimePickerInput(attrs={'class': 'form-control'}),
'language': forms.TextInput(attrs={'class': 'form-control'}),
'country': forms.TextInput(attrs={'class': 'form-control'}),
}
and plug this into the TweetCreateView:
class TweetCreateView(LoginRequiredMixin, CreateView):
model = TweetSearch
form_class = TweetForm
if you however only want to change the class, you can simplify this with:
class FormControlForm(forms.Form):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
class TweetForm(FormControlForm, forms.ModelForm):
class Meta:
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country']

Identify the custom user model in REST_FRAMEWORK settings Django

I'm new in Django rest_framework. I'm using a custom user model and djoser as my authentication system. I want to use my custom user model in the djoser register view and I don't know how to identify that in the rest_framework settings?
settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSIONS_CLASSES':(
'rest_framework.permissions.IsAuthenticated',
),
}
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, phone, password=None):
if not email:
raise ValueError("Users must have an email address")
if not username:
raise ValueError("Users must have an username")
if not phone:
raise ValueError("Users must have a phone number")
user = self.model(
email=self.normalize_email(email),
username=username,
phone=phone
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self,email, username, phone, password):
user = self.create_user(
email=self.normalize_email(email),
username=username,
phone=phone,
password=password
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email",max_length=60, unique=True)
username = models.CharField(max_length=60,unique=True)
phone = models.CharField(max_length=60,unique=True)
date_joined = models.DateTimeField(verbose_name="date joined",auto_now_add=True)
last_login = models.DateTimeField(verbose_name="last login",auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
first_name = models.CharField(max_length=60,null=True)
last_name = models.CharField(max_length=60,null=True)
wilaya = models.CharField(max_length=60,null=True)
city = models.CharField(max_length=60,null=True)
address = models.CharField(max_length=200,null=True)
store_coordinates = models.CharField(max_length=60,null=True)
documents1 = models.CharField(max_length=60,null=True)
documents2 = models.CharField(max_length=60,null=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email','phone']
objects = MyAccountManager()
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
What should I add to use my custom user model in djoser register view?
You're doing almost everything right, but you need to tell Django in the settings what user model it should use.
In models.py use something like this
from django.contrib.auth.models import AbstractUser
from .managers import UserManager
class User(AbstractUser):
# Add whatever fields you want
# Use your custom manager
objects = UserManager()
In settings.py
# Tell Django what user model should be used
AUTH_USER_MODEL = 'auth.User' # app_label.model
make sure you use python manage.py makemigrations && python manage.py migrate to create your custom user model.
Enjoy!

django prevent empty model being saved

Is there a way to stop a model in django allowing an empty model to be saved?
e.g. I have a simple contact form
class Contact(models.Model):
alphabetical = RegexValidator(r'^[a-zA-Z]*$', 'Only alphabetical characters
are allowed', 'Invalid input')
name = models.CharField(max_length=200, validators=[alphabetical])
email = models.EmailField(validators=[EmailValidator, ])
subject = models.CharField(max_length=200)
message = models.CharField(max_length=250)
created_date = models.DateTimeField(auto_now_add=True)
How can I prevent an empty model being saved? e.g. in the django shell I can do
contact = Contact()
contact.save()
This gives a model with all blank values saved.
for validation you have to use django.forms. django forms will manage the validation part:
for eg: if your model.py is:
class Contact(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
subject = models.CharField(max_length=200)
message = models.CharField(max_length=250)
created_date = models.DateTimeField(auto_now_add=True)
now create a view in views.py :
from django.forms import modelformset_factory
from django.shortcuts import render
from myapp.models import Contact
def manage_contacts(request):
ContactFormSet = modelformset_factory(Contact, fields=('name', 'email', 'subject', 'message'))
if request.method == 'POST':
formset = ContactFormSet(request.POST)
if formset.is_valid(): # check the validation for blank fields
formset.save()
# do something.
else:
formset = ContactFormSet()
return render(request, 'manage_contacts.html', {'formset': formset})
create a template in templates/manage_contacts.html:
<form method="post">
{{ formset }}
</form>

Error with rendering webapp2

Good personal day. I have a problem I can not solve.
It happens that in an app I am creating have 3 files: main, config and home.html
The config file is used to grab the User data and adds them to a dictionary. If the User does not exist in the datastore, he adds.
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from google.appengine.api.app_identity import get_default_version_hostname
from google.appengine.ext import ndb
url = get_default_version_hostname()
# BANCO DE DADOS PARA SALVAR OS USUARIOS
class Usuarios(ndb.Model):
usuario = ndb.StringProperty()
email = ndb.StringProperty()
openID = ndb.StringProperty()
date = ndb.DateTimeProperty(auto_now_add=True)
tipo = ndb.StringProperty()
#classmethod
def get_email(cls, email):
return cls.query(cls.email == email)
########### FUNÇÃO QUE CHAMA O LOGIN ########
def Redir():
from google.appengine.api import users
user = users.get_current_user()
if users.is_current_user_admin():
redir = 'http://' + url + '/admin'
else:
redir = None
return redir
def Geral():
from google.appengine.api import users
user = users.get_current_user()
providers = {
'Google' : 'https://www.google.com/accounts/o8/id',
'Yahoo' : 'yahoo.com',
}
rt = {
'titulo' : 'BETA HCBravin',
'version' : '14.11.10',
'url' : 'http://' + url,
}
# O USUARIO ESTA LOGADO?
if user:
# O USUARIO E UM ADMINISTRADOR?
if users.is_current_user_admin():
dtipo = 'Admin'
else:
dtipo = 'Aluno'
# O USUARIO EXISTE NO BANCO DE DADOS?
quser = Usuarios.get_email(user.email())
buser = quser.get()
if not buser:
dbuser = Usuarios(usuario = user.nickname(), email = user.email(), openID = user.user_id(), tipo = dtipo)
dbuser.put()
if buser:
if buser.tipo == 'Professor':
dtipo = 'Professor'
else:
dtipo = 'Aluno'
rt.update({
'usuario': user.nickname(),
'email': user.email(),
'openID': user.user_id(),
'logout_url': users.create_logout_url('/'),
'user_tipo': dtipo,
})
else: # let user choose authenticator
#login_url = {'usuario': None, 'logout_url': None}
login_url = {}
for name, uri in providers.items():
login_url[name] = users.create_login_url(dest_url = ('/usuario') ,federated_identity=uri)
rt.update(login_url)
return rt
########## ############
The main file is the main file of my app that renders the home.html
import os
import webapp2
import sys
from config import *
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
Geral = Geral()
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.out.write(template.render('home.html', Geral))
app = webapp2.WSGIApplication([
('/', MainHandler),
], debug=True)
The home.html only has a value that is to get the variable {{ email }} and print it (that's not all, logical. Bad am using the simplest approach)
The problem:
When I login with a User it perfectly shows email. But if I make out and User mute rather than appearing email "new" keeps popping up the old email.
This remains even if I refresh the page.
Code outside of your handler's methods only runs when an instance starts up, not once-per-request.
So your call Geral = Geral() isn't being repeated for visitors after the first one.
You should move that line inside your get method (and probably change the name on the left-hand-side to not be the same as the function-name!)

edit and update the row in database using django

models.py
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
age = models.IntegerField()
def __unicode__(self):
return "{0} {1} {2} {3} {4}".format(
self, self.first_name, self.last_name, self.email, self.age)
class Book(models.Model):
book_name=models.CharField(max_length=30)
publisher_name=models.CharField(max_length=40)
author=models.ForeignKey(Author)
def __unicode__(self):
return "{0} {1} {2}".format(
self.pk, self.book_name, self.publisher_name)
forms.py
class AuthorForm(ModelForm):
class Meta:
model = Author
BookFormset = inlineformset_factory(Author, Book,
fields=('book_name', 'publisher_name'), extra=1,
can_delete=False)
urls.py is
admin.autodiscover()
urlpatterns = patterns('',
url('^$', index),
url('^index/$', index),
url('^addbook/$', addbook),
url('^book_detail/$', book_detail, 'book_summary'),
url('^editbook/(?P<book_id>\d+)/$', editbook) ,
url('^deletebook/(?P<book_id>\d+)/$',deletebook) ,
url(r'^admin/', include(admin.site.urls)),
)
I need to perform edit and update the row in database,i did it by using single table.But using two table have some confusion how to take 2nd table using that particular id.I am using forms in this.Can you help me in this to write codes in views.py.Example for doing the same using two table is no where i seen.
Thanks
def update_book(request, book_id):
author = get_object_or_404(Author, pk=author_id)
form = AuthorForm(instance=author)
book_formset = BookFormset(instance=author)
if request.method == 'POST':
form = AuthorForm(request.POST, instance=author)
if form.is_valid():
author = form.save(commit=False)
book_formset = BookFormset(request.POST, instance=author)
if book_formset.is_valid():
author.save()
book_formset.save()
return redirect('/index/')
return render_to_response('updatebook.html',{
'form': form, 'formset': book_formset
},context_instance=RequestContext(request))
<div align="center">
<tr>
<form method="POST">
{% csrf_token %}
<h5>Author:</h5>
{{ form.as_p }}
<h5>Book:</h5>
{{ formset.as_p }}
<input type="submit" value="submit">
</form>
</tr>
</div>

Resources