I have an app called profiles which just leverages the django-registration-redux module. I am trying to create a form that allows the user to edit it, with the information they already have in it, but it isn't showing up. I can get it to show up without the information, but not the profile information that already exists.
urls.py
from django.conf.urls import url
from profiles import views
urlpatterns = [
url(r'^(?P<username>[-\w]+)/$', views.single, name='profile_single'),
url(r'^(?P<username>[-\w]+)/edit/$', views.edit, name="profile_edit"),
]
views.py
def edit(request, username):
instance = Profile.objects.get(user=username)
# It would be good to have an in depth understanding of what the actual request module does
if request.user == instance.user:
form = ProductForm(request.POST or None, instance = instance)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.slug = slugify(form.cleaned_data['title'])
profile.save()
return HttpResponseRedirect('/user/%s'%(user.username))
return render_to_response("profiles/edit.html", locals(), context_instance=RequestContext(request))
The error that I am recieving is:
Exception Value: invalid literal for int() with base 10: 'admin'
You need to check username field of User model.
To do that, replace the following line:
instance = Profile.objects.get(user=username)
with:
instance = Profile.objects.get(user__username=username)
Related
I checked the other posts on here that have the attribute error that I have, but they seem to be for different reasons. I am currently requesting the information from a form for users to update a project page. Then, if the form is valid, I am saving the form, saving the project, then trying to return redirect to the project page; however, when I click the button, the computer renders the error page. I will attach my forms.py, views.py, models.py, and urls.py:
Views.py for the update section:
#wraps(function)
def wrap(request, *args, **kwargs):
user = request.user
name = kwargs.get('name')
if uProjects.objects.filter(project=Project.objects.get(name=name), user=user, ifAdmin=True).exists():
return function(request, *args, **kwargs)
else:
return HttpResponseRedirect('/')
return wrap
#admin_check
def update(request, name):
project = Project.objects.get(name = name)
if request.method == "POST":
pr_form = ProjectUpdateForm(request.POST,
request.FILES,
instance=project)
#if is_admin in Member == True: #need to authenticate user, access user permissions, if user has permission:
if pr_form.is_valid():
pr_form.save()
messages.success(request, f'This project has been updated.')
request.project.save()
return redirect('project')
else:
pr_form = ProjectUpdateForm(instance=project)
context = {
'pr_form': pr_form
}
return render(request, 'projects/updateproject.html', context)
forms.py for ProjectUpdateForm:
class ProjectUpdateForm(forms.ModelForm):
class Meta:
model = Project
fields=['name', 'department', 'department','bPic', 'logo',
'department', 'purpose', 'projectTag', 'lookingFor', 'recruiting']
urls.py
from projects import views as p
path('project/<str:name>/', p.project, name='project'),
path('editproject/<str:name>/', p.update, name="editproject"),
Thanks, please let me know what I can do.
Your error is in line request.project.save(), request doesn't have project attribute.
And actually you don't need to call save() method for project.
Because ProjectUpdateForm is the ModelForm and ModelForm.save() (Django docs) method will create a new instance of the specified model or update assigned instance.
#admin_check
def update(request, name):
project = Project.objects.get(name = name)
if request.method == "POST":
pr_form = ProjectUpdateForm(request.POST,
request.FILES,
instance=project)
#if is_admin in Member == True: #need to authenticate user, access user permissions, if user has permission:
if pr_form.is_valid():
# save() returns an instance object, you can use it to manipulate your object.
instance = pr_form.save()
messages.success(request, f'This project has been updated.')
# YOUR ERROR IS ⬇️ HERE request doesn't have project attribute
# request.project.save()
# redirect with arguments
return redirect('project', name=instance.name)
...
Also your redirect must contain argument name, because your project url required name attribute:
redirect('project', name=instance.name)
I am trying to get or create an object when another one is created with a form :
def index(request, log_id, token):
log = get_object_or_404(LogBook, pk=log_id)
logmessages = LogMessage.objects.filter(logbook=log_id)
form = CreateLogMessage(request.POST)
if request.method == "POST":
if form.is_valid():
instance = form.save(commit=False)
instance.reported_by = request.user
instance.logbook = log
instance.save()
logdone = LogDone.objects.get_or_create(logmessage=logmessages, done_status=False)
I am trying to figure out a way to get the id of the logmessage created to pass it to my logdone instance.
I don't find a way to do it so far, any help will be appreciate it.
The object that is created is the instance, you thus can implement this as:
from django.shortcuts import redirect
def index(request, log_id, token):
log = get_object_or_404(LogBook, pk=log_id)
if request.method == 'POST':
form = CreateLogMessage(request.POST)
if form.is_valid():
form.instance.reported_by = request.user
form.instance.logbook = log
instance = form.save()
logdone = LogDone.objects.get_or_create(
logmessage=instance,
done_status=False
)
return redirect('name-of-some-view')
else:
form = CreateLogMessage(request.POST)
…
Since your form creates a new object every time, this however always create an object.
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
I have a form and a model, in my views I take the data from form and use it to delete the object from my model, but it does not delete the object at all, even though if I use the shell and create the same query set with the same syntax it works. What am I missing here?? Thx
Code from views:
form = SecondForm()
query_list = DictWord.objects.all()
dict_DictWord = {'words': query_list,"form":form}
if request.method == "POST":
form = SecondForm(request.POST)
if form.is_valid():
##Does not delete the object from models
data = form.cleaned_data['name']
DictWord.objects.filter(name=data).delete()
return render(request, 'appone/index.html', context = dict_DictWord)
else:
messages.error(request, "Error")
return render(request,'appone/index.html',context=dict_DictWord)
But if I use manage.py shell, I import my model and this syntax works, and it returns the dict with the deleted object:
from app.models import DictWord
DictWord.objects.filter(name="SomeName").delete()
#try this
record=DictWord.objects.get(name=data)
record.delete()
return render(request, 'appone/index.html', context = dict_DictWord)
I have a very simple index page view, from which the user can fill in a login popup, which sends a post request to /login
def index(request):
"""Shows list of studyspaces, along with corresponding 'busyness' score"""
context = {'study_space_list': StudySpace.objects.order_by('-avg_rating')}
if request.user.is_authenticated():
context['user'] = request.user
else:
context['login_form'] = LoginForm()
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
If the login is valid it simply redirects to the index page, this works fine.
The login view looks as follows:
def user_login(request):
form = LoginForm(request.POST)
if request.method == 'POST' and form.is_valid():
user = form.login(request)
if user:
login(request, user)
return redirect(reverse('spacefinder:index'))
# Load the context all over again
context = {
'study_space_list': StudySpace.objects.order_by('-avg_rating')
}
context['login_form'] = form
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
However when the login is incorrect I want to be able to refresh the page and show the login form errors inside the index template (in the login popup)
I'm actually able to achieve this with the above code, but I'm unhappy with the solution for the following reasons:
I have to manually fetch the context all over again, e.g user/student forms and studyspaces, this goes against the DRY principle
When the page is refreshed the url is localhost:8000/spacefinder/login
Screenshot of behaviour here
I'm wondering if there's somehow a way to use redirect to reload the index page and somehow pass errors from my login_form, e.g. something like:
return redirect('spacefinder:index', {'login_form': form})
I've looked into using messages to pass form validation errors, but struggled to get this working since Validation Errors are thrown inside forms.py, and I'm unable to fetch the request instance from inside a ModalForm to properly create a message
You are doing it the wrong way around.
Consider these prerequisites:
entry point to your page is the index view
the index view must only be accessible by authenticated users
the login view allows both methods GET and POST and is accessible to anonymous users only
The reason to use Django is to make use of all the features that it offers, and that includes handling of the above (because that is what most pages need, not only you).
To set it up correctly you need to define your urls.py like this:
from django.contrib.auth.decorators import login_required
urlpatterns = [
....
url('^login/$', user_login, 'login'),
url('^/$', login_required(index), 'index'),
....
]
In your settings/base.py (or settings.py if you have no environment differentiation) tell Django how to redirect users:
LOGIN_URL = reverse_lazy('login')
LOGIN_REDIRECT_URL = reverse_lazy('index')
https://docs.djangoproject.com/en/1.9/ref/settings/#login-url
https://docs.djangoproject.com/en/1.9/ref/settings/#login-redirect-url
Simplify your index view:
def index(request):
"""Shows list of studyspaces, along with corresponding 'busyness' score"""
context = {'study_space_list': StudySpace.objects.order_by('-avg_rating')}
if request.user.is_authenticated():
context['user'] = request.user
else:
return HttpResponseForbidden() # prevented by Django, should never happen
return render(request, 'spacefinder/index.html', context)
Let the user_login view deliver the empty login form:
#require_http_methods(["GET", "POST"])
def user_login(request):
params = getattr(request, request.method)
form = LoginForm(params)
if request.method == 'POST' and form.is_valid():
user = form.login(request)
if user:
login(request, user)
return redirect(reverse('spacefinder:index'))
# Load the context for new form or form with errors
context = {
'study_space_list': StudySpace.objects.order_by('-avg_rating')
}
context['login_form'] = form
context['user_form'] = UserForm()
context['student_form'] = StudentForm()
return render(request, 'spacefinder/index.html', context)
You have not presented any code that handles the UserForm or the StudendForm. You would need to add that to the user_login view, as well - if this is something that all users should fill in every time they login. Otherwise use a different view.
It's worth looking at modules like allauth. They might spare you some work when it comes to allowing users to login with their e-mail addresses, ascertain that e-mail addresses are unique in the system etc.
I am new to Django and web programming in general, please don't make the answers too complicated. I have looked up the documentation and questions in here but I can't wrap my head around it.
I have a form and after validating and saving the model to the database I want to redirect the user to a new page. My question is, how do I do it with HttpResponseRedirect(or even the shortcut redirect) correctly, because it redirects the view correctly, the url pattern gets called but when it reaches the view in the views.py something goes array. Why doesn't the template change but the view does?
Can somebody tell me where I am wrong, and how to fix it?
views.py
class CreateSuccess(generic.ListView):
template_name = 'login/successReg.html'
def CreateUser(request):
if request.method == "POST":
form = CreateUserForm(request.POST)
if form.is_valid():
newUser = form.save()
return HttpResponseRedirect('sucess/')
else:
form = CreateUserForm()
return render(request, 'login/addUser.html', {'form':form})
urls.py
urlpatterns = patterns('',
url(r'^$', views.LoginIndex.as_view(), name='loginIndex'),
url(r'^create/', views.CreateUser, name='addUser'),
url(r'^authenticate/', views.LoginUser.as_view(), name='loginUser'),
url(r'^create/success/', views.CreateSuccess.as_view(), name='successReg'),
)
Try returning an reverse() object which constructs the required url for you
if form.is_valid():
newUser = form.save()
url = reverse('your_app:successReg') # Replace your_app with the name of your app
return HttpResponseRedirect(url)
More about reverse():
reverse(viewname)
viewname is either the function name (either a function reference, or
the string version of the name) which means that either you could make viewname a existing function in your views.py or either reference it by its string name in the urls.py
It's always recommended to do it in the form reverse('app_name : name_defined_in_urls')
Note: since your a beginner I dropped those optional args and kwargs parameters which are used if you want to redirect a user to dynamic webpage