Adding username when submitting form on django - python

I am trying to store the username of the user currently logged in when they submit information on a form on a django website.
This is what my models.py file looks like so far:
from django.db import models
from django.contrib.auth.models import User
class Transfer(models.Model):
id = models.AutoField(primary_key=True)
username = User._meta.get_field('username')
amount = models.DecimalField(max_digits=10, decimal_places=2)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
however this doesn't seem to work. The migrations etc work fine and the server runs, but when I submit information on the form I get the following error:
Exception Type: IntegrityError
Exception Value: UNIQUE constraint failed: transfer_transfer.username
Any advice on how I could get the username to save would be very helpful.
Thanks in advance

That declaration doesn't make any sense in a model definition. It might "work", in the sense that you get a field with the same properties as User.username, but it isn't doing anything useful; you could just as well define it directly as models.CharField.
Instead you need to define a ForeignKey from Transfer to User, and call it user; there is plenty of documentation on how to do this, and also plenty of questions here on how to fill in the user field automatically on form submission.

Related

Django Creating Custom User models

I am making a website through Django and I want to create a similar model for the Users model (default user model came with Django)
I have tried everything I have found from google django docs and I couldn't.
Can anyone help?
Or help me to make a login system for my normal model
For an instance,
I have created a normal model called accounts and there is a field in it called loggedin.
Whenever I try to login system set it to True means logged in. And if i logged out by the logout button i set it to false now lets take in consideration if i have closed the web browser Immediately i want to set it to False
Any help?
There are two common ways to deal with is extending django's AbstractUser:
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
# Some other fields to go along with the default fields
info = models.TextField(max_length=500, blank=True)
phone_number = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
After this, just change the default user model on your settings.py adding AUTH_USER_MODEL = my_app.models.user

showing which post a user liked/saved with python django.

I have trouble to display the ''saved''/''liked'' posts of my users in django/admin. I would like to have a field in the Adminpage to show which user likes which posts. I made an Userprofile model where all extra information (besides the one on the given django admin user Profile) are stored. so here is my model View:
class UserProfile(models.Model):
user = models.OneToOneField(User, null=True)
#likes = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True,default=1, related_name='likes')
likedPosts=models.ManyToManyField('self')
Field1 = models.CharField(max_length=50,default='Sunny')
Field2 = models.CharField(max_length=50,default='')
class Meta:
ordering =['-user']
#def __unicode__(self):
# return self.user.username
User.profile =property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
right now in the liked post field I have only some usernames or "User object"
I tried all kinds of combinations to get the information into the admin page but as you can see I did not make it.
I tried to change the unicode and of course the liked post line. If you need more information please tell me so. I appreciate every kind of help.
django admin isn't really meant to support many to many relationships from both directions in the django admin. However, the link below contains a workaround that I think should address your problem with a better explanation of why many-to-many relationships are only shown from one side by default.
(many-to-many in list display django).
so for everybody who wants to do something similar this worked for me:
class UserProfile(models.Model):
likedPosts = models.ManyToManyField('self',default=None,blank=True)
def __unicode__(self):
return "{0}".format(self.user.likes.all())

Getting logged in User's Profile in Django without repeating request.user a lot?

The application I am writing in Django requires me to get a UserProfile model object (which has a one-to-one relationship with the standard Django User object) in a lot of the views. To get the user's profile, I end up repeating something like this quite a bit in all the different views:
user_profile = UserProfile.objects.get(user=request.user)
or
user_profile = UserProfile.objects.get(user=self.request.user)
I know good software engineering principles say don't repeat yourself (DRY), so I was wondering if there was a good way to encapsulate the code above in a separate method or if it's fine to keep it the way it is.
Thanks in advance for any help!
Add a related name to your UserProfile in models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
about = models.TextField(default='')
Then in your views.py, reference it with
request.user.profile.about = 'abc'
request.user.profile.save()
Or make it shorter
p = request.user.profile
p.about = 'abc'
p.save()

Django NOT NULL constraint failed userprofile.user_id in case of uploading a file

I am trying to practice a simple project: A user registers (using Django registration-redux), uploads some file, and then s/he is provided with a list of her files, being downloadable. Here are my models.py, forms.py, and views respectively:
models.py
class UserProfile(models.Model):
user = models.ForeignKey(User, related_name='uploaded_by')
names = models.CharField(max_length=40)
lastname = models.CharField(max_length=50)
email = models.EmailField()
uploads = models.FileField(upload_to= 'blablabla')
def __str__(self):
return self.email
forms.py
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['names', 'uploads']
view.py
from .forms import UserProfileForm
from .models import UserProfile
#login_required()
def new(request):
form = UserProfileForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
context = {'title': 'welcome', 'form': form}
return render(requst, 'upform.html', context)
however when I login with a user and try to upload a file I get the error: IntegrityError at /new
NOT NULL constraint failed: _userprofile.user_id
After digging a lot I noticed someone suggested the reason of the error is because the user is not included anyhow in the process of posting the form, so I tried whatever came to my mind and the case in which I added the user field to the forms.py worked:
forms.py
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['names', 'uploads']
the problem however is that the form shown in the browser now includes a drop-down list containing all the registered users. I tried to associate the logged-in user with the form in the views by I kept seeing different errors.
My question is: How can I associate the uploads with the logged-in user in a transparent manner.
sorry if the question is too newbie-liked
Keep the user out of the form and add it on save:
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.save()
I must say your model looks a bit odd; you have multiple profiles for each user, each with a single upload. Seems more likely you want a single profile, with a OneToOne relationship to User, than a separate Uploads model with a ForeignKey to UserProfile.
I added the user field to the forms.py worked:
This probably also opens up a security hole, because you could then set the user from outside of your application, overriding the logged-in user.
After digging a lot I noticed someone suggested the reason for the error is because the user is not included anyhow in the process of posting the form.
You figured that quite right. If the user is not a field, the form never knows how to fill the user field of UserProfile. Since you cannot save a UserProfile without a filled in user foreign key, you get the error.
There are various ways around this:
One way to solve the problem is to use save(commit=False) on the form, patch the user into the unsaved instance and manually saving the object to the database:
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.save()
This slightly violates the encapsulation because you now handle the database save outside of the form.
You are also able to provide a initial "template" instance to the form:
form = UserProfileForm(
request.POST,
request.FILES,
instance=UserProfile(user=self.request.user)
)
You probably want to do so, anyway because the form also allows to edit an existing userprofile. Currently you are saving a new UserProfile each time and since user is not unique=True in your model class, you will get multiple profiles per user.
If you do not want this to be possible, check Daniel Roseman's answer, because then you probably want UserProfile.user to be a OneToOne field.
In this case, we can simplify to
profile, created = UserProfile.objects.get_or_create(user=request.user)
form = UserProfileForm(
request.POST,
request.FILES,
instance=profile
)
Note also that I removed the or None as it is not necessary. BaseForm (which ModelForm derives from) does this check for you (it actually does self.data = data or {}) which essentially undoes the prior none-ification)
You can do following the advice of Daniel.
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='uploaded_by')
names = models.CharField(max_length=40)
lastname = models.CharField(max_length=50)
email = models.EmailField()
class UserFiles(models.Model):
user = models.ForeignKey(UserProfile)
file = models.FileField(upload_to= 'blablabla')
Remember OneToOneField is similar a ForeignKey with the attribute unique=True.

Django AbstractUser Inheritence Error

I'm still pretty new to Django, and have been having a problem defining my own user model that inherits from the Abstract User in Django. However, I have users already in the databse (with only usernames and passwords) and when I try to migrate the changes, I get the error that the email field is required and doesn't have a default value.
What confuses me is that I looked it up in the docs, and at https://docs.djangoproject.com/en/1.7/ref/contrib/auth/ the email field is clearly listed as optional. Furthermore, when I try to override the email field I get an error that my field clashes with the existing one.
Why is it giving me this error, and how do I fix it?
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserProfile(AbstractUser):
additionalFields = models.IntegerField(default=0)
def __unicode__(self):
return self.username
EmailField is a text field in the database, and 'empty' text fields are saved as an empty string (''). They are not empty (NULL) on a database level, and the column is defined as NOT NULL. What you need to do is set a default of '', then the migration will work.

Categories