Inline Custom Form in Django - django

I am trying to create a system to add applications (named Candidatura in models.py) to a database and, in each application, the user can add as many experiences (named CandidaturaExp in models.py) as they wish (one to many relation).
I already have forms.py and views.py working for the application but I have no idea how to do it so a the user can insert experiences. I also have no idea how to create a "PLUS" button in my template to add the experience form since I am not an expert in Java Script.
So, I have the following:
models.py
class Candidatura(models.Model):
## IDENTIFICACAO E CONTACTO
nome=models.CharField(max_length=200, verbose_name='Nome Completo')
nacionalidade=models.CharField(max_length=200, verbose_name='Nacionalidade')
data_nascimento=models.DateField(verbose_name='Data de Nascimento')
residencia=models.CharField(max_length=200, verbose_name='Residência')
localidade=models.CharField(max_length=200, verbose_name='Localidade')
cod_postal=models.CharField(max_length=10, verbose_name='Código Postal')
email=models.EmailField(max_length=254, verbose_name='Email')
telefone=models.IntegerField(verbose_name='Telefone')
## HABILITACAO E CONHECIMENTOS
nivel_academico=models.CharField(max_length=200, verbose_name='Nível Académico')
ano_conclusao=models.CharField(max_length=4, verbose_name='Ano de Conclusão')
curso=models.CharField(max_length=200, verbose_name='Curso')
instituicao=models.CharField(max_length=200, verbose_name='Instituição')
outras_hab=models.CharField(max_length=255, null=True, blank=True, verbose_name='Outras Habilitações')
conhec_tec=models.CharField(max_length=255, null=True, blank=True, verbose_name='Conhecimentos Técnicos')
## DOCUMENTOS ANEXOS
cv=models.FileField(upload_to=None, max_length=100, verbose_name='Curriculum Vitae', null=True, blank=True)
data_criado=models.DateTimeField(default=timezone.now, editable=False, verbose_name='Data de criação')
def __unicode__(self):
return self.nome
## EXPERIENCIA PROFISSIONAL
class CandidaturaExp(models.Model):
candidatura = models.ForeignKey(Candidatura)
experiencia=models.BooleanField(verbose_name='Experiência Profissional')
ano_admissao=models.CharField(max_length=4, null=True, blank=True, verbose_name='Ano de Admissão')
ano_saida=models.CharField(max_length=4,null=True, blank=True, verbose_name='Ano de Saída')
empresa=models.CharField(null=True, blank=True, max_length=200, verbose_name='Empresa')
funcao=models.CharField(null=True, blank=True, max_length=255, verbose_name='Função Desempenhada')
def __unicode__(self):
return self.candidatura
class CandidaturaForm(ModelForm):
class Meta:
model = Candidatura
fields = '__all__'
class CandidaturaExpForm(ModelForm):
class Meta:
model = CandidaturaExp
fields = '__all__'
forms.py
class NovaCandidatura(forms.ModelForm):
class Meta:
model = Candidatura
fields = ('__all__')
class NovaCandidaturaExp(forms.ModelForm):
class Meta:
model = CandidaturaExp
fields = '__all__'
views.py
def inicio(request):
return render_to_response('indexDB.html', locals(), context_instance=RequestContext(request))
#login_required
def listing(request):
table = CandidaturaTable(Candidatura.objects.all())
return render(request, "listDB.html", {'table': table})
#login_required
def newform(request, template_name="NovaCandidatura.html"):
if request.method == 'POST':
form = NovaCandidatura(request.POST, request.FILES)
if form.is_valid():
form.save()
url = urlresolvers.reverse('change_success')
return HttpResponseRedirect(url)
else:
form = NovaCandidatura()
page_title = ('Update user data')
return render_to_response(template_name, locals(),
context_instance=RequestContext(request))

Related

How to display conditional form field that is dependent on an attribute of a selected foreign key on django model form

I want to conditionally display either frequency_input or duration_input fields based on the behavior.recording attribute of the selected behavior.
I have a Trial form that currently displays 3 fields:
behavior_name (foreign Key) dropdown
frequency_input
duration_input
Im not sure if i should the best method to solve this (Javascript or solve in the View)?
Trial Model
class Trial(models.Model):
behavior_name = models.ForeignKey(Behavior, on_delete=models.CASCADE)
client_session = models.ForeignKey(Client_Session, on_delete=models.CASCADE)
frequency_input = models.PositiveIntegerField(default=0, blank=True)
duration_input = models.DurationField(blank=True, default=timedelta(minutes=0))
class Meta:
verbose_name_plural = 'trials'
def __str__(self):
return str(self.id)
Behavior Model
RECORDING_CHOICES = (
('Rate','RATE'),
('Duration','DURATION'),
('Frequency','FREQUENCY')
)
class Behavior(models.Model):
name = models.CharField(max_length=200)
goal = models.CharField(max_length=200)
recording = models.CharField(max_length=10, choices=RECORDING_CHOICES, null=False)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='Active')
def __str__(self):
return self.name
Trial Form
class TrialForm(forms.ModelForm):
class Meta:
model = Trial
fields = ('behavior_name','frequency_input', 'duration_input')
Add Trial View
def add_trial(request, clientsession_id):
client_session = Client_Session.objects.get(id=clientsession_id)
if request.method != 'POST':
form = TrialForm()
else:
form = TrialForm(data=request.POST)
if form.is_valid():
add_trial = form.save(commit=False)
add_trial.client_session = client_session
add_trial.save()
return HttpResponse(status=204, headers={'HX-Trigger': 'trialupdated'})
context = {'client_session': client_session, 'form': form}
return render(request, 'sessions/add_trial.html', context)

how to update a extended Django User model?

I have created the user authentication system which includes both the default User model and an extended User model. They are as below:
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
Photo = models.ImageField(upload_to='documents/%Y/%m/%d/', null=True)
uploaded_at = models.DateTimeField(auto_now_add=True, null=True)
dob = models.DateField(max_length=20, null=True)
country = models.CharField(max_length=100, null=True)
State = models.CharField(max_length=100, null=True)
District = models.CharField(max_length=100, null=True)
phone = models.CharField(max_length=10, null=True)
def get_absolute_url(self):
return reverse('profile', kwargs={'id': self.id})
forms.py
class UserProfileForm(forms.ModelForm):
Photo = forms.ImageField( max_length=100)
dob = forms.DateField(widget=forms.TextInput(attrs={'type': 'date'}))
country = forms.CharField(max_length=100)
State = forms.CharField(max_length=100)
District = forms.CharField(max_length=100)
phone = forms.CharField(max_length=10)
class Meta:
model = UserProfile
fields = ('Photo', 'dob', 'country', 'State', 'District', 'phone')
With the help of the above model and form, I am able to create user, and enter values for those custom model fields and see the user profile. So far so good.
However, I am facing issues while I update those custom fields. I have used the Django's in-built modules to update the default User fields(email). But I am not able to find a way to update those custom fields('dob', 'country', 'State', 'District', 'phone'). Below is the method from views.
views.py
#login_required(login_url="/login/")
def editUserProfile(request):
if request.method == "POST":
form = UserProfileUpdateForm(request.POST, instance=request.user) # default User profile update
obj = UserProfile.objects.get(id=request.user.id)
form1 = UserProfileForm(request.POST or None, instance=obj) # custom fields update.
if form.is_valid() and form1.is_valid():
obj.Photo = form1.cleaned_data['Photo']
obj.dob = form1.cleaned_data['dob']
obj.country = form1.cleaned_data['country']
obj.State = form1.cleaned_data['State']
obj.District = form1.cleaned_data['District']
obj.phone = form1.cleaned_data['phone']
form.save()
form1.save()
messages.success(request, f'updated successfully')
return redirect('/profile1')
else:
messages.error(request, f'Please correct the error below.')
else:
form = UserProfileUpdateForm(instance=request.user)
form1 = UserProfileUpdateForm(instance=request.user)
return render(request, "authenticate\\editProfilePage.html", {'form': form, 'form1': form1})
I have an update button on my profile page, on clicking I could only see the "email" field with pre-populated data to update(I can update this default field successfully).
I have seen other stackoverflow posts, but they are not helping.
I am not able to figure out the mistakes.
Please help
Thank you,
I think the problem is in this line
obj = UserProfile.objects.get(id=request.user.id)
here left id is id from UserProfile model. so it will be something like this
obj = UserProfile.objects.get(user__id=request.user.id)

Why can not I submit a double form to the database

I created a form view and when I want to save a form with two modules I see "IntegrityError". Please help, Thank you in advance
class Place(models.Model):
LocalName = models.CharField('Nazwa Lokalu', max_length=200)
slug = models.SlugField('Link', max_length=100, default="")
LocalImg = models.ImageField('Zdjęcie Lokalu',
upload_to='Place/static/locals/img', blank=True, max_length=20000)
LocalAdress = models.CharField('Adres', max_length=500)
LocalNumberPhone = models.CharField('Numer telefonu', max_length=9)
LocalHours = models.TextField(verbose_name='Godziny otwarcia',
max_length=20000)
def get_aboslute_url(self):
return reverse("place:place_create", kwargs={'id': self.id})
class Meta:
verbose_name = "Lokal"
verbose_name_plural = "Lokale"
def __str__(self):
return self.LocalName
class Menu(models.Model):
place = models.ForeignKey(Place, on_delete=models.CASCADE,
related_name="place", default="")
Dinner = models.CharField("Nazwa potrawy",blank=True, default="",
max_length=200)
DinnerComponents = models.CharField("Składniki",blank=True, default="",
max_length=20009)
PizzaPrice = models.CharField("Rozmiar i cena Pizzy",
help_text="np.Mała-10zł", default="", blank=True, max_length=300)
Price = models.DecimalField("Cena",default="00", max_digits=5,
decimal_places=2)
class Meta:
verbose_name = "Menu"
verbose_name_plural = "Menu"
views.py
def create_place(request):
form = PlaceForm()
sub_form = MenuForm()
if request.POST:
form = PlaceForm(request.POST)
sub_form = MenuForm(request.POST)
if form.is_valid() and sub_form.is_valid():
place = form.save(commit=False)
place.location = sub_form.save()
place.save()
context = {
'form': form,
'sub_form': sub_form
}
return render(request, 'posts/layout.html', context)
Forms.py
class PlaceForm(forms.ModelForm):
class Meta:
model = Place
fields = ('LocalName', 'LocalAdress', 'LocalNumberPhone','LocalHours',)
class MenuForm(forms.ModelForm):
class Meta:
model = Menu
fields = ('Dinner','DinnerComponents','DinerCategory', 'Price',)
After filling in the form and clicking submit, an error will appear "NOT NULL constraint failed: posts_menu.place_id"
You have to first save a Place then assign the saved place to the Menu and finally save the menu.
if form.is_valid() and sub_form.is_valid():
place = form.save()
menu = sub_form.save(commit=False)
menu.place = place
menu.save()
That's because a Menu needs a place foreign key otherwise it cannot be saved.
(Note: why do you mix snake_case and CamelCase for your field names? It's terribly difficult to know how your model's properties are called. Python's convention is snake_case for all properties/methods/variables)

Save comment.id to another object

I want to save in my database the comment id which has been commented. For that I have two models: Comentario and Pregunta. Look below:
models.py
class Comentario (models.Model):
titulo = models.CharField(max_length=50)
texto = models.CharField(max_length=200)
autor = models.ForeignKey (Perfil, null=True, blank=True, on_delete=models.CASCADE)
fecha_publicacion = models.DateTimeField(auto_now_add=True)
tag = models.ManyToManyField(Tags, blank=True)
def __str__(self):
return (self.titulo)
class Pregunta (models.Model):
descripcion = models.CharField(max_length=150)
autor = models.ForeignKey (Perfil, null=True, blank=True, on_delete=models.CASCADE)
fecha_pregunta = models.DateTimeField(auto_now_add=True)
comentario_preguntado = models.ForeignKey(Comentario, null=True, blank=True, related_name="pregunta_set")
def __str__(self):
return (self.descripcion)
When a comment is commented I want to save the 'comentario' id as 'comentario_preguntado' id. For that I have created the next view:
views.py
def ComentarioListar2 (request):
aa=Puesto.objects.filter(nombre_puesto=request.user.nom_puesto).values_list('etiquetas')
bb=Tags.objects.filter(id__in=aa)
objects=Comentario.objects.filter(tag__in=bb).exclude(autor__id=request.user.id)
form = preguntaform(request.POST or None)
if request.method == 'POST' and form.is_valid():
form.instance.autor = request.user
form.instance.comentario_preguntado=request.comentario.id
form.save()
return render(request, 'home/comentario_listar.html', {'objects': objects, 'form': form})
urls.py
urlpatterns = [
url(r'^listar2$', views.ComentarioListar2, name="listar2"),
]
But I obtain this error "ComentarioListar2() missing 1 required positional argument: 'Comentario_id'"
I do not know how to save in the comentario_preguntado id the id of the comment it is commented (comentario_id).
thank you for your help
Your URL needs to be declared so that the primary key of the model instance can be referred to from the view.
It should be like this:
url(r'^listar2/(?P<Comentario_id>[0-9]+)/$', views.ComentarioListar2, name="listar2"),
So, an example of the URL would be /listar2/101/. Where 101 is the ID of your Comentario model instance.
Then, you can access it in the view with the function you have defined:
def ComentarioListar2 (request, Comentario_id):
^^^^^^^

Django Form Validators on Comparing One Object Against Another

I am creating a Non Disclosure Agreement form that a user fills out after registering and logging in. I am using a custom signup form with AllAuth and pre-populating parts of the form. I pre-populate the first and last name into the top part of the form as shown below in first screen shot, but as a part of the digital signature I am setting up; I need to validate the typed signature field matches the name of the first_name and the last_name concatenated together per the second screen-shot. I know I need to setup a validator based on Django Form & Field Validations and I've tried several things but just can't get my mind rapped around it. Any help putting this together would be huge...thank you.
My Models
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="profile", verbose_name="user")
...
class NonDisclosure(Timestamp):
profile = models.ForeignKey(Profile, on_delete=models.CASCADE, related_name="nda", verbose_name="profile")
user_signature = models.CharField(max_length=250, verbose_name='Signature')
user_street = models.CharField(max_length=250, verbose_name='Street Address')
user_city = models.CharField(max_length=250, verbose_name='City')
user_state = models.CharField(max_length=2, verbose_name='State Initials')
user_zip = models.IntegerField(verbose_name='Zip Code')
phone = models.CharField(max_length=25, verbose_name='Phone Number')
cash_on_hand = models.CharField(max_length=250, verbose_name='Cash on Hand')
value_of_securities = models.CharField(max_length=250, verbose_name='Value of Securities')
equity_in_real_estate = models.CharField(max_length=250, verbose_name='Equity on Real Estate')
other = models.CharField(max_length=250, verbose_name='Other Assets')
#property
def username(self):
return self.profile.username
#property
def first_name(self):
return self.profile.first_name
#property
def last_name(self):
return self.profile.last_name
#property
def email(self):
return self.profile.email
class Meta:
verbose_name = 'Non Disclosure Agreement'
verbose_name_plural = 'Non Disclosure Agreements'
def __str__(self):
return "%s" % self.profile
def get_absolute_url(self):
return reverse('nda_detail', args=[str(self.id)])
My Views:
class NonDisclosureForm(BaseModelForm):
cash_on_hand = forms.CharField(required=False)
value_of_securities = forms.CharField(required=False)
equity_in_real_estate = forms.CharField(required=False)
other = forms.CharField(required=False)
class Meta:
model = NonDisclosure
fields = ['user_signature', 'user_street', 'user_city', 'user_state', 'user_zip', 'phone', 'cash_on_hand', 'value_of_securities', 'equity_in_real_estate', 'other']
class NdaCreate(CreateView):
form_class = NonDisclosureForm
template_name = 'nda/nda_form.html'
def form_valid(self, form):
form.instance.profile = Profile.objects.get(user=self.request.user)
form.instance.created_by = self.request.user
return super(NdaCreate, self).form_valid(form)
Firstly, you should subclass ModelForm, not BaseModelForm. Write a clean_<fieldname> method for your user_signature field, and make sure that the value is as expected. You can access self.instance.created_by to check.
class NonDisclosureForm(ModelForm):
...
class Meta:
model = NonDisclosure
fields = ['user_signature', ...]
def clean_user_signature(self):
user_signature = self.cleaned_data['user_signature']
expected_name = '%s %s' % (self.instance.created_by.first_name, self.instance.created_by.last_name)
if user_signature != expected_name:
raise forms.ValidationError('Signature does not match')
return user_signature
Then you need to update your view so that it sets instance.created_by. You can do this by overriding get_form_kwargs.
class NdaCreate(CreateView):
def get_form_kwargs(self):
kwargs = super(NdaCreate, self).get_form_kwargs()
kwargs['instance'] = NonDisclosure(created_by=self.request.user)
return kwargs