I design Django Model as shown below :
`
class User(models.Model):
id=models.AutoField(primary_key=True)
username=models.CharField(max_length=25,verbose_name="username")
name=models.CharField(max_length=20,default="noName",verbose_name="name")
password=models.CharField(max_length=20,verbose_name="password")
email=models.EmailField()
userCode=models.CharField(default=" ",max_length=100,verbose_name="User Code")
def __str__(self):
return self.username
class Meta:
ordering = ['-username']`
Then I create an object in view.py. Although id is auto incremented, python want me to define an id. View.py is shown below.
def register(request,id):
if request.method=='POST':
form = RegisterForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
name=form.cleaned_data["name"]
password = form.cleaned_data["password"]
email=form.cleaned_data.get("email")
newUser = User(1,username,name,password,email)
newUser.save()
return redirect('mainPage')
else:
form=RegisterForm()
context = {
"form" : form,
"id":id
}
return render(request,"SignupLogin.html",context)
User(1,username,name,password,email) in that line, 1 is the id number. When I delete it, error which is about missing variable id, is thrown. How can I get rid of 1?
Just introduce your parameters to model init function. That might help :)
newUser = User(username=username, name=name, password=password, email=email)
and if you have nullable fields (null=True) you must describe it on model.
You do not need to declare an autoincrementing primary key field by hand – Django implicitly adds an id field for you if there is none.
Your problem is likely not having set editable=False on that manually created field of yours.
Related
check the updated pic
When I save the model, The object name is None, but I need to save the username instead of object name (None) automatically while I saving the Model
here is pic of admin site
Models.py
class solo_21_6_2021(models.Model):
user = models.OneToOneField(User,null=True,on_delete=models.CASCADE)
player1_pubg_id = models.PositiveIntegerField(null=True,blank=True)
player1_pubg_name = models.CharField(max_length=15,null=True,blank=True)
def __str__(self):
return str(self.user)
Views.py
def solo(request):
form = SoloForm()
if request.method=="POST":
form=SoloForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'bgmiapp/solo.html',{'form':form})
Forms.py
class SoloForm(forms.ModelForm):
class Meta():
model = solo_21_6_2021
fields=['player1_pubg_id','player1_pubg_name'
Admin.py
class SoloAdmin(admin.ModelAdmin):
list = ('user','player1_pubg_id','player1_pubg_name')
admin.site.register(Profile)
admin.site.register(solo_21_6_2021,SoloAdmin)
you have set user field to null so the model is created without it, so when you want to show objects by user, it does not have this info so it shows None.
modify models to :
class solo_21_6_2021(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
player1_pubg_id = models.PositiveIntegerField(null=True,blank=True)
player1_pubg_name = models.CharField(max_length=15,null=True,blank=True)
def __str__(self):
return str(self.user)
so now it is required and related as it is supposed to be
and inf the forms:
class SoloForm(forms.ModelForm):
class Meta():
model = solo_21_6_2021
fields=['user','player1_pubg_id','player1_pubg_name']
so it display the choice of user in the html form
now when you submit the form, the user name will display in the admin page
*Alternatively you could make your authenticated user the one who is creating the object, so no need to show list of your users to everyone:
def solo(request):
form = SoloForm()
if request.method=="POST":
form=SoloForm(request.POST)
if form.is_valid():
f = form.save(commit=False)
f.user = request.user
f.save()
return render(request, 'bgmiapp/solo.html',{'form':form})
and get rid of user in forms:
class SoloForm(forms.ModelForm):
class Meta():
model = solo_21_6_2021
fields=['player1_pubg_id','player1_pubg_name']
Ps: since you have a OnetoOne relation, you can create only one object by user, creating another will throw a user_id unique constraint error
So I been seeing the same question posted in different scenarios and I am unable to get mine to work. Basically trying to find a model instance if it already exists and create a new one if it doesn't - based on if the instance have the same field as the user's username
I tried get_object_or_404 and even changing the primary key to a field in the model class.
this is the models.py
class Cart(models.Model):
user = models.CharField(max_length=30)
#classmethod
def create(cls, user):
user = cls(user=user)
return user
def __str__(self):
"""String for representing the Model object."""
return f'{self.id} {self.user}'
this is the views.py
def cart(request, pk):
try:
pizza = PizzaInstance.objects.get(id=pk)
# get the topping(s)
topping_1 = int(request.POST["topping1"])
topping = PizzaTopping.objects.get(pk=topping_1)
# get the username
user = request.user.username
# check if the user already has an order
try:
order = Cart.objects.get(user=user)
except KeyError:
order = Cart.create([user])
order.save()
user creation
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2'
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
I expected to see the order being saved and a new instance being created or even new instances added to the cart.
error is get is -
Cart matching query does not exist.
Thank you!
There is a couple of problems:
You should retrieve the user with request.user instead of request.user.username (the latter gives you the username which is a str instead of the User instance.
You shouldn't really create your objects with a custom class method. Instead, use the object manager and call Cart.objects.create(user=user) (and if you do need to make a custom create() function, it should be defined on a custom manager class).
With these changes you should be able to use Cart.objects.get_or_create(user=user), which returns a tuple containing your Cart object and a bool indicating wether the object was created or not (ie. existed in the first place).
So put together:
def cart(request, pk):
try:
pizza = PizzaInstance.objects.get(id=pk)
# get the topping(s)
topping_1 = int(request.POST["topping1"])
topping = PizzaTopping.objects.get(pk=topping_1)
# get the user
user = request.user
# get the Cart object associated with 'user' or create a new one
order, created = Cart.objects.get_or_create(user=user)
Try using the .get_or_create() method:
cart, created = Cart.objects.get_or_create(...)
You're doing some odd things here.
Cart.objects.get won't raise a KeyError. It raises the error you see: Cart.DoesNotExist. So that is the error you need to catch.
Additionally, for some reason you are wrapping the user in a list when you pass it in the except block. Don't do that.
try:
order = Cart.objects.get(user=user)
except Cart.DoesNotExist:
order = Cart.create(user)
order.save()
Here i have two models:
ProfilePic
Member
ProfilePic's user variable extends from Member's username (this is so i can have one username in the DB for all other forms and models).
Now ProfilePic is used as a form, and in my views.py I want to add:
member_obj = Member.objects.get(pk=username)
to my ProfilePic form. However, when I run my code, it doesn't give an error but it doesn't render the information in the db either. So I'm confused as to whats going on here.
What am i doing wrong? Thanks in advance !
# models.py
class ProfilePic(models.Model):
user = models.ForeignKey(Member, related_name='%(class)s_user', null=True)
text = models.TextField(max_length=4096)
thumbnail = models.FileField(upload_to='media', null=True)
class Member(models.Model):
username = models.CharField(max_length=16, primary_key=True)
password = models.CharField(max_length=16)
profile = models.OneToOneField(Profile, null=True)
following = models.ManyToManyField("self", symmetrical=True)
# forms.py
from django import forms
from .models import ProfilePic
class UploadFileForm(forms.ModelForm):
class Meta:
model = ProfilePic
fields = ['text','thumbnail']
# views.py
def profile(request):
username = request.session['username']
member_obj = Member.objects.get(pk=username)
if request.POST:
invitations = Invitation.objects.filter(to_user=username)
form = UploadFileForm(request.POST,request.FILES, instance=member_obj)
form.save()
picture = ProfilePic.objects.all()
return render(request, 'social/profile.html', {
'appname': appname,
'username': username,
'invitations':invitations,
'picture' : picture,
'form' : form,
'loggedin': True}
)
You are passing a Member instance to a ProfilePic model form.
What you want to do is:
form = UploadFileForm(request.POST, request.FILES,
instance=member_obj.profile_pic_user)
So you get a ProfilePic instance.
View is just a function. You get a Member object from the database, assign it to a member_obj variable, but you are not actually doing anything with it. You want to assign it to a ProfilePic object. Also, I don't think this line picture = ProfilePic.objects.all() does what you intend to do. You are getting a list of all profile picture objects instead of just one.
You have to add it to the saved object. You do that by telling the form to create the object, but not saving it to the DB yet.
Then, set the field, and save to the DB.
Add this lines to the view, instead of the form.save():
profile_pic = form.save(commit=False) #not saving to db
member_obj = Member.objects.get(username=request.user.username)
profile_pic.user = member_obj
profile_pic.save() # now it's saved
I have two models: User (pre-defined by Django) and UserProfile that are connected through a foreign key.
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="connect")
location = models.CharField(max_length=20, choices=LOCATION_CHOICES)
gender = models.CharField(max_length=20, choices=GENDER_CHOICES)
The User model contains fields such as username, first_name, last_name, and password.
In my view, I want to find a UserProfile object using the username field which is located in the User Object. To filter/get a UserProfile object with the username field, I need to "travel" through the Foreign Key to access the User Model.
However, I got several errors in trying to do this. Does anyone know how I can do this?
This is what I have so far:
def edit(request):
#the line below is where I am facing troubles.
#The error I'm getting is SyntaxError: keyword can't be an expression
user = UserProfile.objects.filter(user.username=request.user.username)
form1 = UserEditForm()
form2 = UserProfileEditForm()
c = RequestContext(request, {
'action': 'update/',
'button': 'Update',
'form1': form1,
'form2': form2,
})
return render_to_response('registration/user_profile.html', c)
Does anyone know how to solve this? Thanks!
Use double underscores (__) to traverse relationships. E.g.:
user = UserProfile.objects.filter(user__username=request.user.username)
However, in your case, you don't need to do this. request.user is a User object, so to get their UserProfile just do:
user = request.user.get_profile()
or even:
UserProfile.objects.get(user=request.user)
Note that your first example should return a QuerySet with 1 result, whereas the second returns a single object. In other words:
request.user.get_profile() ==
UserProfile.objects.filter(user__username=request.user.username)[0]
i'm using Django registration, and unlike everybody else, I seem to have the opposite problem. My User object is saved fine, but my UserProfile object isn't!
I followed this website:
http://birdhouse.org/blog/2009/06/27/django-profiles/
which was really good, and so now i have:
class ProfileForm(forms.ModelForm):
YESNO = [
(True,mark_safe('<img src="/static_files/greenTick.png"/>')),
(False,mark_safe('<img src="/static_files/redCross.png"/>'))]
class Meta:
model = UserProfile
exclude = ('isTweeting','points','user')
fields = ('display_name','first_name','last_name','email','gravatar')
def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
self.fields['email'].initial = self.instance.user.email
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
self.fields['display_name'].initial = self.instance.user.username
self.fields['gravatar'].initial = self.instance.usesGravatar
#add in the input to size it juuuuust right.
email = forms.EmailField(label="Primary email",help_text='',widget=forms.TextInput(attrs={'class': 'wideInput'}))
first_name = forms.Field(label="First name",help_text='',required=False,widget=forms.TextInput(attrs={'class': 'wideInput'}))
last_name = forms.Field(label="Last name",help_text='',required=False,widget=forms.TextInput(attrs={'class': 'wideInput'}))
display_name = forms.Field(label="Display name",help_text='',widget=forms.TextInput(attrs={'class': 'wideInput'}))
gravatar = ImgModelChoiceField(label='Gravatar', choices=YESNO, widget=forms.RadioSelect(renderer=ImgRadioFieldRenderer))
def save(self, *args, **kwargs):
"""
Update the primary email address on the related User object as well.
"""
u = self.instance.user
u.email = self.cleaned_data['email']
u.username = self.cleaned_data['display_name']
u.first_name = self.cleaned_data['first_name']
u.last_name = self.cleaned_data['last_name']
u.save()
self.instance.gravatar = (self.cleaned_data['gravatar'] == 'True')
profile = super(ProfileForm, self).save(*args,**kwargs)
return profile
this object is passed into the Django-profile as the form_class for use, as described in the website above. The problem i have is that when i submit my form, while the "User" data is updated correctly - any changes in the email or whatnot propagate to the db - the change to the "gravatar" value is not sent. Also no error is thrown.
Any ideas what I should do?
I'm going to hazard a guess here
def save(self, *args, **kwargs):
...
self.instance.gravatar = (self.cleaned_data['gravatar'] == 'True')
profile = super(ProfileForm, self).save(*args,**kwargs)
return profile
It seems you are using a custom widget, and by the looks of things you need to change the string 'True' (passed back from the form) to a boolean True before saving it to the DB. When you call save() on the next line though, the ModelForm will overwrite the value you have given self.instance.gravatar with the data directly from the form's cleaned_data:
https://github.com/django/django/blob/master/django/forms/models.py#L351
Also, in __init__, you don't need to include
self.fields['gravatar'].initial = self.instance.usesGravatar
as this field is already bound to the model form and will be automatically populated (if the UserProfile is being edited for example) when you instantiate the form along with an instance in your view.
Finally, in your Meta, you don't need to include both excludes and fields, one or the other should be fine.
First of all consider suggestions from #Timmy.
The only thing which else should be noticed is in this line:
profile = super(ProfileForm, self).save(*args,**kwargs)
By default the save method has commit=True. Verify that the function which is calling this Form might be sending commit=False in args or kwargs. If yes then you have to manually save the profile profile.save() before returning because commit=False means the changes will not reflect to the db.
And why you are allowing user to update both username and email? How you will keep track of the registration process if you are allowing to update both fields? Usually user sign up using their email. Define your criteria which field(username or email) you want to kept unchanged.
Update
Also you are doing one more thing wrong in your save function. You are updating the email, username, firstname and lastname in user taken from instance.user. But that instance overwritten when profile form default save is call here profile = super(ProfileForm, self).save(*args,**kwargs). What you should do is to update those fields using the user = profile.user The profile which is returned by the super. Your save function should be looked like this:
def save(self, *args, **kwargs):
"""
Update the primary email address on the related User object as well.
"""
profile = super(ProfileForm, self).save(*args,**kwargs)
u = profile.user
u.email = self.cleaned_data['email']
u.username = self.cleaned_data['display_name']
u.first_name = self.cleaned_data['first_name']
u.last_name = self.cleaned_data['last_name']
u.save()
#profile.save() #if commit=False in kwargs
return profile