I'm using Django to build a small system to control the lending and borrowing of some stuff our Students Café lend to students.
I'm having trouble identifying an object after a form submit, I want to mark the object as 'unaivalable' (disponible means available, so I want to set it to False) so next time someone comes to ask for THAT object, it will not show up in the 'lending' form.
All I need is a hint on how to achieve it, I've been looking through Django docs, and this site, with no success. Thanks in advance for the tips!
models.py
class Mate(models.Model):
color = models.CharField(max_length=2,
choices=COLOR_CHOICES, default=u'RO')
disponible = models.BooleanField(default=True)
def __unicode__(self):
return self.color
class Prestamo(models.Model):
cliente = models.ForeignKey(Usuario, null=False, blank=False)
mate = models.ForeignKey(Mate, null=False, blank=False)
termo = models.ForeignKey(Termo, null=False, blank=False)
bombilla = models.ForeignKey(Bombilla, null=False, blank=False)
fecha = models.DateTimeField(null=False, blank=False)
devuelto = models.BooleanField(default=False)
fecha_devolucion = models.DateTimeField(null=True, blank=True)
def __unicode__(self):
return str(self.pk)
views.py
#login_required
# Add_prestamo means 'Add lending' this basically deals with prestamo model, but i want to alter 'mate' objects here too.
def add_prestamo(request):
if request.method == 'POST':
form = PrestamoForm(request.POST,
auto_id=False, error_class=DivErrorList)
if form.is_valid():
prestamo = form.save(commit=False)
if request.POST.get('usuarios'):
miuser = request.POST.get('usuarios', '')
else:
miuser = ''
prestamo.cliente = Usuario.objects.get(nombre__exact=miuser)
# I KINDA NEED SOMETHING RIGHT HERE
prestamo.fecha = timezone.now()
prestamo.devuelto = False
prestamo.save()
return HttpResponseRedirect(reverse('list-prestamos'))
else:
form = PrestamoForm()
return TemplateResponse(request,
'gester/add_prestamo.html', {'form': form, })
add_prestamo.html
<form action="" method="post">
{% csrf_token %}
<table>
<tr>
<td>
<div class="ui-widget">
<label for="usuarios">Usuario: </label></td><td>
<input id="usuarios" name="usuarios">
</div>
</td>
</tr>
{{ form.as_table }}
</table>
<input class="btn" type="submit" value="Crear" />
</form>
In the template I show the form with a {{ form.as_table }} it display a select, but many of them (mates) have the same color, so when I get through POST in my view, how do I identify the exact object to alter the 'disponible' field value?
I really don't understand your codes but because you mention disponible, I hope this is what you mean.
prestamo.fecha = timezone.now()
prestamo.devuelto = False
//Because Prestamo model has a foreignkey for Mate model.
//The Mate model contains the disponible field which you want to access
// (to set it to False or unavailable)?
//This is how to access and update it.
prestamo.mate.disponible = False
prestamo.mate.save()
prestamo.save()
Related
This is my first post on StackOverflow. I'm also new to using Django (I'm actually using version 3.2). I have read about how to set the initial value of a field in a form using the initial parameter of a modelform_factory. I have followed several code examples but, the field does not display the value. My App uses the crispy_form plugin.
The matricula field in my model is the one I want to set up with a value that is taken from a query getting the total number of records in the teacher table plus 1.
When I load the page, the matricula field in the form does not display the desired value. what am I doing wrong?
Thanks for your help.
Sorry for my English. It is not very good. I hope you can understand me.
This is my code:
Model:
class docente(models.Model):
matricula = models.CharField(max_length=10, verbose_name="Matrícula", unique=True)
nombre = models.CharField(max_length=80)
apellidoPaterno = models.CharField(max_length=80, verbose_name=" Apellido Paterno")
apellidoMaterno = models.CharField(max_length=80, verbose_name="Apellido Materno", blank=True) # Campo opcional
direccion = models.CharField(max_length=150, verbose_name="Dirección", blank=True) # Campo opcional
telefono = models.CharField(max_length=13, verbose_name="Teléfono", blank=True) # Campo opcional
email = models.EmailField(verbose_name="Correo Electrónico", blank=True) # Campo opcional
colonia = models.CharField(max_length=150, blank=True) # Campo opcional
comunidad = models.CharField(max_length=150, blank=True) # Campo opcional
fecha_nacimiento = models.DateField(verbose_name="Fecha de Nacimiento", blank=True, null=True) # Campo opcional
estado_civil = models.ForeignKey(estado_civil, verbose_name="Estado Civil", on_delete=models.CASCADE)
profesion_ocupacion = models.CharField(verbose_name="Profesión/Ocupación", max_length=150, blank=True, null=True) # Campo opcional
ultimo_grado_estudios = models.ForeignKey(grado_estudios, verbose_name="Último Grado de Estudios", on_delete=models.CASCADE)
otros_estudios = models.ManyToManyField(otros_estudios, verbose_name="Otros estudios")
def __str__(self):
return self.nombre
Form:
class FormularioDocente(forms.ModelForm):
class Meta:
model = docente
fields = '__all__'
widgets = {
'matricula': TextInput(attrs={'readonly': 'readonly'})
}
View:
def nuevo_docente(request):
mensaje = "Nuevo Docente"
cuantos = docente.objects.count()
cuantos+=1
initial_data = {'matricula':cuantos}
formFormulario = modelform_factory(docente, form=FormularioDocente)
form = formFormulario(request.POST, initial=initial_data)
if request.method=='POST':
if form.is_valid():
form.save()
messages.success(request, MENSAJE_SUCCESS_FORMULARIO)
form = formFormulario() # Limpiar el formulario ya procesado y guardado
else:
messages.error(request, MENSAJE_ERROR_FORMULARIO)
messages.error(request, form.errors)
return render(request, 'escuela/nuevo_form.html', {'mensaje': mensaje, 'form':form})
Template:
{% extends 'escuela/base.html' %}
{%load crispy_forms_tags%}
{% block content %}
<div class="col-md-8 offset-md-2 ">
<h2>{{mensaje}}</h2>
</div>
<div class="main">
{% include 'escuela/messages.html' %}
<form method="POST" class="post-form">
{% csrf_token %}
<table class="table table-borderless table-responsive">
{{form|crispy}}
</table>
<br>
<button type="submit" id="boton-formulario" class="save btn btn-primary">Guardar</button>
</form>
</div>
{% endblock %}
When you pass request.POST to your form class, you're actually saying data=request.POST, which is overriding your initial values. This is because if you are not submitting a form then request.POST equals an empty dictionary, and data (even an empty dictionary of data) is used over initial values.
To counteract this, try:
form = formFormulario(request.POST or None, initial=initial_data)
An empty dictionary has a Falsey value, so here you are saying if request.POST is falsey, then data=None. In the absence of a dictionary, your initial values should be used instead.
I have a model called 'Competicion', with some objects and another model called 'Participante'. This second model has two fields: a foreignkey with the user and another foreingkey to 'Competicion'.
In the view, I've made queryset from 'Competicion' and with a for loop in the template I've given each object the button of the form.
With storing the user of the current session I have no problem but I want the form to know which object of the queryset it is to grab its id. #I have no problem with choices I just don't include them to save space
Models.py
class Competicion(models.Model):
ciudad = models.CharField(max_length=50, null=True, choices=Ciudades_a_elegir, default="Ninguna")
nombre = models.CharField(max_length=20, null=True, choices=Competiciones_a_elegir, default="Ninguna")
titulo = models.CharField(max_length=40, null=True)
fecha = models.DateField(null=True)
participantes = models.IntegerField(null=True)
flyer = models.ImageField(null=True, upload_to='imagenes', default='Ninguna')
def __str__(self):
return self.nombre + " " + self.titulo
class Participante(models.Model):
competicion = models.ForeignKey(Competicion, on_delete=models.CASCADE, null=True, blank=True)
participantes = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.competicion.nombre + " " + self.competicion.titulo
forms.py
class ParticipanteForm(ModelForm):
class Meta:
model = Participante
exclude = ['competicion', 'participantes']
views.py
def competiciones(request):
qs = Competicion.objects.all()
form = ParticipanteForm(request.POST or None)
if form.is_valid():
nombres = form.save()
nombres.competicion = ???#Help me
nombres.participantes = request.user
nombres.save()
return redirect('home')
context = {
'object_list':qs,
'form':form,
}
return render(request, "competiciones.html", context)
template
{% for i in object_list %}
<ul>
<li>{{i.nombre}}</li>
<li>{{i.ciudad}}</li>
<li>{{i.titulo}}</li>
<li>{{i.fecha}}</li>
<li>{{i.participantes}}</li>
{% if i.flyer %}
<img src="{{i.flyer.url}}" width="100px" >
{% endif %}
<li><form action="" method="POST">
{% csrf_token %}
<p> {{ form.competicion}} </p>
<p>{{form.participantes}}</p>
<input type="submit" name="Inscribirse" value="Inscribirse">
</form> </li>
</ul>
{% endfor %}
This is only like 1 course. In number one there is the different fields of the Competicion Model. And number two is the button of the form to the Participante Model, which fields are hidden and take the id of the course and the user. So I have a lot of these both courses displayed in the web. The function of the Particpante Model is to store the people who register in the course and the course itself.
def competiciones(request):
qs = Competicion.objects.all()
form = ParticipanteForm(request.POST or None)
if form.is_valid():
data = form.save()
data.participantes_id = request.user
for i in qs:
data.competicion_id = i.id
data.save()
return redirect('home')
I am using custom user authentication for verifying user. I have table named voter and I am tacking username and password via from and matching that with username and password of table if it match user will be logged in and allowed them to pass to next page which contain form. In that form I initiated data but it will not appear automatically it will appear only when i refresh the page
code of my files is bellow (for some big file only relevant code is included that's why it is partial)
model.py (partial)
class Voter(models.Model):
serial_voter_id = models.AutoField(primary_key=True)
voter_id = models.CharField(unique=True, max_length=10)
voter_name = models.CharField(max_length=255)
voter_constituency = models.ForeignKey(Constituency, models.DO_NOTHING, blank=True, null=True)
username = models.CharField(unique=True, max_length=32)
password = models.TextField()
voter_address = models.CharField(max_length=255, blank=True, null=True)
area = models.CharField(max_length=10, blank=True, null=True)
city = models.CharField(max_length=10, blank=True, null=True)
pincode = models.IntegerField(blank=True, null=True)
adhar_no = models.BigIntegerField(unique=True)
birth_date = models.DateField()
age = models.IntegerField()
fingerprint = models.TextField(blank=True, null=True)
authenticity = models.CharField(max_length=3, blank=True, null=True)
wallet_id = models.TextField()
class Meta:
managed = False
db_table = 'voter'
forms.py
from django import forms
from .models import Voter
class VoterForm(forms.ModelForm):
class Meta:
model = Voter
fields = [
'serial_voter_id',
'voter_id',
'voter_name',
'voter_constituency',
'username',
'voter_address',
'area',
'city',
'pincode',
'adhar_no',
'birth_date',
'age',
'authenticity',
'wallet_id'
]
views.py (partial)
from .models import Voter
from .forms import VoterForm
def voter_login(request, *args, **kwargs):
contex = {}
return render(request, "poll/voter_login.html", contex)
def voter_verification(request, *args, **kwargs):
f_username = request.POST.get('username')
voter = Voter.objects.get(voter_id=1) # thing need to be dynamic hear by replacing it with username
f_username = request.POST.get('username')
f_password = request.POST.get('password')
u_password = voter.password # fetching the password from voter object
u_password = u_password.decode() # decoding binary password to string
form = VoterForm(request.POST or None, instance=voter)
if form.is_valid():
form.save()
form = VoterForm()
contex = {
'voter' : voter,
'f_username' : f_username,
'f_password' : f_password,
'u_password' : u_password,
'form' : form
}
# compare hear username and password entered by user and from database if these are correcgt then allow this view or redirect to voter_login view
if voter.username == f_username and u_password == f_password:
return render(request, "poll/voter_verification.html", contex)
else:
return render(request, "poll/voter_login.html", {})
voter_login.html
{% extends 'header.html' %}
{% block content %}
<table>
<form method="get" action='voter_verification'> {% csrf_token %}
username <input type="text" name="username">
password <input type="password" name="password">
<input type="submit" name="login" value="login">
</form>
{% endblock %}
voter_verification.html (template file)
<!DOCTYPE html>
<html>
<body>
{% if f_username == voter.username and f_password == u_password %}
<h1>verified</h1>
{% else %}
<h1>wrong id and password</h1>
{% endif %}
<form method='post' action='vote_page'> {% csrf_token %}
{{ form.as_p }}
<input type='submit' value="sumbit">
</form>
</body>
</html>
changes query in view model ( def voter_verification(request, *args, **kwargs):)
def voter_verification(request, *args, **kwargs):
f_username = request.POST.get('username')
voter = Voter.objects.get(username=f_username)
then request user check in voter table which have exits with same user name.
Thanks to DrMaxwellEdison from reddit for providing answer
https://www.reddit.com/r/djangolearning/comments/fecn1f/question_django_data_in_form_only_appear_after/
Please do not have a separate model that stores usernames and passwords aside from your User model. You can simply add a OneToOneField to the User model to connect this Voter model to the authenticated User, and you don't need to do any extra data storage (plus, you are more likely to be handling the password information incorrectly, exposing it to being compromised if your site is breached).
Also per your comment on SO, the POST is not working because of CSRF protection (the traceback of your error would likely have indicated this already). Please see those docs for details on how to proceed (hint: do not disable CSRF!).
I've already read many other threads complaining about this error message but I still can't figure this out. I try removing the fields that give the error, and the error message just moves to another field the next time I try to submit. They are CharField, Foreign Key, and other types.
forms.py
class TemporaryresponseForm(forms.ModelForm):
gender_custom = forms.CharField(
required=False,
label="",
)
ethnicity = forms.ModelChoiceField(
queryset=Ethnicity.objects.all(),
widget=forms.RadioSelect(),
empty_label=None,
required=True,
label="Which of the following best describes your ethnicity?"
)
...
class Meta:
model = Temporaryresponse
fields = [...'gender_custom', 'ethnicity',...]
views.py
def tr(request):
if request.method == "POST":
form = TemporaryresponseForm(request.POST)
if form.is_valid():
tempresponse = form.save(commit=False)
tempresponse.ip = "123456"
tempresponse.save()
return redirect('politicalpollingapp/index.html')
else:
form = TemporaryresponseForm()
return render(request, 'politicalexperimentpollapp/tr.html', {'form': form})
def nr(request, pk):
return render(request, 'politicalexperimentpollapp/nr.html', {'tempresponse': tempresponse})
tr.html template
{% extends 'politicalexperimentpollapp/base.html' %}
{% block extrahead %}
{% load crispy_forms_tags %}
{{ form.media }}
{% endblock extrahead%}
...
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<div><br></div>
<div class="text-center"><button type="submit" class="save btn btn-primary">CONTINUE</button></div>
</form>
..
models.py
class Ethnicity(models.Model):
ethnicity = models.CharField(max_length=200)
def __str__(self):
return '%s' % (self.ethnicity)
...
class Temporaryresponse(models.Model):
birth_year = models.PositiveIntegerField()
voting_registration = models.ForeignKey(Voting_registration, models.SET_NULL, null=True)
party_identification = models.ForeignKey(Party_identification, models.SET_NULL, null=True)
gender = models.ForeignKey(Gender, models.SET_NULL, null=True)
gender_custom = models.CharField(max_length=200, blank=True)
ethnicity = models.ForeignKey(Ethnicity, models.SET_NULL, null=True)
race = models.ManyToManyField(Race)
zip_code = models.IntegerField()
ip = models.CharField(max_length=200, blank=True)
policy_areas_of_importance = models.ManyToManyField(Policy_category, blank=True)
likelihood_of_voting = models.PositiveIntegerField(models.SET_NULL, null=True, blank=True)
Oddly no error shows up in my Chrome console - it's only because I am showing errors on the actual page. I'm not sure if that's normal. Thanks in advance for any help, I'm ripping my hair out at this point.
I discovered that I was using the wrong language for the "race" form field. I had used ModelChoiceField but it should be ModelMultipleChoiceField as follows:
race = forms.ModelMultipleChoiceField(queryset=Race.objects.all(), widget=forms.CheckboxSelectMultiple, label="5. Which of the following best describes your race? Please select all that apply.")
I have Contestant model that has many-to-one relationship with Category. I want the creator of the award to only have access to last 15 categories of the award he has created in instantiating contestant model. That's, the multichoice queryset in the Contestant field(category) will only show the list of the last 15 categories being created in the Category Model. I have made different efforts, but the code is either not working or giving '['ManagementForm data is missing or has been tampered with']' error.
I have made countless re-factorization of codes and I have tried to adopt solutions I found on internet. But they didn't work.
# MY CATEGORY MODEL
class Category(models.Model):
award = models.ForeignKey(Award, on_delete=models.CASCADE)
award_category = models.CharField(max_length=150, blank=True, null=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def __str__(self):
return self.award_category
# MY CONTESTANT MODEL
class Contestant(models.Model):
award_name = models.ForeignKey(Award, on_delete=models.CASCADE)
contestant_name = models.CharField(max_length=150, null=True, blank=True )
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='contestants')
vote = models.IntegerField()
def number_of_vote(self):
return Contestant.objects.filter(self.vote).count()
vote_count = property(number_of_vote)
#MY VIEW
def get_award(request, pk):
new_award = get_object_or_404(Award, pk=pk)
Contest_Formset = modelformset_factory(Contestant, fields('contestant_name', 'category',), extra=15)
formset = Contest_Formset(request.POST)
for form in formset:
form.fields['category'].queryset = Category.objects.filter(user=request.user)[1:15]
if request.method == 'POST' and form.is_valid():
myform = form.save(commit=False)
myform.award_name = new_award
myform.save()
return redirect('award_details', pk=new_award.pk)
else:
formset = Contest_Formset()
context = {
'new_award': new_award,
'formset': formset
}
return render(request, 'voting/get_award.html', context)
# TEMPLATE
<form action=" " method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{{ formset }}
<input type="submit" value="save">
</form>
I expect the output of the contestant's category field to show only the last 15 categories created by the login user.