I am new to django and i am trying to pass user instance from one view to another and then save data in model Category but i get this error:
ValueError at /bookmark/category/
Cannot assign "45": "Category.user" must be a "User" instance.
bookmark is the name of my application.
After registering a new user, he is redirected to another page where he selects category from a dropdown list. I wish to add this selected category in Category model with the same userid.
This is my views.py code:
def register(request):
if request.method == 'POST':
form = signUpForm(request.POST)
if form.is_valid():
user = form.save()
request.session['user'] = user.pk
return render(request,'category.html')
def get_category(request):
cname = request.POST.get("dropdown1")
user = request.session.get('user')
obj=Category(user=user,category=cname)
obj.save()
This is models.py file
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
user = models.ForeignKey(User)
category= models.CharField(max_length=100)
Can someone please guide if this is the right approach or something else is to be done?Thanks!
def get_category(request):
cname = request.POST.get("dropdown1")
user = request.session.get('user')
obj=Category(user_id=user,category=cname)
obj.save()
as user is a foreign key it needs an User Instance to get saved.
as you are having the id of the user you can use user_id for saving it
In addition to obj=Category(user_id=user,category=cname) there was also problem in my template.
I had written :
<select multiple = "dropdown1">
That is why i was getting Null constraint.
I modified it to
<select name = "dropdown1" multiple>
Related
i want that user can submit a particular form only once. Is it possible without any js,react.. actually by using django only ??
i have tried something like that --
def apply(request):
p=0
if request.method=="POST":
p=1
...do something..
else:
...do something...
i have tried to catch the value of p=1, and try to not return the html is it's submitted once , but each time reload makes the value of p=0.
i have to save the session ?? or what will be the right way to do this ?
can anyone suggest anything please?
I suggest adding a field name form_submitted as BooleanField to your User model(by abstracting the based User model) to check and see if that user submitted the form. You can get the current logged in user from request.user.
models.py:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
# also do this if you have custom user model
form_submitted = models.BooleanField(default=False)
class Meta:
db_table = "users"
views.py:
def apply(request):
if request.method=="POST":
user = request.user
if not user.form_submitted:
# save the form
user.form_submitted = True
user.save()
else:
# this user already submitted the form
so i'm making a generic "accounts" page in django. I've used the django-registration plugin, and currently have a (djang-standard) User object, as well as a UserProfile and UserProfileForm object.
This is a question of style, or best-practices, i suppose. Is what i'm planning "right" or is there a "better/recommended/standard way" to do this?
What i'm planning on doing is creating the UserProfile from the request.user ie:
form = UserProfileForm(instance=User)
(and sending that form to the view), and in the UserProfileForm:
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
def __init__(self,*args,**kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
if kwargs.has_key('instance'):
self.user = kwargs['instance']
where my UserProfile is pretty much like so:
class UserProfile(models.Model):
user = models.OneToOneField(User)
points = models.IntegerField(default=0) #how is the user going with scores?
and where User is of the django.contrib.auth.models variety.
Ok! The handling of the editing and saving will either be done via the mixin django stuff or, more likely because i haven't read up on mixins my own user-defined view that handles post and gets. But ignoring that - because i'm sure i should be using the mixins - is the above "right?" or are there suggestions?
cheers!
Take a look at user profiles on the django docs, the basics are listed there. You should also take a look at using a form in a view.
Some specific feedback:
You got the UserProfile model right, but you have to create an instance of one every time a new user is added (either through the admin interface or programmatically in one of your views). You do this by registering to the User post_save signal:
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
You should init the ModelForm with an instance of the UserProfile, not User. You can always get the current user profile with request.user.get_profile() (if you define AUTH_PROFILE_MODULE in settings.py). Your view might look something like this:
def editprofile(request):
user_profile = request.user.get_profile()
if request.method == 'POST':
form = UserProfileForm(request.POST, instance=user_profile)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/profile')
else:
form = UserProfileForm(instance=user_profile)
# ...
No need for the init override in your ModelForm. You will be calling it with a UserProfile instance, anyway. If you want to create a new user, just call the User constructor:
user = User()
user.save()
form = UserProfileForm(instance = user.get_profile())
# ...
So the problem is I have extended User model in django. and I have written views for it.
Here is my models code :-
class StudentProfile(User):
batch = models.CharField(max_length=10)
course = models.CharField(max_length=20)
date_of_birth = models.DateField()
answer = models.CharField(max_length=20)
contact = models.CharField(max_length=20)
here is my auth backend file :-
from quizapp.models import StudentProfile
class StudentAuthenticationBackend(object):
def authenticate(self, username=None, password=None):
try:
student = StudentProfile.objects.get(username=username)
if student.check_password(password):
return student
except StudentProfile.DoesNotExist:
pass
return None
def get_user(self, user_id):
try:
return StudentProfile.objects.get(pk=user_id)
except StudentProfile.DoesNotExist:
return None
And I have made changes in seetings.py
AUTHENTICATION_BACKENDS = (
'quizapp.backends.StudentAuthenticationBackend',
'django.contrib.auth.backends.ModelBackend',
)
I'm printing username,password and authentication user. This is what i got :-
When using django created superuser
>> a = authenticate(username="super",password="super")
>> print(a)
>> super
But when using user created by form,
>> b = authenticate(username="test",password="123")
>> print(b)
>> None
I have cross checked username and password and it's true.
So but in auth_user table, username is super and password is encrypted but for test user, username is user and password is 123.
So the problem must be django is taking 123 is encrypted password and using decrypted version of it to authenticate.
Is there any way to solve this?
I have used OneToOneField and added extra fields in StudentProfile model. Now I'm using forms and registering user with it.
This is the view code :-
def register_page(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
user = StudentProfile.objects.create(
username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
batch=form.cleaned_data['batch'],
first_name=form.cleaned_data['first_name'],
last_name=form.cleaned_data['last_name'],
course=form.cleaned_data['course'],
date_of_birth=form.cleaned_data['date_of_birth'],
secret_question=form.cleaned_data['secret_question'],
answer=form.cleaned_data['answer'],
contact=form.cleaned_data['contact']
)
return HttpResponseRedirect('/register/success/')
else:
form = RegistrationForm()
variables = RequestContext(request, {'form': form})
return render_to_response('registration/register.html',variables)
And I'm getting IntegrityError at /register/
null value in column "user_id" violates not-null constraint error.
Is there any way to fix this?
From the Django authenication docs section on storing additional information about users:
If you'd like to store additional information related to your users, Django provides a method to specify a site-specific related model -- termed a "user profile" -- for this purpose.
To make use of this feature, define a model with fields for the additional information you'd like to store, or additional methods you'd like to have available, and also add a OneToOneField named user from your model to the User model. This will ensure only one instance of your model can be created for each User.
So you shouldn't subclass User at all -- that's the root of your problem. Instead, you should create another model with a one-to-one relationship with User and add your fields there.
I'm working on an app that has three "profile" models types. Each of these models has a foreign key to the contrib.auth.models User model.
I would like to have a single sign on for each model type and provide a redirect via classmethod depending on which "profile" model type is related to the logged in user.
Here's some pseudo-code to illustrate what I would like to do:
from django.contrib.auth import authenticate, login
from django.http import HttpResponse, HttpresponseRedirect
from lib.forms import Loginform #extends the built-in AuthenticationForm
def login_user(request):
if request.method == 'POST':
form = LoginForm(data=request.POST)
if form.is_valid():
cleaned_data = form.cleaned_data
user = authenticate(username=cleaned_data.get('username'), \
password=cleaned_data.get('password'))
if user:
login(request, user)
#Determine the content type of the model related to the user
#get the correct redirect value from an #classmethod
#called: after_login_redirect for that type and...
return HttpResponseRedirect(klass.after_login_redirect())
else:
response = form.errors_as_json()
return HttpResponse(json.dumps(response, ensure_ascii=False), \
mimetype='application/json')
Is it possible to leverage the ContentTypes framework to do this? or am I better off just writing a class resolver that loops over an array of the "profile" classes? I'm not seeing a way I can do this with ContentTypes from the User class, unless someone knows a workaround.
Thanks in advance,
Brandon
[SOLVED]
So, what I ended up doing was creating a UserContentType junction model that looks like this:
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
class UserContentType(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
Then, I made a pre-save signal to fire a get or create if the instance of one of the three "profile" models I have doesn't have an id:
from django.contrib.contenttypes.models import ContentType
from lib.models import UserContentType
def set_content_type_for_user(sender, **kwargs):
instance = kwargs.get('instance')
content_type = ContentType.objects.get_for_model(instance)
user = instance.user
if not instance.id:
user_content_type, \
created = UserContentType.objects.get_or_create(user=user, \
content_type=content_type, \
defaults={'user' : user, 'content_type' : content_type})
Then, in my custom login view which is posted to via ajax, I can get the content type associated with the User instance and get the URL to redirect to from the 'after_login_redirect()' classmethod on that content type. :)
def login_user(request):
if request.method == 'POST':
form = LoginForm(data=request.POST)
if form.is_valid():
cleaned_data = form.cleaned_data
user = authenticate(username=cleaned_data.get('username', ''),
password=cleaned_data.get('password', ''))
if user:
login(request, user)
user_content_type = UserContentType.objects.get(user=user)
redirect_path =
user_content_type.content_type.\
model_class().after_login_redirect_path()
response = {'redirect_path' : redirect_path}
else:
response = form.errors_as_json()
return HttpResponse(json.dumps(response, \
ensure_ascii=False), mimetype='application/json')
This way, I don't have to monkeypatch User. I hope this helps someone out. If there's a way I can improve on this, I'd love to hear some ideas.
Thanks,
Brandon
What approach is the best way to make content-types restricted to a user in Django?
Let us say I want all users with the user-role "blogger" to have its own blog.
I have created a weblog app. How do I restrict it so that the user logged in can only post in his "own" blog, and how do I make views that shows only a user's blog?
First your blog entries has to be attached to user, so you know on whos blog display, it, right? models.py:
class BlogEntry(models.Model):
user = models.ForeignKey(User, related_name='blog_entries')
other_field_1 = ...
other_field_2 = ...
Next, skip it in ModelForm, forms.py:
class BlogEntryModelForm(forms.ModelForm):
class Meta:
exclude = ('user',)
Then, when user want to post entry you require he's logged, views.py:
#login_required
def post_blog_entry(request):
....
if request.method == 'POST':
form = BlogEntryModelForm(request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.user = request.user
new_entry.save()
When you want display some user blog, views.py:
def view_blog(request, blogger_name):
user = get_object_or_404(User, username=blogger_name)
entries = user.blog_entries.all()
User is django.contrib.auth.models.User
You can add custom role checking to views above to display 404 page or error page if user has no rights to create blog.
Optionally you can replace User from django.contrib.auth with your own User implementation but you'll have to write model, authentication and middleware for it as well...
I didnt try to implement this, but I found another soultion that worked very good. It was easy to implement and did everything i wanted.
Check it out...