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')
Related
I'm doing a edit form for some data. I'm having problem to pass information to . As you can see in my view, I pass the data to form using "initial" dictionary.
VIEWS.PY
#login_required
def project_detail(request, project_id):
if request.method == 'POST':
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(project_id, request.POST, instance = project)
if form.is_valid():
instance = form.save(commit=False)
instance.client = Project.objects.get(pk=project_id).client
form.save()
messages.success(request,'Projeto modificado')
return redirect('projects')
else:
messages.error(request,'Ocorreu um erro!')
else:
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(project_id, initial={'modal':project.modal,
'culture':project.culture,
'owner':project.owner,
'value':project.value,
'final_date':project.final_date,
'text':project.text,
'status':project.status,
'farm':project.farm.values()})
return render(request,'project_detail.html',{'form':form})
But doing this, the data is not displaied in . Thinking here, ManyToManyField saves data in lists. I tried iterate this field but still not working and I guess thats not the best way to do this.
MODELS.PY
class Project(models.Model):
modal_types = [('CUSTEIO AGRÍCOLA','Custeio Agrícola'),('CUSTEIO PECUÁRIO','Custeio Pecuário'),('INVESTIMENTO AGRÍCOLA','Investimento Agrícola'),('INVESTIMENTO PECUÁRIO','Investimento Pecuário'),('FGPP','FGPP')]
status_opts = [('Análise','Análise'),('Desenvolvimento','Desenvolvimento'),('Processamento','Processamento'),('Liberação','Liberação'),('Finalizado','Finalizado'),('Cancelado','Cancelado'),('Suspenso','Suspenso')]
farm = models.ManyToManyField(Farm, related_name='farm_name',verbose_name='Propriedade beneficiada')
client = models.ForeignKey(Clients, on_delete=models.CASCADE, related_name='project_client',default=None,null=True, verbose_name='Cliente')
owner = models.ForeignKey(Owner, on_delete=models.CASCADE, related_name='project_bidder',default=None,null=True, verbose_name='Proponente')
warranty = models.ManyToManyField(Farm, related_name='project_warranty',default=None, verbose_name='Propriedade de garantia')
modal = models.CharField(max_length=100,default=None,choices=modal_types, null=True, verbose_name='Tipo')
culture = models.CharField(max_length=50,null=True, verbose_name='Cultura')
status = models.CharField(max_length=50,null=True, verbose_name='Status', choices=status_opts)
created_date = models.DateField(null=True, verbose_name='Data de criação')
value = models.FloatField(max_length=10,null=True, verbose_name='Valor financiado')
final_date = models.DateField(default=None,null=True, verbose_name='Fim do contrato')
text = models.TextField(default=None,null=True, verbose_name='Observações')
forms.py
class ProjectDetailForm(ModelForm):
class Meta:
model = Project
fields = ['status','owner', 'farm', 'warranty', 'modal', 'culture', 'value','final_date','text']
def __init__(self, project_id, *args, **kwargs):
client_id = Project.objects.get(pk=project_id).client
super(ProjectDetailForm,self).__init__(*args,**kwargs)
self.fields['value'].required = False
self.fields['final_date'].required = False
self.fields['text'].required = False
self.fields['farm'].queryset = Farm.objects.filter(client=client_id)
self.fields['warranty'].queryset = Farm.objects.filter(client=client_id)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control'
Here all the fields with information, but in "select" nothing is selected, despite having data in the database
Someone can help me?
Why are you passing 'project_id' into your form class instance? Try changing this:
form = ProjectDetailForm(project_id, request.POST, instance = project)
to this:
form = ProjectDetailForm(request.POST, instance = project)
and see if it helps. Also in your form initialization, I'm not sure you're using the "initial=" values dictionary correctly. Initial values are typically defaults applicable to the "create" view, not database records that it sounds like you want to see in an update view. I think you want to pass in the instance of your database record there, something like:
else:
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(instance=project)
Also, you really don't need to write project object query twice in this view. You can do something like:
def project_detail(request, project_id):
project = get_object_or_404(Project, pk=project_id) # query this once here
if request.method == 'POST':
form = ProjectDetailForm(request.POST, instance=project)
if form.is_valid():
instance = form.save(commit=False)
instance.client = Project.objects.get(pk=project_id).client
form.save()
messages.success(request,'Projeto modificado')
return redirect('projects')
else:
messages.error(request,'Ocorreu um erro!')
# you probably want a redirect here as well
else:
form = ProjectDetailForm(instance=project)
return render(request,'project_detail.html',{'form':form})
Finally, if you're trying to limit the choices from your ManyToMany field in the user's form, you can do so with something like this:
class ProjectDetailForm(forms.ModelForm):
class Meta:
model = YourModelName
fields = ['farm']
farm = forms.ModelMultipleChoiceField(
queryset=Farm.objects.filter(some_field=some_criteria).order_by('some_field'),
widget=forms.CheckboxSelectMultiple)
More info about widgets on form classes here in Django docs.
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Customer(models.Model):
user = models.OneToOneField(User,null=True,blank=True,on_delete=models.CASCADE)
name = models.CharField(max_length=200,null=True)
## phone = models.IntegerField(null=True)
email = models.EmailField(max_length=250)
profile_pic = models.ImageField(default='default_pic.png',null=True,blank=True)
date_created = models.DateTimeField(auto_now_add=True,null=True)
def __str__(self):
return self.name
class Task(models.Model):
customer = models.ForeignKey(Customer,on_delete=models.CASCADE,null=True)
title = models.CharField(max_length=200)
description = models.TextField(null=True,blank=True)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ['complete']
views.py
#login_required(login_url='login')
def taskCreate(request):
if request.method == 'POST':
form = TaskForm(request.POST or None)
if form.is_valid():
form.instance.customer = request.user
form.save()
return redirect('tasks')
else:
form = TaskForm()
context = {'form':form}
return render(request,'todo_list/task_create.html',context)
Error:
ValueError at /create_task/
Cannot assign "<SimpleLazyObject: <User: Dominic>>": "Task.customer" must be a "Customer" instance.
I am trying to link the username in the user account to be shown on the model Task.customer that represents the post is created by that user. May I ask any methods could be done in order to specify the customer in the model Task? Also I do not understand the error message in detail because my admin panel already has the current username in the Customer model. However if I used request.user.customer the username does not show up instead returning None so how to solve this issue?
I don't know form.instance.customer = request.user
but I think I understood what you meant and the below code does the same thing
#login_required(login_url='login')
def taskCreate(request):
if request.method == 'POST':
form = TaskForm(request.POST or None)
if form.is_valid():
t = form.save(commit = False)
t.customer = request.user # assigning current user to created task.customer
t.save()
return redirect('tasks')
else:
form = TaskForm()
context = {'form':form}
return render(request,'todo_list/task_create.html',context)
if the code is still not working then try changing your line
customer = models.ForeignKey(Customer,on_delete=models.CASCADE,null=True) to
customer = models.ForeignKey(User,on_delete=models.CASCADE,null=True) in your models.py
The error comes from the following snippet
form.instance.customer = request.user
request.user is not a Customer instance, you can try extracting the information from request.user and create a Customer object from it and then assign it back
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()
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.
So I have a problem about how to save model instance with foreign key relation,
models.py
class Connect(models.Model):
username = models.CharField(max_length=255)
password = models.CharField(max_length=255,null=True, blank=True)
conft = models.TextField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return unicode(self.username)
class Ip(models.Model):
class Meta:
db_table = 'autonet_ip'
connect_id = models.ForeignKey(Connect, on_delete=models.CASCADE)
ipaddr = models.CharField(max_length=255)
def __str__ (self):
return self.ipaddr
forms.py
class NacmForm(ModelForm):
password = forms.CharField(widget=forms.PasswordInput,required = False)
class Meta:
model = Connect
fields = ['username', 'password','conft']
labels = {'conft':_('Config'),}
class IpForm(ModelForm):
class Meta:
model = Ip
fields = ['ipaddr']
labels = {'ipaddr':_('IP address'),}
IpFormset = formset_factory(IpForm, extra=1)
views.py
def konfig(request):
ip_list = []
status = ''
value_bak = 1
if request.method == 'POST':
formm = NacmForm(request.POST or None)
ipform = IpFormset(request.POST)
upform = UploadForm(request.POST,request.FILES)
userValue = formm['username'].value()
passValue = formm['password'].value()
confValue = formm['conft'].value()
usernamef = get_object_or_404(Connect, pk=id)
if ipform.is_valid():
for form in ipform:
ipaddr = form.cleaned_data.get('ipaddr')
//.... some code ...//
simpanIp = form.save(commit=False)
simpanIp.connect_id = usernamef
simpanIp.save()
simpanForm.save()
return HttpResponseRedirect('/konfig')
else:
formm = NacmForm()
ipform = IpFormset()
return render(request, 'konfig.html', {'form': formm, 'logins': Connect.objects.all(), 'ipform': ipform, 'status': status })
Then, when I input all data and click submit to collect form data and on simpanIp.save(), I've got an error: id() takes exactly one argument (0 given).
I just want to know how to save the instance of Connect model to database with foreign key, thanks in advance
so i edit my models.py like this
class Connect(models.Model):
......
def get_usernameinf(self):
return ', '.join(self.usernameinf.all().values_list('username', flat=True))
and views.py like this
if request.method == 'POST':
.....some code.....
if ipform.is_valid() and formm.is_valid():
simpanForm = formm.save()
for form in ipform:
simpanIp = form.save(commit=False)
...... some code ..
simpanIp.connect_id = simpanForm
simpanIp.save()
and its work, now the result is my "connect_id" got value from "Connect id"
id is a Python builtin that gives a unique ID for an object. I would guess that you did not intend to pass it get_object_or_404 on this line:
get_object_or_404(Connect, pk=id)
The calling convention for this functions seems to be that it is meant to be an integer for the primary key in a database table. Figure out where you should be getting your primary key from and set it correctly.
Pro-tip: avoid using names that are predefined by Python (see here for a full list). It can lead to headaches like the one you just had.