I have an issue with my authentication process.
I create a SignIN process giving a user the ability to create an a new account using only his mail, account that will be inactive until he edits it providing his first name, last name and a password.
I gave it a try but I go to the URL for edit profile I receive an error related to the PK ..
error:
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/registration/users/2/edit/
Django Version: 1.11.3
Python Version: 3.6.2
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'registration']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/Users/raphaelbendenoun/anaconda/envs/myDjangoEnv/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/Users/raphaelbendenoun/anaconda/envs/myDjangoEnv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/Users/raphaelbendenoun/anaconda/envs/myDjangoEnv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/raphaelbendenoun/Documents/testregis/registration/views.py" in update_profile
41. user = get_object_or_440(User, pk=pk) #find user instance by id in db
Exception Type: NameError at /registration/users/2/edit/
Exception Value: name 'get_object_or_440' is not defined
'pk'
urls:
from django.conf.urls import url, include
from registration import views
app_name = 'registration'
urlpatterns = [
url(r'^register/$', views.register, name='register'),
url(r'^users/(?P<pk>\d+)/edit/$', views.update_profile, name="edit-user-profile"),
]
form.py:
from django import forms
from django.contrib.auth.models import User
from .models import MyUser
from django.contrib.auth import get_user_model
User = get_user_model()
class Form(forms.ModelForm):
password = forms.CharField(widget= forms.PasswordInput())
class Meta():
model = User
fields= ('first_name','last_name','email','password','company')
class InactiveForm(forms.ModelForm):
class Meta():
model = User
fields= ('email',)
class UpdateProfile(forms.ModelForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
password = forms.CharField(widget= forms.PasswordInput())
class Meta:
model = User
fields = ('email', 'first_name', 'last_name','password')
def clean_email(self):
email = self.cleaned_data.get('email')
if email and User.objects.filter(email=email).count():
raise forms.ValidationError('This email address is already in use. Please supply a different email address.')
return email
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py
from django.shortcuts import render
from django.views import generic
from django.views.generic import TemplateView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .forms import InviteForm
from invitations.models import Invitation
from .models import project
from django.core.urlresolvers import reverse
# Create your views here.
class HomePage(TemplateView):
template_name= 'index.html'
class CandidateIndex(TemplateView):
template_name= 'candidateIndex.html'
class HRIndex(TemplateView):
template_name= 'HRindex.html'
class ProjectDetailView(generic.DetailView):
model = project
template_name = 'project_details.html'
class ProjectCreate(CreateView):
model = project
fields = ['project_name']
template_name = 'project_form.html'
def create_invite(request):
if request.method == "POST":
invite_form = InviteForm(data=request.POST)
if invite_form.is_valid():
email1 = invite_form.cleaned_data['email1']
email2 = invite_form.cleaned_data['email2']
email3 = invite_form.cleaned_data['email3']
email4 = invite_form.cleaned_data['email4']
email5 = invite_form.cleaned_data['email5']
for i in invite_form.cleaned_data:
invite = Invitation.create(i)
invite.send_invitation(request)
print("The mail was went")
#return reverse('website:ProjectDetails', kwargs = {'pk' : self.pk} )
else:
print("Your form is not valid")
else:
invite_form = InviteForm()
return render(request, 'team_invite.html', {'invite_form': invite_form})
project_detail.html:
{% extends 'base.html' %}
{% block body %}
<div class="container">
<div class="jumbotron">
<h2>Welcome to your Project {{project.project_name}} Detail page</h2>
</div>
<div class="invite-team">
GOGO
</div>
</div>
{% endblock%}
You pass pk variable from urls.py to view method, but your view method did not expect it you have to change your update_profile method signature like so:
update_profile(request, pk)
....
your method has more erros inside like this one:
form = UpdateProfile(request.POST, instance=request.User)
it probaly should be:
User = get_user_model()
user = get_object_or_404(User, pk=pk) #find user instance by id in db
form = UpdateProfile(request.POST, instance=user)
Related
I have a small problem with adding data to the database in django 2.0.3
I created the following model:
from django.contrib.auth.models import User
class UserInputSignal(models.Model):
name = models.CharField(max_length=512)
author = models.ForeignKey(User, on_delete=models.CASCADE)
input_file = models.FileField(upload_to='signals/', null=True)
I tried to solve the problem using this form:
from django import forms
from .models import UserInputSignal
class UserInputSignalForm(forms.ModelForm):
name = forms.CharField()
input_file = forms.FileField()
class Meta:
model = UserInputSignal
fields = ('name', 'input_file', )
and this view:
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate
from .forms import UserInputSignalForm
#login_required
def storage(request):
form = UserInputSignalForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
name = request.POST.get('name')
author = request.POST.get(request.user)
input_file = request.POST.get('input_file')
return redirect('home')
else:
form = UserInputSignalForm()
return render(request, 'storage.html', {'form': form})
In the template I called, I created the form as follows:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
I am able to load a page with a form, but it does not post data to the database. I would like to add that I am a novice in django and some mechanisms are just plain understandable for me. Can I ask someone for help with this problem?
Before the redirect, call form.save()
Okay, i worked on your code and it works with me with slight modifications:
models.py
class UserInputSignal(models.Model):
name = models.CharField(max_length=512)
author = models.ForeignKey(User, on_delete=models.CASCADE)
input_file = models.FileField(upload_to='signals/', null=True)
objects = models.Manager()
#this returns the name for your modelobject
def __str__(self):
return self.name
forms.py
#excluded the assiging as fields defination is enough in itself
class UserInputSignalForm(forms.ModelForm):
class Meta:
model = UserInputSignal
#this will exclude the formfield it self but the author will be saved as the person who is logged in
exclude = ["author"]
Edited - Views.py
#login_required
def storage(request):
#authentication for author field using request.user
insta = UserInputSignal(author=request.user)
print(request.user)
form = UserInputSignalForm(request.POST or None, request.FILES or None,instance=insta)
if request.method == 'POST':
if form.is_valid():
signal = form.save(commit=False)
signal.save()
return redirect('home')
else:
form = UserInputSignalForm(instance=insta)
return render(request, 'storage.html', {'form': form})
JlucasRs was right to tell you to use form.save(), but you needed to assign form to something and need not use model fields here as forms.py does that for you.
app/Urls.py - Just for reference
urlpatterns = [
path('home/', home, name='home'),
path('storage/', storage, name='storage'),
]
Edit- Admin.py
from .models import PostModel, UserInputSignal
class UserInputSignalAdmin(admin.ModelAdmin):
list_display = ('name', 'author', 'input_file' )
admin.site.register(UserInputSignal, UserInputSignalAdmin)
Add this code in Admin.py if its not there.
I've installed django-registration-redux and custom_user. I have a UserProfile model with fullname,dob and photo as extra fields.
I have connected the UserProfile with user-registration so as to save the additional fields to UserProfile table.
Here my questions are...
How do I validate fields in UserProfile model at the time of registration so that I can prevent addition of a user to the emailuser table. Say, if the dob given is invalid or not in allowed range, then stop adding a user to emailuser table.
How can I make an EditProfile system that allows authenticated users to edit their profile (/user/edit - id to be obtained from session).
Below is my settings.py file
INSTALLED_APPS = [
'django.contrib.admin',
'custom_user',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
#------------
'registration',
'userprofile',
]
AUTH_USER_MODEL = 'custom_user.EmailUser'
models.py
class UserProfile(models.Model):
user=models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
primary_key=True,)
fullname=models.CharField(max_length=70, blank=False)
dob=models.DateField(blank=False)
photo=models.ImageField(upload_to='profile_images', blank=False)
def __str__(self):
return self.user.email
def user_registered_callback(sender, user, request, **kwargs):
profile = UserProfile(user = user)
profile.fullname =request.POST["fullname"]
profile.dob ="%s-%s-%s" % (request.POST["dob_year"],request.POST["dob_month"],request.POST["dob_day"])
if 'photo' in request.FILES:
profile.photo = request.FILES['photo']
profile.save()
user_registered.connect(user_registered_callback)
forms.py
class UserProfileForm(RegistrationForm):
fullname=forms.CharField(required=True,label="Full name", min_length=3, max_length=75)
dob=forms.DateField(required=True,label="Date of birth",
widget=forms.SelectDateWidget(years=range(now.year-settings.AGE_UPPER,now.year-settings.AGE_LOWER)))
photo=forms.ImageField(required=False)
views.py
def profile(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/user/login')
else:
return render(request, 'userprofile/profile.html', {"user":request.user})
class EditProfile(UpdateView):
template_name = 'userprofile/edit_profile.html'
fields = ['fullname','dob','photo']
main urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'user/register/$',
RegistrationView.as_view(form_class = UserProfileForm),
name = 'registration_register'),
url(r'^user/', include('registration.backends.default.urls')),
url(r'^user/', include('userprofile.urls')),
userprofile.urls.py
urlpatterns = [
url(r'^profile/$', views.profile, name='profile'),
url(r'^profile/edit/$', views.EditProfile.as_view(), name='edit_profile'),
]
Right now I'm, getting EditProfile is missing a QuerySet. Define EditProfile.model, EditProfile.queryset, or override EditProfile.get_queryset().
Is it the right way to proceed? Any help would be appreciated.
Thanks
Altough my form to send an offer is correctly displayed and I have no error when submitting the offers, they are not saved in my database.
I know that by checking the admin site, no objects are saved.
But on the other hand, I already have written the code for the registration and users are saved in the database.
I suspect the ForeignKey relation between my 2 models as the culprit.
models.py
from django.db import models
class User(models.Model):
username = models.CharField(max_length=30, unique=True, blank=False)
password1 = models.CharField(max_length=40, blank=False)
password2 = models.CharField(max_length=40, blank=False)
mail = models.EmailField(unique=True, blank=False)
birthday = models.DateField(blank=False)
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name="Date d'inscription")
def __str__(self):
return self.username
class Offer(models.Model):
publisher = models.ForeignKey(User)
content = models.TextField()
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name="Date de parution")
def __str__(self):
return self.publisher.username
forms.py
from django import forms
from django.contrib import admin
from django.contrib.auth.hashers import make_password, check_password
from django.utils.translation import ugettext_lazy as _
from myuser.models import User, Offer
class UserCreationForm(forms.ModelForm):
class Meta:
model = User
widgets = {
'password1' : forms.PasswordInput(),
'password2' : forms.PasswordInput(),
}
fields = ("username", "password1", "password2", "mail")
def clean_password2(self):
# Check that the two password entries match
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("les mots de passes ne correspondent pas")
return password2
def save(self, commit=True):
# Save the provided password in hashed format
user = super(UserCreationForm, self).save(commit=False)
user.password1 = make_password(self.cleaned_data["password1"])
user.password2 = make_password(self.cleaned_data["password2"])
if commit:
user.save()
return user
class LoginForm(forms.Form):
username = forms.CharField(label="nom d'utilisateur")
password = forms.CharField(label="mot de passe",
widget = forms.PasswordInput)
def clean(self):
cleaned_data = super(LoginForm, self).clean()
username = cleaned_data.get('username')
password = cleaned_data.get('password')
user = User.objects.get(username=username)
if check_password(password, user.password1):
return cleaned_data
else:
raise forms.ValidationError("Le nom d'utilisateur et le mot de passe ne correspondent pas")
class SendOfferForm(forms.ModelForm):
class Meta:
model = Offer
fields = ('content',)
Views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.exceptions import ObjectDoesNotExist
from myuser.models import User, Offer
from myuser.forms import UserCreationForm, LoginForm, SendOfferForm
def get_logged_user_from_request(request):
if 'logged_user_id' in request.session:
logged_user_id = request.session['logged_user_id']
return User.objects.get(id=logged_user_id)
else:
return None
def register(request):
registered = False
if request.method == 'POST':
user_form = UserCreationForm(data=request.POST)
if user_form.is_valid():
user = user_form.save()
registered = True
else:
print(user_form.errors)
else:
user_form = UserCreationForm()
return render(request,
'myuser/create_account.html',
{'user_form': user_form, 'registered': registered} )
def login(request):
if request.method=='POST':
form = LoginForm(request.POST)
try:
if form.is_valid():
user = User.objects.get(username=request.POST.get('username'))
logged_user = User.objects.get(username=request.POST.get('username'))
request.session['logged_user_id'] = logged_user.id
return HttpResponseRedirect('/')
else:
error = "le nom d'utilisateur et le mot de passe ne correspondent pas"
return HttpResponse("Invalid login details supplied.")
except User.DoesNotExist:
return HttpResponse("Invalid login details supplied.")
else:
form = LoginForm
return render(request, 'myuser/mylogin.html', locals())
def send_offer(request):
sent = False
logged_user = get_logged_user_from_request(request)
if logged_user:
if request.method == 'POST':
try:
offerform = SendOfferForm(request.POST, instance=logged_user)
if offerform.is_valid():
sent = True
offerform.save()
else:
print(offerform.errors)
except:
return HttpResponse("drapeau except")
else:
offerform = SendOfferForm(instance=logged_user)
else:
return HttpResponse("Vous n'ĂȘtes pas connectĂ©")
return render(request, 'myuser/send_offer.html', locals())
urls.py
from django.conf.urls import patterns, url, include
from django.views.generic import TemplateView
urlpatterns = patterns('myuser.views',
url(r'^inscription/$', 'register', name='create_account'),
url(r'^connexion/$', 'login', name='login'),
url(r'^envoyer_une_offre$', 'send_offer', name='send_offer'),
)
send_offer.html
{% extends "base.html" %}
{% block content %}
<h1> Offer </h1>
{% if not sent %}
<p> write your offer <p/>
<form action="{% url "send_offer" %}" method='POST' class='sendofferform'>
{{ form.errors }}
{{ form.non_field_errors }}
{% csrf_token %}
{{ offerform.as_p }}
<input type="submit" value="Submit" />
</form>
{% else %}
Offer is published
publish another offer?<br />
get back to the homepage<br />
{% endif %}
{% endblock %}
admin.py
from django.contrib import admin
from myuser.models import User, Offer#, Message
class UserAdmin(admin.ModelAdmin):
list_display = ('id', 'username', 'status', 'college', 'apercu_description')
list_filter = ('id', 'username', 'birthday')
date_hierarchy = 'date'
ordering = ('date', )
search_fields = ('username', 'description')
def apercu_description(self, User):
text = User.description[0:40]
if len(User.description) > 40:
return '%s' % text
else:
return text
class OfferAdmin(admin.ModelAdmin):
list_display = ('id', 'publisher', 'apercu_offre')
list_filter = ('id', )
date_hierarchy = 'date'
ordering = ('date', )
search_fields = ('publisher',)
def apercu_offre(self, Offer):
text = Offer.content[0:40]
if len(Offer.content) > 40:
return '%s' % text
else:
return text
admin.site.register(User, UserAdmin)
admin.site.register(Offer, OfferAdmin)
All of the other function works (register and login) and the register() function correctly saves the user but the send_offer() function, which is very similar to the register function doesn't work and after searching on internet for hours, I still have no idea why the offers are not saved.
But when I try to add an offer in the admin site, it seems to work.
Besides, I tried to save an offer in the python manage.py shell :
>>> Offer.publisher = "a"
>>> Offer.content = "lalalala"
>>> Offer.save()
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/django/core/management/commands/shell.py", line 69, in handle
self.run_shell(shell=options['interface'])
File "/usr/local/lib/python3.4/dist-packages/django/core/management/commands/shell.py", line 61, in run_shell
raise ImportError
ImportError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.4/code.py", line 90, in runcode
exec(code, self.locals)
File "<console>", line 1, in <module>
TypeError: save() missing 1 required positional argument: 'self'
EDIT : The solution was to add these lines :
if offerform.is_valid():
sent = True
offer = offerform.save(commit=False)
offer.publisher = User.objects.get(id=logged_user.id)
offer.save()
Please, note that logged_user is a function, which is described in view.py.
On a ModelForm if you don't pass any object when its instantiated It will create a new object in the database of the specified type. So in this case on your SendOfferForm you have specified Offer. IF you do pass an existing object it has to be the specified type in this case Offer.
It looks like you are trying to automatically fill the publisher field with the currently logged in user. In order to do this you need to manually set the publisher field to an instance of User.
If you intend for the form to create a new Offer in the database do this
offerform = SendOfferForm(request.POST)
If you are trying to update a current offer THEN you would need to pass an instance object into the form
offerform = SendOfferForm(request.POST, instance=someOffer)
To manually add the user field call save on your form with commit=False this will return an offer object WITHOUT saving to the DB. At this point you have a chance to customize the data in object and then save.
offer = offerform.save(commit=False)
offer.publisher = request.user.id
offer.save()
All of this is explained in more detail in the django documentation
ModelForm documentation
My problem is similar to how to edit model data using django forms, but I'm not able to solve it.
I would like to get an form with prefielled fields and to allow user to edit them.
I believe my problem is in views.py file, but unfrotuntely I'm not able to solve it.
models.py
from django.db import models
class Item(models.Model):
product = models.CharField(max_length=150)
quantity = models.DecimalField(max_digits=8, decimal_places=3)
price = models.DecimalField(max_digits=7, decimal_places=2)
purchase_date = models.DateTimeField()
warranty = models.DecimalField(max_digits=4, decimal_places=1)
comment = models.TextField()
forms.py
from django import forms
from items.models import Item
class EditItemForm(forms.ModelForm):
class Meta:
model = Item
fields = ('product','quantity', 'price', 'purchase_date', 'warranty', 'comment')
urls.py
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(r'^show_all/$', 'items.views.items'),
url(r'^(?P<item_id>\d+)/$', 'items.views.item'),
url(r'^edit/(?P<item_id>\d+)/$', 'items.views.edit'),
)
edit.html
<form action="/items/edit/" method="post" class="form horizontal well">{% csrf_token %}
{{ form.as_p }}
<imput type="submit" class="btn btn-inverse" value="Aktualizuj">
</form>
views.py
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from items.models import Item
from decimal import Decimal
from django.core.context_processors import csrf
from items.forms import EditItemForm
def edit(request):
if request.method == 'POST':
form = EditItemForm(request.POST, instance=request.item)
if form.is_valid():
form.save()
return HttpResponseRedirect('/items/show_all/')
else:
form = EditItemForm(instance=item)
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('edit.html', args)
Above code is resulting this message:
TypeError at /items/edit/1/
edit() got an unexpected keyword argument 'item_id'
Can you please help me?
Django 1.6, Python 3.4
You've imagined an attribute called request.item. There's no such thing. You need to get the item from the database, via the ID passed into the function as alecxe showed.
def edit(request, item_id):
item = Item.objects.get(pk=item_id)
if request.method == 'POST':
form = EditItemForm(request.POST, instance=item)
edit() view should allow a keyword argument item_id:
def edit(request, item_id=None):
if request.method == 'POST':
...
It's taking me way to long to make this simple form. Almost there but when I submit I get the NoneType error
views.py:
from djangoproject1.authentication import forms
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
def main(request):
rf = forms.RegisterForm()
pf = forms.ProfileForm()
return render_to_response("authentication/index.html", {'form1': rf, 'form2':pf})
def register(request):
if request.method == 'POST':
rf = forms.RegisterForm(request.POST)
pf = forms.ProfileForm(request.POST)
if rf.is_valid() and pf.is_valid():
newuser = User(username=rf.cleaned_data['username'],email=rf.cleaned_data['email']) # this is the offending line
newuser.set_password(rf.cleaned_data['password'])
newuser.save()
profile = pf.save(commit=False)
profile.user = newuser
profile.save()
return HttpResponseRedirect("/register-success/")
else:
return main(request)
forms.py:
from django import forms
from djangoproject1.authentication.models import UserProfile
class RegisterForm(forms.Form):
username = forms.CharField(min_length=6,max_length=15)
password = forms.CharField(min_length=6,max_length=15,widget = forms.PasswordInput())
cpassword = forms.CharField(label='Confirm Password',widget = forms.PasswordInput())
email = forms.EmailField(label='E-mail Address')
def clean(self):
if self.cleaned_data['cpassword']!=self.cleaned_data['password']:
raise forms.ValidationError("Passwords don't match")
class ProfileForm(forms.ModelForm):
phonenumber = forms.CharField(label='Phone Number')
class Meta:
model = UserProfile
exclude = ('user')
Stack trace:
Environment:
Request Method: POST
Request URL: http://localhost:8000/register/
Django Version: 1.2.1
Python Version: 2.7.0
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'djangoproject1.authentication']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware')
Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
100. response = callback(request, *callback_args, **callback_kwargs)
File "C:\Users\jec23\My Java Projects\djangoproject1\src\djangoproject1\..\djangoproject1\authentication\views.py" in register
21. newuser = User(username=rf.cleaned_data['username'],email=rf.cleaned_data['email'])
Exception Type: TypeError at /register/
Exception Value: 'NoneType' object is not subscriptable
Your clean method in the forms.py should return the self.cleaned_data, if it doesn't raise an error.
Currently, it is returning None (as you are not returning anything explicitly)
Going by the contents of this line:
newuser = User(username=rf.cleaned_data['username'],email=rf.cleaned_data['email'])
it seems to me that the form instance rf doesn't have a cleaned_data field. The 'NoneType' object is unsubscriptable error can be raised when you are trying to access cleaned_data like you would access a dictionary but cleaned_data is actually None.
To check (rather clumsily) add a print statement before the offending line:
print rf.cleaned_data
OK. On closer look this is the most likely culprit:
def clean(self):
if self.cleaned_data['cpassword']!=self.cleaned_data['password']:
raise forms.ValidationError("Passwords don't match")
Clean methods should return cleaned_data explicitly. Since this one is not, it causes an error.