I am creating a simple application, successfully created for a single user, but I want to develop for multiple users, but unable to do so... i.e. user A can create his task and save in the database. similar B user can create tasks and store in the database. and each can see their own tasks I am newbie unable to proceed with the creation of instance can someone please guide me or point me to a blog ( searched online but no help ) I already asked this question however i was not clear ( django each user needs to create and view data Issue) hope now I am clear.
My model :
from django.contrib.auth.models import User, AbstractUser
from django.db import models
# Create your models here.
from django.db.models import Sum, Avg
class Task(models.Model):
user = models.ForeignKey(User, null=True,on_delete=models.CASCADE)
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True,auto_now=False,blank=True)
purchase_date = models.DateField(auto_now_add=False,auto_now=False,blank=True,null=True)
price = models.FloatField(max_length=5,default='0.00',editable=True)
def __str__(self):
return self.title
#classmethod
def get_price_total(cls):
total = cls.objects.aggregate(total=Sum("price"))['total']
print(total)
return total
Views
def createTask(request):
form = TaskForm()
if request.method =='POST':
form=TaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('query')
context = {'form':form}
return render(request,'tasks/create.html',context)
def display(request):
# tasks = Task.objects.all()
tasks = request.user.task_set.all()
form = TaskForm()
if request.method =='POST':
if form.is_valid():
form.save()
return redirect('/')
# tasks= task.objects.all()
print("tasks",Task.get_price_total)
context = {'tasks':tasks,'form':form,'Totalprice':Task.get_price_total}
return render(request,'tasks/products.html',context)
urls
from django.urls import path
from . import views
urlpatterns = [
#path('', views.index, name="list"),
path('', views.query, name="query"),
path('create/', views.createTask, name="create"),
path('update_task/<str:pk>/', views.updateTask, name="update_task"),
path('register/', views.registerPage,name="register"),
path('login/', views.loginPage,name="login"),
path('logout/', views.logoutUser,name="logout"),
path('delete/<str:pk>/', views.deleteTask, name="delete"),
path('query/', views.query, name="query"),
path('products/', views.display, name="products"),
path('search/', views.showresults, name="search"),
]
Error (output)
Internal Server Error: /products/
Traceback (most recent call last):
File "C:\Users\s5114509\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\s5114509\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 124, in _get_response
raise ValueError(
ValueError: The view tasks.views.display didn't return an HttpResponse object. It returned None instead.
[21/Oct/2020 14:35:59] "GET /products/ HTTP/1.1" 500 60680
From what I heard it sounds lke you want to save a task when a user creates one. You don't want to include the user field in the form. You have to first get the model instance returned by the TaskForm.save() method. Now you have to assign the user field to the request.user since the user is authenticated. Here is how you can achieve that.
def createTask(request):
form = TaskForm()
task = None
if request.method =='POST':
form=TaskForm(request.POST)
if form.is_valid():
#Just get the Task instance do not make any commitments to database
task = form.save(commit=False)
#Now update the user
task.user = request.user
#Finally save to database
task.save()
return redirect('query')
context = {'form':form}
return render(request,'tasks/create.html',context)
On display you are getting an error because you are return a response only when a POST request is made. Check you identation and correct it. Identation mean scope in python. Check I have modified you code
def display(request):
#tasks = Task.objects.all()
tasks = request.user.task_set.all()
form = TaskForm()
if request.method =='POST':
if form.is_valid():
form.save()
return redirect('/')
#tasks= task.objects.all()
print("tasks",Task.get_price_total)
context = {'tasks':tasks,'form':form,'Totalprice':Task.get_price_total}
return render(request,'tasks/products.html',context)
Take a look at python identation
Related
I want to count how may files the user has uploaded.
I have added signals.py
from django.dispatch import Signal
upload_completed = Signal(providing_args=['upload'])
And summary.py
from django.dispatch import receiver
from .signals import upload_completed
#receiver(charge_completed)
def increment_total_uploads(sender, total, **kwargs):
total_u += total
to my project.
My views upload
#login_required
def upload(request):
# Handle file upload
user = request.user
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.uploaded_by = request.user.profile
upload_completed.send(sender=self.__class__, 'upload')
#send signal to summary
newdoc.save()
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('upload'))
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the upload page
documents = Document.objects.all()
# Render list page with the documents and the form
return render(request,'upload.html',{'documents': documents, 'form': form})
This effort does not work.I got
upload_completed.send(sender=self.__class__, 'upload')
^
SyntaxError: positional argument follows keyword argument
I found signal example testing-django-signals
from .signals import charge_completed
#classmethod
def process_charge(cls, total):
# Process charge…
if success:
charge_completed.send_robust(
sender=cls,
total=total,
)
But it seems to me that classmethod would not work in my case
How to fix my method?
You don't need the 'uploads' argument for the send() method.
But a tip, if you're planning on a persistent count of the number of file uploads (which I assume you most likely are), then I think you should create a new model so that you can save it in your database.Then you can update that model every time a Document model is saved.
And I suggest you have a look at post_save. Have a nice day coding!
I'm using Django 2.0
I have two modesl course and chapter
I want to pass course.pk in CreateView of chapter since chapter is related to course.
This is my urls.py
from django.urls import path
from courses.views import Courses, NewCourse, CourseView, NewChapter
app_name = 'course'
urlpatterns = [
path('all', Courses.as_view(), name='list'),
path('new', NewCourse.as_view(), name='new'),
path('<pk>/detail', CourseView.as_view(), name='detail'),
path('<course_id>/chapter/add', NewChapter.as_view(), name='new_chapter')
]
and NewChapter(CreateView)
class NewChapter(CreateView):
template_name = 'courses/chapter/new_chapter.html'
model = Chapter
fields = ['name']
def get_context_data(self, **kwargs):
context = super(NewChapter, self).get_context_data(**kwargs)
course = Course.objects.get(pk=kwargs['course_id'])
if course is None:
messages.error(self.request, 'Course not found')
return reverse('course:list')
return context
def form_valid(self, form):
form.instance.created_by = self.request.user
form.instance.course = Course.objects.get(pk=self.kwargs['course_id'])
form.save()
I also want to carry on validation if the Course with passed course_id exists or not. If it does not exists user will be redirected back otherwise he will be able to add chapter to it.
But it is giving error as
KeyError at /course/9080565f-76f4-480a-9446-10f88d1bdc8d/chapter/add
'course_id'
How to access parameters of path url in view?
You need to use self.kwargs, not kwargs.
course = Course.objects.get(pk=self.kwargs['course_id'])
I was using the q&a at
Get Primary Key after Saving a ModelForm in Django.
It's exactly on point with what I need to do.
I have the following model:
class meetingEvent(models.Model):
'''
A meeting event
'''
name = models.CharField(max_length=64, help_text="a name for this meeting")
account_number = models.ForeignKey(account)
meeting_type = models.ForeignKey(meetingType)
meeting_group = models.ForeignKey(meetingGroup)
start_time = models.DateTimeField(help_text="start time for this event")
end_time = models.DateTimeField(help_text="end time for this event")
created_time = models.DateTimeField(auto_now_add=True)
listed_products = models.ForeignKey(product)
additonal_notes = models.TextField(help_text="additional notes for this meeting")
def __unicode__(self):
return self.name
I have the following form:
class meetingEventForm(forms.ModelForm):
"""
to create a new meeting event.
"""
portal_user = forms.CharField(help_text="username to access portal data")
portal_pass = forms.CharField(widget=forms.PasswordInput, help_text="password to add access portal data")
def save(self, commit=True):
super(meetingEventForm, self).save(commit=commit)
class Meta:
model = meetingEvent
I have the following view:
def meeting_event(request):
if request.method == 'POST':
form = meetingEventForm(request.POST)
if form.is_valid():
new_agenda=form.save()
return HttpResponseRedirect(reverse('agenda_detail', args=(new_agenda.pk,)))
else:
form = meetingEventForm()
return render_to_response('agendas/event.html',{'form':form,}, context_instance=RequestContext(request))
I've confirmed that this makes it into the database cleanly.
However, I get the following error:
Traceback:
File "/usr/lib/python2.6/site-packages/Django-1.5.2-py2.6.egg/django/core/handlers/base.py" in get_response
115. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python2.6/site-packages/Django-1.5.2-py2.6.egg/django/contrib/auth/decorators.py" in _wrapped_view
25. return view_func(request, *args, **kwargs)
File "/var/www/html/tamtools/agendas/views.py" in meeting_event
44. return HttpResponseRedirect(reverse('agenda_detail', args=(new_agenda.pk,)))
Exception Type: AttributeError at /agendas/add/
Exception Value: 'NoneType' object has no attribute 'pk'
Has something changed in Django 1.5 that I don't know about? new_agenda should be a meetingEventForm type, shouldn't it?
You overwrite save methid in modelform, but you forgot to return model.
return super( ....
You don't need to override the ModeForm save method, since you aren't doing anything special with it. Your ModelForm should look like:
class MeetingEventForm(forms.ModelForm):
"""
to create a new meeting event.
"""
class Meta:
model = meetingEvent
I also changed the class name to conform with the Python style guide.
You also have two extra fields in the form that have nothing to do with your model. There could be two reasons - one, you need to save these fields in another model, or the second option is that you want someone to authorize themselves before they can add a new event.
Since the second one seems more plausible, restrict access to the form from your view:
from django.contrib.auth.decorators import login_required
from django.shorcuts import render, redirect
#login_required()
def meeting_event(request):
form = MeetingEventForm(request.POST or {})
context = {'form': form}
if request.method == 'POST':
if form.is_valid():
new_agenda = form.save()
return redirect('agenda_detail', args=(new_agenda.pk,))
else:
return render(request, 'agendas/event.html', context)
else:
return render(request, 'agendas/event.html', context)
As this is a common task, and you are using django 1.5, why not use the generic class based views?
Your code will be reduced, and you don't have to worry about the mundane details:
First, in your views.py, create a class that inherits from the generic CreateView which is used to display a model form for a model, let the user fill it in, and save the details:
from django.views.generic.edit import CreateView
class CreateMeetingRequest(CreateView):
template_name = 'agendas/event.html'
model = meetingRequest
Now, to map the view to a url, we add it to urls.py. Since we also want the user to be logged in before they can add a meeting request - the login_required decorator takes care of that for us. It will check if the user is logged in - if not, redirect the user to a login form and once they have logged in, redirect them back to the form:
from django.contrib.auth.decorators import login_required
from .views import CreateMeetingRequest
urlpatterns = patterns('',
# your other views
url(r'meeting-request/add/$',
login_required(CreateMeetingRequest.as_view()), name='add-meeting-req'),
)
Finally, we need to tell the view where to go once the form is successful. CreateView will check if the model has a get_absolute_url method, and call that. So in your models.py:
from django.core.urlresolvers import reverse
class meetingRequest(models.Model):
# your normal fields
def get_absolute_url(self):
return reverse('agenda_detail', args=(self.pk,))
Update
I tried replacing everything in my custom manager with the following:
def create_user(self, username, email):
return self.model._default_manager.create(username=username)
And that throws an error. I then tried returning the User from my custom user manager and I get 'Cannot assign "": "UserSocialAuth.user" must be a "Barbuser" instance.' thrown from associate_user. It comes from the bowels of django.db.models.fields.related.py. Basically, I'm stuck with knowing how to correctly create users from my custom model mgr. I was going directly off of the docs which lead me to copying everything from django's built in ModelManager. Help?
Update
I'm having trouble configuring django-social-auth. I've been at this for 3-4 days and I'm getting ready to throw in the towel. I have a working existing user registration app installed and I then installed and followed along with the docs on django-social-auth github site. I added the following to my settings.py
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
'polls',
'barbuser',
'social_auth',
)
AUTHENTICATION_BACKENDS = (
'social_auth.backends.facebook.FacebookBackend',
'django.contrib.auth.backends.ModelBackend',
)
FACEBOOK_APP_ID = os.environ.get('FACEBOOK_APP_ID')
FACEBOOK_API_SECRET = os.environ.get('FACEBOOK_SECRET')
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'social_auth.context_processors.social_auth_by_type_backends',
)
#SOCIAL_AUTH_ENABLED_BACKENDS = ('facebook',)
SOCIAL_AUTH_DEFAULT_USERNAME = 'new_social_auth_user'
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/profile/'
LOGIN_ERROR_URL = '/login-error/'
SOCIAL_AUTH_USER_MODEL = 'barbuser.Barbuser'
My models.py looks like:
from datetime import date
from django.db import models
from django.contrib.auth.models import User
from django.db.models import BooleanField
from django.db.models.fields import DateTimeField
from django.utils import timezone
from django.utils.crypto import get_random_string
class BarbuserManager(models.Manager):
#classmethod
def normalize_email(cls, email):
"""
Normalize the address by converting the domain part of the email address to lowercase.
"""
email = email or ''
try:
email_name, domain_part = email.strip().rsplit('#', 1)
except ValueError:
pass
else:
email = '#'.join([email_name, domain_part.lower()])
return email
def create_user(self, username, email=None, password=None):
"""
Creates and saves a User with the given username, email and password.
"""
email = 'you#email.com' if email.strip() == '' else email
now = timezone.now()
if not username:
raise ValueError('The given username must be set')
email = BarbuserManager.normalize_email(email)
user = User(username=username, email=email,
is_staff=False, is_active=True, is_superuser=False,
last_login=now, date_joined=now)
user.set_password(password)
user.save()
barbuser = Barbuser(user=user, birthday=date.today(), last_login=user.last_login, name=username)
barbuser.save()
return barbuser
def create_superuser(self, username, email, password):
u = self.create_user(username, email, password)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
def make_random_password(self, length=10,
allowed_chars='abcdefghjkmnpqrstuvwxyz'
'ABCDEFGHJKLMNPQRSTUVWXYZ'
'23456789'):
""" Generates a random password with the given length and given allowed_chars. Note that the default value of allowed_chars does not have "I" or "O" or letters and digits that look similar -- just to avoid confusion. """
return get_random_string(length, allowed_chars)
def get_by_natural_key(self, username):
return self.get(username=username)
class Barbuser(models.Model):
user = models.OneToOneField(User)
username = models.CharField(max_length=200)
last_login = DateTimeField(blank=True)
is_active = BooleanField(default=True)
birthday = models.DateField()
name = models.CharField(max_length=200)
objects = BarbuserManager()
def __init__(self, *args, **kwargs):
me = super(Barbuser, self).__init__(*args, **kwargs)
barbuser = me
return me
def __unicode__(self):
return self.name
def is_authenticated(self):
return self.user.is_authenticated()
I've updated my urls.py to include 'social_auth.urls' and after authentication the user is redirected to ViewProfile view from my views.py:
# Create your views here.
from barbuser.forms import RegistrationForm, LoginForm
from barbuser.models import Barbuser
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template.context import RequestContext
def create_Barbuser(form):
user = User.objects.create_user(form.cleaned_data['username'], form.cleaned_data['email'], form.cleaned_data['password'])
user.save()
barbuser = Barbuser(user=user, name=form.cleaned_data['name'], birthday=form.cleaned_data['birthday'])
barbuser.save()
def process_form(form, request_context):
if form.is_valid():
create_Barbuser(form)
return HttpResponseRedirect('/profile/')
else:
return render_to_response('register.html', {'form': form}, context_instance=request_context)
def render_blank_registration_form(request):
'''When the user is not submitting the form, show them the blank registration form.'''
form = RegistrationForm()
context = {'form': form}
return render_to_response('register.html', context, context_instance=RequestContext(request))
def BarbuserRegistration(request):
"""
Handles the registration of new Barbwire users.
"""
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == "POST":
return process_form(RegistrationForm(request.POST), RequestContext(request))
else:
return render_blank_registration_form(request)
def LoginRequest(request):
'''
Handles Login requests.
'''
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
barbuser = authenticate(username=username, password=password)
if barbuser is not None:
login(request, barbuser)
return HttpResponseRedirect('/profile/')
else:
return render_to_response('login.html', {'form' : form}, context_instance=RequestContext(request))
else:
return render_to_response('login.html', {'form' : form}, context_instance=RequestContext(request))
else:
form = LoginForm()
return render_to_response('login.html', {'form' : form}, context_instance=RequestContext(request))
def LoginError(request):
return render_to_response('login.html', {'form' : LoginForm()}, context_instance=RequestContext(request))
def LogoutRequest(request):
logout(request)
return HttpResponseRedirect('/')
def ViewProfile(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/login/')
else:
return render_to_response('profile.html',{'barbuser' : request.user.barbuser }, context_instance=RequestContext(request))
My problem is 2-fold. When I add this extra stuff in my models.py:
def facebook_extra_values(sender, user, response, details, **kwargs):
return False
from social_auth.signals import pre_update
from social_auth.backends.facebook import FacebookBackend
pre_update.connect(facebook_extra_values, sender=FacebookBackend)
I get errors on server startup: assert isinstance(to, basestring), "%s(%r) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string %r" % (self.class._name_, to, RECURSIVE_RELATIONSHIP_CONSTANT)
AssertionError: ForeignKey(None) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string 'self'
When I remove it I can go thru the login with facebook flow but I get: AttributeError at /complete/facebook/
'NoneType' object has no attribute 'extra_data'
I'm not sure what I'm missing or where I've gone wrong. could somebody help explain where I'm going wrong?
Update
I've traced the problem in debug and apparently I'm getting an IntegrityError in social_auth.backends.pipeline.social.py in the associate_user function when it tries "UserSocialAuth.objects.create". It then falls back into an Except block that calls social_auth_user() and this function returns None for the social_user. The IntegrityError I'm getting is:
insert or update on table "social_auth_usersocialauth" violates foreign key constraint "social_auth_usersocialauth_user_id_fkey"
DETAIL: Key (user_id)=(17) is not present in table "auth_user".
I'm not familiar enough to know how, where or why to associate a social_user with the user created in my CustomUserManager in my models.py. Also I've removed the facebook_extra_values, extra imports, and the preupdate.connect stuff from the bottom of my models.py since I really don't understand what it does or what it's for. I was merely copying things from the example app trying to fix my first problem with the missing association. Help?
Update
The first problem — the ForeignKey error — is caused by a circular import. The solution is easy and follows convention. Take that signal registering code block at the end of models.py and move it to a new file called barbuser/signals.py. Then in barbuser/__init__.py put the line, from .signals import *
I haven't run your code far enough to get your second error — 'NoneType' object has no attribute 'extra_data' — but I found a couple other issues.
Remove the SOCIAL_AUTH_ENABLED_BACKENDS setting from settings.py. I'm not sure where you got that from, but it's not in the documentation for the current social-auth 0.7.0. It's not in the social_auth code either. Probably an old setting.
You reference a non-existent context processor in settings.py (social_auth_login_redirect). Again, maybe an old function. Make sure you are running the newest social-auth (available through PyPi with pip install django-social-auth). Also, use only the context processors you need, never all of them. (Context processors add variables to the template context. If you aren't using the social_auth variable in your templates then you don't need any of the social-auth context processors.) This is important because two of the processors conflict with each other. From the documentation,
social_auth_backends and social_auth_by_type_backends don't play nice
together.
Make sure you've run ./manage.py syncdb to setup the database for the social-auth Model. If there is no database table for the model, that would cause "UserSocialAuth.objects.create()" to break.
Last thought, Django doesn't like the type of thing you are doing defining your own User Model. It's best to leave auth.User alone and make a UserProfile.
UPDATE
Check your database structure; I suspect the indexes are incorrect. Better yet, just delete the three social_auth_* tables and syncdb again. The UserSocialAuth table has a ForeignKey Constraint to the User Model. It should be mapping "user_id" to "Barbuser.id" but if the table was created before you set the settings.py/SOCIAL_AUTH_USER_MODEL value, then the table will be forever broken because SocialAuth defaulted to Django's Auth.User when the initial SQL was run. Make sense? Anyway, just recreate the tables now that you have Social Auth configured.
Note: Your recent experiment using self.model._default_manager.create() isn't accomplishing anything. "self" is a BarbuserManager; "model" is a Barbuser; "_default_manager" is back to a BarbuserManager. Why? "Barbuser.objects" is the default manager for the Model.
Oh, and you had it correct the first time. BarbuserManager.create_user() needs to return a Barbuser.
I know this is an easy question, I am just not getting something...so thank you for your patience and advice.
I have a view that asks a user to register to use our app. The data he/she submits is stored in a database and he is sent off to another page to set up the application:
#views.py
def regPage(request, id=None):
form = RegForm(request.POST or None,
instance=id and UserRegistration.objects.get(id=id))
# Save new/edited pick
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect('/dev/leaguepage/')
user_info = UserRegistration.objects.all()
context = {
'form':form,
'user_info' :user_info,
}
return render(request, 'regpage.html', context)
Rather than sending ALL users to the same page '/dev/leaguepage/', I need to send each user to his own page based on the PK in the database like: '/dev/PrimaryKey/' I am not sure how to make this happen either on the views file or in the URLs.py file:
#urls.py
from django.conf.urls.defaults import patterns, include, url
from acme.dc_django import views
urlpatterns = patterns('',
url(r'^leaguepage/$','acme.dc_django.views.leaguePage'),
url(r'^$', 'acme.dc_django.views.regPage'),
)
Thank you for your help!
dp
Updated code:
#url
url(r'^user/(?P<id>\d+)/$','acme.dc_django.views.leaguePage', name="league_page"),
#view
def regPage(request, id):
form = RegForm(request.POST)
# Save new/edited pick
if request.method == 'POST' and form.is_valid():
form.save()
return HttpResponseRedirect(reverse('league_page', kwargs={'id' :id}))
#return HttpResponseRedirect('/dev/leaguepage/')
user_info = UserRegistration.objects.all()
context = {
'form':form,
'user_info' :user_info,
}
return render(request, 'regpage.html', context)
You can do a reverse lookup on your leaguePage to do your redirect, passing in the values you need to resolve the pattern. You'll need to add a name to the URL pattern you want to reverse, but basically the syntax is:
return HttpResponseRedirect(reverse('my_detail', args=(), kwargs={'id' : id}))
Example URL pattern and view:
urlpatterns = patterns('my_app.views',
url(r'^my-pattern/(?P<id>\d+)/$', 'my_action', name='my_detail'),
)
def my_action(request, id):
#do something
Hope that helps you out.