I have 2 models
class User(models.Model):
email = models.CharField(max_length = 100)
password = models.CharField(max_length = 100)
class Authentication(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
token = models.CharField(max_length =50, null = True)
Here is the code I use for login in views.py
from user.models import User, Authentication
import uuid
from django.db.utils import IntegrityError
user = User.objects.get(pk = request.user.id)
token = uuid.uuid4().hex
try:
Authentication.objects.create(user = user, token = token)
except IntegrityError:
user.authentication.token = token
user.authentication.save()
return JsonResponse({'token':token})
The problem I meet here is everytime a user login, I will generate a new token and save in the database. The error appears at the line
user.authentication.save()
The error is: django.db.utils.IntegrityError: (1062, "Duplicate entry '30' for key 'user_id' ")
The 30 is the user_id existed in Authentication models when login in the second time ( the first time login is always succeed).
I solved this problem by using these codes:
except IntegrityError:
au = Authentication.objects.get(user = user)
au.token = token
au.save()
But I dont know why i got this bug. I used to do the first approach many times but not got no bugs at all. Anyone has faced to this problem can show me the way to solve this? Thank you
The problem is that you are trying to create a new token to a user who already have one, and since you've defined a OneToOneField it is not possible. I suggest you to try the get_or_create() instead of create() method.
Alternatively, you can modify the create method:
try:
auth = Authentication.objects.create(user = request.user)
except Exception as e:
#do something
return JsonResponse({'token': auth.token})
In models.py
from user.managers import MyManager
class Authentication(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
token = models.CharField(max_length =50, null = True)
objects = MyManager()
Then create a file 'managers.py' and put this in it:
from django.db import models
import uuid
class MyManager(models.Manager):
def create(self, user):
token = uuid.uuid4().hex
if user.authentication:
user.authentication.token = token
user.authentication.save()
return user.authentication
else:
auth = self.model(user=user, token=token)
auth.save(using=self._db)
return auth
Now if you use Authentication.objects.create(user=request.user) the create method in MyManager will be invoked. This also helps to separate token generation from views.py
Cheers!
You should have look at django builtin auth system. For your approach
try:
obj = Authentication.objects.get(user=user)
obj.token = token
obj.save()
except Authentication.DoesNotExist:
Authentication.objects.create(user = user, token = token)
Related
I want to create a user_profile from a factory called UserProfileFactory which uses a User object from UserFactory.
the error is: RuntimeError: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
here are the relivant classes.
from django.contrib.auth import get_user_model
from factory import Faker, post_generation
from factory.django import DjangoModelFactory
class UserFactory(DjangoModelFactory):
username = Faker("user_name")
email = Faker("email")
name = Faker("name")
#post_generation
def password(self, create: bool, extracted: Sequence[Any], **kwargs):
password = (
extracted
if extracted
else Faker(
"password",
length=42,
special_chars=True,
digits=True,
upper_case=True,
lower_case=True,
).evaluate(None, None, extra={"locale": None})
)
self.set_password(password)
class Meta:
model = get_user_model()
django_get_or_create = ["username"]
class UserProfileFactory(DjangoModelFactory):
user = UserFactory.create() #### the problem line ###
country = Faker("country") # which laws apply
birth_date = Faker("date_of_birth") # in the US you can't collect data from <13yo's
class Meta:
model = UserProfile
and in the tests/test.py
class TestUserProfileDetailView():
def test_create_userprofile(self):
"""creates an APIRequest and uses an instance of UserProfile to test a view user_detail_view"""
factory = APIRequestFactory()
request = factory.get('/api/userprofile/')
request.user = UserProfileFactory.create() # problem starts here #
response = user_detail_view(request)
self.assertEqual(response.status_code, 200)
(I know this is an old one, but in case someone else finds this question later)
I think what you want is the build method. The create method saves the instance in the database (which you said you don't want) but the build method doesn't.
Here's an explanation in the factory-boy docs of build and create.
When i use my super acc, this error does not shows up, but when I tried to use other acc. this error shows up. where did I do wrong?
The error : DoesNotExist at /voting/
Userdata matching query does not exist.
My Model :
class Userdata(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
faculty = models.ForeignKey(Fakultas, on_delete=models.CASCADE, default=1)
is_voted = models.BooleanField(default=False)
def __str__(self): return self.user.username
My views :
#login_required
def voted(response):
user = Userdata.objects.get(id=response.user.id) # get the username
if user.is_voted:
return render(response, 'Main/voting.html', {'calon': Voting.objects.order_by('id'), 'hasil': 'You Have Voted'})
if response.method == 'POST':
id = response.POST['idcalon']
calon2 = Voting.objects.get(id=id) # get user selection in html
user.is_voted = True
calon2.voters += 1
user.save()
calon2.save()
return render(response, 'Main/voting.html', {'calon': Voting.objects.order_by('id')}) # balik ke sendiri
User and UserData don't have the same primary key. So Userdata.objects.get(id=response.user.id) will not work because there is no such Userdata with the given user's id. But you do not need that, because User and Userdata have OneToOne relation. So simply use this:
user = response.user.userdata
Hey guys I am a bit new in Django. What I want to achieve is a URL which I can access with a GET request from my app, passing some values along with it.
I have a UserProfile model in Django which has a oneToOneField relationship to User. I want to pass email with my GET request and find a Userinstance with this email, then I want to pass two more values which I want to compare with this Users UserProfile attributes. But I don't quite understand how to achieve this. Here is what I have:
in my views.py
def check(request):
try:
email = request.GET.get('email', '')
osusername = request.GET.get('osusername', '')
computername = request.GET.get('computername','')
except TypeError:
return HttpResponseBadRequest()
user = get_object_or_404(User.objects.filter(user__email=email)[0])
in my urls.py
urlpatterns = patterns('',
url(r'^check/$', 'myapp.views.check'),)
But how do I compare for instance computername with User.UserProfile.computername of that user? No matter how I write it its wrong.
My UserProfile model as requested #comments:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
computername = models.CharField("Computername", max_length=150, blank=False)
osusername = models.CharField("Osusername", max_length=150, blank=False)
So your syntax for get_object_or_404 is wrong. You don't pass it an object: it gets the object for you. So:
user = get_object_or_404(User, email=email)
Now you've got a User instance, and you want to get the relevant profile, so you can just do:
profile = user.userprofile
Alternatively it might be easier to grab the profile directly, if you don't need the actual user instance for anything else:
profile = get_object_or_404(UserProfile, user__email=email)
Now you can check the relevant attributes:
osusername == profile.osusername
computername == profile.computername
You need to retrieve the User instance first by:
try:
a_user = User.objects.get(email=email)
except User.DoesNotExist:
# error handling if the user does not exist
Then, get the corresponding UserProfile object by:
profile = a_user.userprofile
Then, you can get osusername and computername from the UserProfile object:
profile.osusername
profile.computername
As an addition to #daniel-roseman answer.
If checking the relevant attributes is a common task on multiple views it could also be worth creating a method in your UserProfile model which can perform the required validation check.
class UserProfile(object):
# various attributes ...
def check_machine_attributes(self, os_username, computer_name):
if os_username == self.osusername and computername == self.computername:
return True
return False
In your view you can then do:
if profile.check_machine_attributes(osusername, computername):
# ...
else:
# ...
I'm trying to take input of a domain name (domainNm) and an email address at a domain (emailVerified) and submit them via modelform based off a table [Tld] .
It appears, it is failing to save() the foreign key (from the currently authenticated user)
domain.FKtoClient = user_info
What am I doing wrong here?
forms.py
class SubmitDomain(ModelForm):
domainNm = forms.CharField(initial=u'', label='Enter your domain')
emailVerified = forms.EmailField(label='Email at Domain')
class Meta:
model = Tld #Create form based off Model for Tld
fields = ['domainNm','emailVerified']
def save(self, request=None):
instance = self.cleaned_data
#domain = instance["domainNm"])
domains = Tld.objects.filter(domainNm=instance["domainNm"])
if len(domains) == 0:
domain = Tld()
else:
domain = domains[0]
user_info = request.user
unique_id = int(uuid.uuid4())
domain.generated_hash = str(unique_id)
domain.entered_email = instance["emailVerified"]
domain.domainNm = instance["domainNm"]
domain.FKtoClient = user_info
domain.save()
Thanks!
def save(self, request=None):
You assign a default value of None to request in the definition of save, so what happens when the caller of save doesn't pass an instantiated request?
user_info = request.user #request is None here
That will throw the error you see. To mitigate, add a simple if request is not None or similar statement.
EDIT
After seeing your views.py, you are passing request.POST to SubmitDomain's __init__ magic method, which you have not defined. The way you have your modelform defined above, you would have to pass the request to save(), not __init__(), i.e.
form.save(request)
This is my view for User registration:
def user_reg(request):
UserReg = modelformset_factory(UserProfile)
if request.method == 'POST':
formset = UserReg(request.POST)
if formset.is_valid():
formset.save()
return HttpResponseRedirect('/thanks/')
else:
formset = UserReg()
return render_to_response("regform.html",{"formset":formset,})
This is my models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
name = models.CharField(max_length = 100)
reg_no = models.TextField(unique=True)
password = models.CharField(max_length=128)
The error I get is:
Exception Type: DatabaseError at /register/
Exception Value: column auth_userprofile.name does not exist
LINE 1: ..._userprofile"."id", "auth_userprofile"."user_id", "auth_user...
I've two questions here:
1. Obviously, i want to know why I'm getting the error and how to debug.
2. Is this the right way to go about it or should a define it in forms.py and then import it? The model formset I meant. The django documentation showed that this way it can be done.
The error is a database error, you need to add the column "name" to the table "auth_userprofile". I'd highly recommend looking into "South" for all your database schema migration needs.