Django ValueError - add user to userteam - python

I am creating a Django form where you can add a user to a UserTeam (UserTeams model below). The 'invite' page (below) queries the Team model to get the id of the current team, which it then assigns to 'teamID', so you can only add a user to the current team. (I have disabled this field so the user cannot change the team) The user then selects the user they want to add, and submits the form. I am trying this using the Team "Kate FC", and adding the player 'steven'. When I submit the form, however, i get this error:
ValueError at /teams/1/invite/
Cannot assign "'Kate FC'": "UserTeams.teamID" must be a "Team" instance.
What does this error mean??
class UserTeams(models.Model):
userID = models.ForeignKey(User,on_delete=models.CASCADE)
teamID = models.ForeignKey(Team,on_delete=models.CASCADE)
class Team(models.Model):
name = models.CharField(max_length=100)
venue = models.CharField(max_length=100)
countryID = models.ForeignKey(Countries, on_delete=models.CASCADE)
owner = models.ForeignKey(User)
def invite(request, teamID):
try:
query = Team.objects.get(id=teamID)
except:
raise Http404()
if request.method == 'POST':
form = InvitePlayerForm(request.POST or None, initial={'teamID': query})
if form.is_valid():
userteam = form.save(commit=False)
userteam.save()
return redirect('teammanager/teams.html')
else:
form = InvitePlayerForm(initial={'teamID': query})
query = Team.objects.get(id=teamID)
return render(request, 'teammanager/invite.html', {
"team": query,
"form": form
})
the form:
class InvitePlayerForm(forms.ModelForm):
teamID = forms.CharField(disabled=True)
class Meta:
model = UserTeams
fields = ['teamID','userID']

teamID is a foreign key, so you should use a model choice field instead of a CharField:
class InvitePlayerForm(forms.ModelForm):
teamID = forms.ModelChoiceField(queryset=Team.objects.all(), disabled=True)
...
or you could disable the field in the __init__ method.
class InvitePlayerForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(InvitePlayerForm, self).__init__(*args, **kwargs)
self.fields['teamID'].disabled = True
...
Alternatively, you could just leave the teamID field out of the form and set the value when you save the form:
if form.is_valid():
userteam = form.save(commit=False)
userteam.teamID = query
userteam.save()

Related

Retrieving current user id inside a function defined into class (CreateView)

Is possible to retrieve the current logged user id into a function defined inside a class, in views.py, using Django CreateView?
Something like this:
class CreationClass(CreateView):
model = Mymodel
def creation(self, request):
if request.method == 'POST':
form = MyForm(request.POST or None)
if form.is_valid:
form = myForm()
user_id = self.request.user.id
rel_table = Item_id_user ( item_id = form.id, user_id = request.user.id)
rel_table.save() #<--- this does not save, even if table exists
return render(request, ''mypage.html')
And this is my models.py
class Item(models.Model):
id_user = models.ManyToManyField(User, related_name='user_item',
verbose_name='id utente', through='Item_id_user')
object = models.Manager()
# table to handle relationship
class Item_id_user(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
id = models.IntegerField(primary_key=True)
What I want to achieve is to store into Item_id_user, but nothing at all is being stored. I thought the problem was the request.user.id.
instead of:
user_id = self.request.user.id
try this:
user_id = request.user.id
Should work.
I don't understand why you re-initialize the form with form = MyForm() after the form is validated. I think that might wipe the data contained in it. It looks like you forgot it there.
Try this:
class CreationClass(CreateView):
model = Mymodel
def creation(self, request):
if request.method == 'POST':
form = ColumnCreationForm(request.POST or None)
if form.is_valid:
# form = myForm()
user_id = self.request.user.id
rel_table = Item_id_user ( item_id = form.id, user_id = request.user.id)
rel_table.save() #<--- this does not save, even if table exists
return render(request, ''mypage.html')

NOT NULL constraint failed: registratie_inkomen.pg_id

This are my models:
class PersoonGegevens(models.Model):
# Voornaam en achternaam
voornaam = models.CharField(max_length=265,)
achternaam = models.CharField(max_length=265)
#username
user = models.OneToOneField(User, on_delete=models.CASCADE)
class inkomen(models.Model):
pg = models.ForeignKey(PersoonGegevens, on_delete=models.CASCADE)
inkomenfield = models.CharField(max_length=100)
This is the form:
class inkomenForm(forms.ModelForm):
class Meta():
model = inkomen
fields = ('inkomenfield',)
This is my view:
def tijdelijk(request):
#User id
user = request.user.id
if request.method == 'POST':
incoming = inkomenForm(data=request.POST)
if incoming.is_valid():
incoming.save()
return HttpResponse("saved")
else:
x = incoming.errors
print (x)
return HttpResponseRedirect('/tijdelijk')
else:
incoming = inkomenForm()
return render(request, 'index/tijdelijkeindex.html', {'inkomen':incoming})
I have tried:
incoming.save(commit=False)
incoming.pg = user
incoming.save
also readed the documentation about Inline formsets of django. But i dont really get
So i get the following error:(NOT NULL constraint failed) and i know it comes because i need to assign the pg.id and i know i can do that by adding the field in the form.py and let the user choose the id. But what i actually want is that pg = the logged in user.
You need to assign the return value of form.save(commit=False) to a variable, the return value is the created (but not committed to the database) model object
obj = incoming.save(commit=False)
obj.pg = user
obj.save()

How to assign value of field of one model to field of another model?

Say, I have a view function that creates a Vacancy object on saving the form, and it has the field company that, if the form is valid, has to be assigned with value of field name, that is on the other model named EmployerProfile, how can I do that? I have company as a foreign key on my model.
My models
class EmployerProfile(models.Model):
name = models.CharField(max_length = 64)
description = models.TextField()
username = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete = models.CASCADE)
class Vacancy(models.Model):
name = models.CharField(max_length = 64)
competences = models.CharField(max_length = 32)
salary = models.DecimalField(decimal_places = 2, max_digits = 10)
description = models.TextField(null = True)
company = models.ForeignKey(EmployerProfile, on_delete = models.CASCADE)
featured = models.BooleanField(default = False)
My view
#login_required(login_url = 'login')
def vacancyAddView(request):
if request.method == 'POST':
form = VacancyAddForm(request.POST)
if form.is_valid():
form.save()
return redirect('profile')
else:
form = VacancyAddForm()
context = {
'form':form
}
return render(request, "addVacancy.html", context)
My form
class VacancyAddForm(forms.ModelForm):
class Meta:
model = Vacancy
fields = [
'name',
'competences',
'description',
'salary',
]
P.S. I have tried adding this piece of code to my view, rigth after form.is_valid():
obj = EmployerProfile.objects.get(username = request.user)
form.instance.company = obj.name
but it didn't work, it returned the ValueError with text "Vacancy.company" must be a "EmployerProfile" instance.
P.P.S. I also tried to override the save method in my model like this
def save(self, *args, **kwargs):
self.company = self.EmployerProfile.name
super(Vacancy, self).save(*args, **kwargs)
but it didn't work either.
You can't do what you want. Your Vacancy model defines company as a foreign key, but you're trying to set it as a string.
class Vacancy(models.Model):
company = models.ForeignKey(EmployerProfile, on_delete = models.CASCADE)
However, here's what your view should change to be to work with your models as you've defined them currently.
#login_required(login_url = 'login')
def vacancyAddView(request):
if request.method == 'POST':
form = VacancyAddForm(request.POST)
if form.is_valid():
# Set the company
form.instance.company = request.user.employerprofile
form.save()
return redirect('profile')
else:
form = VacancyAddForm()
context = {
'form':form
}
return render(request, "addVacancy.html", context)
The basic issue here is that you can't set a ForeignKey field to be a string. If you want the user to be able to set the Company from the form, you have a couple of choices. One is to take what you have now in the form and use it to filter, e.g. something like:
company = EmployerProfile.objects.filter(name__iexact=form.cleaned_data['company'])
form.instance.company = company
Another would be to change the form so that instead of a text input, company is a ModelChoiceField, or a regular ChoiceField populated with the company choices available to the user.
In either case the end goal will be to ensure that the company field contains a foreign key to an EmployerProfile object, rather than the string name of a company.

How do I remove this error message in ModelForm?

I'm trying to create a way to update an item of the database that has the fields CharField and ForeignKey. I want to pass the original values so that they don't have to be manually entered for each field every time, but this gives me a "Select a valid choice. That choice is not one of the available choices." warning for the group field. How do I remove this warning message?
Setting the error message (in ModelForm) to something else manually still displays an empty (unordered) list item. Setting the form in UpdateUserView to form = UserForm() gets rid of the errors, but doesn't pass default values to the form.
models.py
class User(models.Model):
username = models.CharField(max_length=50)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
class Group(models.Model):
name = models.CharField(max_length=20)
description = models.CharField(max_length=200)
forms.py
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'group']
views.py
class UpdateUserView(TemplateView):
template_name = 'update_user.html'
def get(self, request):
user_id = int(request.GET.get('user_id'))
user = User.objects.get(id=user_id)
default_name = getattr(user, 'username')
default_group = getattr(user, 'group')
form = UserForm({'username': default_name, 'group': default_group})
return render(request, self.template_name, {'form': form, 'user': user})
End Result
You have to use initial argument like this:
class UpdateUserView(TemplateView):
template_name = 'update_user.html'
def get(self, request):
user_id = int(request.GET.get('user_id'))
user = User.objects.get(id=user_id)
form = UserForm(initial={'username': user.username, 'group': user.group.id})
return render(request, self.template_name, {'form': form, 'user': user})
Look I'm using group: user.group.id here, since the model Field you are referencing there in your form is a ForeignKey.
I hope this help.

Django ValueError Cannot assign "'testing'": "Profile.artist" must be a "Artist" instance

I have created a form and have set the foreign key 'artist' as a CharField so users can freely input the artist's name and it would be created if it doens't exist. I am getting the following error when inputting data in the artist field:
ValueError: Cannot assign "'testing'": "Profile.artist" must be a "Artist" instance
Here is my models.py:
class Artist (models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Genre (models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Profile (models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
genre = models.ForeignKey(Genre, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
mix = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.title
Here is my views.py:
def profile_create(request):
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
form = ProfileForm(None) #clears the form for new submission
context = {
"form": form,
"instance": instance,
}
return render(request, "profile_form.html", context)
else:
form = ProfileForm(None)
context = {
"form": form,
}
return render(request, "profile_form.html", context)
Here is my forms.py:
from django import forms
from .models import Profile, Artist
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = [
"artist",
"title",
"mix",
"genre",
]
artist = forms.CharField(widget=forms.TextInput)
def clean_artist(self, commit=True):
artist = self.cleaned_data.get("artist")
if not artist:
raise forms.ValidationError("Artist is a required field.")
else:
artist, created = Artist.objects.get_or_create(name=artist)
self.cleaned_data['artist'] = artist
return super(ProfileForm, self).clean()
The clean_artist method should return the cleaned value of the artist field. so instead of
artist, created = Artist.objects.get_or_create(name=artist)
self.cleaned_data['artist'] = artist
return super(ProfileForm, self).clean()
do
artist, created = Artist.objects.get_or_create(name=artist)
return artist
I am not sure though if it is best practice to rewrite the type of a field in the clean method, as it could pose problems if there are errors in the form and it needs to be rendered again with a artist instance as value.
I would probably remove the artist field from Meta.fields and do the Artist.objects.get_or_create(name=artist) and set the artist field of the instance in the save method of the form.

Categories

Resources