How to add condition to a manytomany relationship - django

I'm a little new to Django, so my question may be basic, but bare with me. Let's say I'm sharing my posts with some of my friends (who are manytomany relation with the post), but also giving an extra condition for whether they can comment on it, or not. This condition, together with the name of the user to be shared with are submitted through a forum. Now my problem is that I don't know how/where to save this condition. I will show you some of my code.
Models.py
class Task(models.Model):
name = models.CharField(max_length=50)
text = models.TextField()
deadline = models.DateTimeField()
created = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='taskset')
shared = models.ManyToManyField(User, blank=True, related_name = 'shared_list')
def __str__(self):
return f"{self.name}-{self.user.username}"
class Comment(models.Model):
text = models.TextField()
task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='comments')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comments')
created = models.DateField(auto_now_add=True)
def __str__(self):
return f"{self.user.username}-{self.task}"
Share form html
{% extends 'base.html'%}
{% load crispy_forms_tags %}
{% block content %}
<h3>Enter the Username of the Friend you want to share with</h3>
<form method="POST">
{% csrf_token %}
{{form|crispy}}
<input type="submit", value="Share">
</form>
{% endblock content %}
And the view processing it
def share(request, id):
task = Task.objects.get(id = id)
if request.method == 'POST':
share_with = User.objects.get(username = request.POST['username'])
if share_with is not None:
task.shared.add(share_with)
task.save()
return redirect('index')
else:
form = ShareForm()
return render(request, 'share.html', {'form':form})
Thanks a lot, I've been stuck for two hours, PLEASE HELP!

Related

How can I get the ids of a queryset from a model and store them into a different model using a form?

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')

How to display A only a users entered data related in a foreignkey on detailview in django

I am building this simple quiz app. This app allows all users to submit an answer to an assignment in Docx format. I what that any time a user views the question on the DetailView page, if the user has already submitted a solution for that assignment, that solution should be shown on the DetailView page as well. Current I get is all that answers submitted by all users. I only want a user's answer to that assignment on the detailpage
this is my model.
class Assignment(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=500)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
class_or_level = models.ForeignKey(StudentClass, on_delete=models.CASCADE)
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
Text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
date_expire = models.DateTimeField()
def __str__(self):
return self.title
class Answer(models.Model):
slug = models.SlugField(max_length=500)
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
student = models.ForeignKey(User, on_delete=models.CASCADE)
file = models.FileField(upload_to='assignment')
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{} - {} '.format(self.assignment, self.student)
Below is my view
class AssignmentSubmitView(DetailView):
model = Assignment
template_name = 'assignment_submit.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['student_answer'] = self.object.answer_set.all()
return context
Below is my filter on detailview template.
{% for answer in student_answer %}
{{ answer.file }}
{% endfor %}
You will need to first of all know the user that is accessing that page, so i presume you have a user model and an authentication system in place.
in the views
class AssignmentSubmitView(DetailView):
model = Assignment
template_name = 'assignment_submit.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['student_answer'] = self.object.answer_set.filter()#then filter and get the answer specific to that user here (depending on your user and Assignment models)
return context
and in your templates
{% if user.is_authenticated %}
{% if student_answer %}
{% for answer in student_answer %}
{{ answer.file }}
{% endfor %}
{% endif %}
{% endif %}

django data in form only appear after refresh

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!).

Every field in Django modelform shows "Select a valid choice. That choice is not one of the available choices."

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.")

Django Formset: multichoice queryset filter is not working for my formset after many attempts

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.