I am trying to add a checkbox that if ticked will make a attribute in my model false.
My model is:
class Topic(models.Model):
"""A topic the user is learning about"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User)
public = False
My forms.py (where the checkbox should go) is:
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
And my function:
def topics(request):
"""Show all topics."""
topics = Topic.objects.filter(owner=request.user).order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
Could you please tell me what I need to change in order that when a checkbox in forms is checked, the public variable becomes True, and then the function Topics displays public topics as well as just the owners.
Thanks
Milo
The models.BooleanField renders itself as a checkbox. Is either True or False. So:
# models.py
class Topic(models.Model):
# ...
public = models.BooleanField(default=True)
# forms.py
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ["text", "public"]
labels = {"text": "", "public": "label for public"}
If you want to also accept null values, then you should use models.NullBooleanField.
Related
I'm beginner in Django/Python and I need to create a multiple select form. I know it's easy but I can't find any example. i use django-taggit.i want to select multiple tag in tag form.
here is my forms.py
class BlogPostForm(ModelForm):
class Meta:
model = BlogPost
fields = ("title","body","tags")
widgets ={
'title' : TextInput(attrs={'class':'form-control ' ,'placeholder':'Title'}),
'body' : TextInput(attrs={'class':'form-control'}),
}
here is my models.py
class BlogPost(models.Model):
title = models.CharField( max_length=100,unique=True)
body = RichTextField()
date = models.DateTimeField(default=timezone.now)
slug = models.SlugField()
tags = TaggableManager()
# class Meta:
# verbose_name = ("BlogPost")
# verbose_name_plural = ("BlogPosts")
def __str__(self):
return self.title
You can use ModelMultipleChoiceField to select multiple tag in tag form, like this:
tags = forms.ModelMultipleChoiceField(label='Tags', queryset=Tag.objects.all())
queryset:
A QuerySet of model objects from which the choices for the field are derived and which is used to validate the user’s selection. It’s evaluated when the form is rendered.
if you have the model about Tag, it can try the example code.
More information can be found here:
https://docs.djangoproject.com/en/4.1/ref/forms/fields/#modelchoicefield
I'm trying to build my own poll app and the models have a lot of relation with each other and I need to count how many objects are in relation with some other objects so I need these custom function for it
Here's the model with the custom functions:
class Poll(models.Model):
title = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)
is_available = models.BooleanField(default=True)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
#property
def total_votes(self):
votes = 0
for o in self.option_set.all():
votes = votes + o.how_much_vote
return votes
#property
def users_involved(self):
list = []
for o in self.option_set.all():
for v in o.vote:
list.append(v.user)
return list
#property
def users_involved(self):
users = []
for o in self.option_set.all():
for v in o.who_voted:
users.append(v)
return users
#property
def total_votes_each_option(self):
dct = {}
for o in self.option_set.all():
dct[o.title]= o.how_much_vote
return dct
My question is how do you include all of those custom functions total_votes, users_involved, etc to my api? because right now my api looks something like this:
{
"id": 1,
"title": "Which is the best frontend framework?",
"is_active": true,
"is_available": true,
"date_created": "2021-07-13T14:08:17.709054Z"
}
which is expected but I want to know how do I add those extra value to make it look like this
{
"id": 1,
"title": "Which is the best frontend framework?",
"is_active": true,
"is_available": true,
"date_created": "2021-07-13T14:08:17.709054Z",
"total_votes": "some number",
"users_involved": [...users]
}
Edit: here's my serializer class
class PollSerializer(serializers.ModelSerializer):
class Meta:
model = Poll
fields = '__all__'
Thank you very much
Simple way we can use SerializerMethodField
from rest_framework import serializers
class PollSerializer(serializers.ModelSerializer):
total_votes = serializers.SerializerMethodField()
users_involved = serializers.SerializerMethodField()
class Meta:
model = Poll
fields = (
'id',
'title',
'is_active',
'is_available',
'date_created',
'total_votes',
'users_involved',
)
def get_total_votes(self, poll):
return poll.total_votes
def get_users_involved(self, poll)
return poll.users_involved
Please note that SerializerMethodField is read_only, cannot for write.
Also make sure your custom model functions well for loop processing, using select_related or prefetch_related.
This one should be easy, you can add addition fields in Serializers by mentioning the field_name and its type before class Meta: something like this.
Model Upload
class Upload(models.Model):
.
.
total_files = models.IntegerField(default=0,null=True,blank=True)
.
.
def add(self):
return (self.total_files + 2)
Serializer FileSerializer
class FileSerializer(serializers.ModelSerializer):
#This is the line you need to add
extra_add = serializers.IntegerField(source = 'add')
class Meta:
model = Upload
fields= ['id','name','uploaded','total_files','created_on','updated_on','extra_add']
Then mention your extra_add field name in fields[..,..,'extra_add'].
You can change the type of field while mentioning the field thereserializer.<field_type>(source='<method_name>').
Result of the Above field i added:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username')
class PollSerializer(serializers.ModelSerializer):
total_votes = serializers.IntegerField(read_only=True)
users_involved = UserSerializer(read_only=True, many=True)
class Meta:
model = Poll
fields = '__all__'
#staticmethod
def setup_eager_loading(queryset):
return queryset.prefetch_related('option_set')
Also note that you defined users_involved twice in your Pool class.
You can use PoolSerializer.setup_eager_loading function in your view/viewset for better db query performance but it's not necessary (I do it in viewset.get_queryset method like self.queryset = self.serializer_class.setup_eager_loading(self.queryset).
I have a simple Django 3.1.0 app I need to create in order to assign Tasks with Tags (or assign tags into tasks).
My Model
class Task(models.Model):
user = models.CharField(max_length=33)
time = models.DateTimeField(auto_now_add=True)
task = models.CharField(max_length=500)
tags = models.ForeignKey('Tag', on_delete=models.SET_NULL, null=True)
class Tag(models.Model):
tag = models.CharField(max_length=30, default="No Tag")
members = models.ManyToManyField('Task')
class Meta:
verbose_name = "tag"
verbose_name_plural = "tags"
My Form
class TaskForm(ModelForm):
class Meta:
model = Task
fields = ['user', 'task', 'tags']
template_name = 'tasks.html'
tags = ModelMultipleChoiceField(
queryset=Tag.objects.values().all(), widget=CheckboxSelectMultiple()
)
My View
def main(request):
model = Task.objects.values().all()
form = TaskForm()
con = {'context': list(model), 'form': form}
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
form.save_m2m()
return redirect('/')
else:
form = TaskForm()
return render(request, "tasks.html", con)
The migrations are successfull, and with the above code, the view shows a checkbox list with the fetched tags, but the problem is that when I hit Submit on the form, the values are not saved/written on the database but the page reloads successfully.
However, if I turn the following:
obj = form.save(commit=False)
form.save_m2m()
into
form.save(commit=True)
#form.save_m2m()
the values are written only from the fields 'user', 'task' - without the 'tags'
It's also funny that what fetches back on the webpage as values of the tags is in the shape of:
[checkbox] {'id': 1, 'tag': 'aks'}
What am I doing wrong? Thanks.
UPDATE after a comment below:
As Abdul Aziz suggested, I had to remove the values() from the queryset. But after that , to make it work, I had to add also:
In the model:
tag = models.CharField(max_length=100, default="No Tags")
and then refer to that one in the form and Vue template.
You have a ForeignKey set to the Tag model on your Task model, when you actually want a ManyToMany relationship between them. Remove the foreign key and set a related_name to the ManyToManyField in the Tag model like so:
class Task(models.Model):
user = models.CharField(max_length=33)
time = models.DateTimeField(auto_now_add=True)
task = models.CharField(max_length=500)
class Tag(models.Model):
tag = models.CharField(max_length=30, default="No Tag")
members = models.ManyToManyField('Task', related_name="tags")
class Meta:
verbose_name = "tag"
verbose_name_plural = "tags"
Also in your form you have:
tags = ModelMultipleChoiceField(
queryset=Tag.objects.values().all(), widget=CheckboxSelectMultiple()
)
Why are you using values here? Remove it:
tags = ModelMultipleChoiceField(
queryset=Tag.objects.all(), widget=CheckboxSelectMultiple()
)
I have the following models:
class Property(models.Model):
user = models.ForeignKey(User)
id = models.CharField(max_length=20, null=True)
class Property_Value(models.Model):
id = models.ForeignKey(Property)
amount = models.DecimalField(max_digits = 10, decimal_places
How do I access the Property_Value.amount via Property on the admin page?
I have this so far...
class PropertyAdmin(admin.ModelAdmin):
list_display = ('id', 'user', 'property_value')
def property_value(self, obj):
return obj.id.amount
class Meta:
model = Property
admin.site.register(Property, PropertyAdmin)
You're interacting, in that instance, with a Property object (since you defined that in the Meta) - syntax is the same as elsewhere in Django. So it would be obj.property_value.amount. If you're using PyCharm, you can get autocomplete for the field by telling PyCharm what 'obj' is, like so:
def property_value(self, obj: Property):
I am trying to sort out a specific problem that involve "many2many" relationship using through specification.
I've already tried to use inline_factory but I was not able to sort out the problem.
I have these tables
class Person(models.Model):
id = models.AutoField(primary_key=True)
fullname = models.CharField(max_length=200)
nickname = models.CharField(max_length=45, blank=True)
class Meta:
db_table = 'people'
class Role(models.Model):
role = models.CharField(max_length=200)
class Meta:
verbose_name_plural = 'roles'
db_table = 'roles'
class Study(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255)
description = models.CharField(max_length=1000)
members = models.ManyToManyField(Person, through='Studies2People')
class Meta:
db_table = 'studies'
class Studies2People(models.Model):
person = models.ForeignKey(Person)
role = models.ForeignKey(Role)
study = models.ForeignKey(Study)
class Meta:
verbose_name_plural = 'studies2people'
db_table = 'studies2people'
unique_together = (('person', 'role', 'study'),)
#forms.py
from .models import Study, Person, Role, Studies2People
class RegisterStudyForm(ModelForm):
class Meta:
model = Study
fields = '__all__'
#View.py
class StudyCreateView(CreateView):
template_name = 'managements/register_study.html'
model = Study
form_class = RegisterStudyForm
success_url = 'success/'
def get(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
return self.render_to_response(self.get_context_data(form=form))
The code above creates a form like:
Study.Title
Study.description
List of People
I want to create a form to fill in all fields that involve Studies2People Something like this:
Study.Title
Study.description
Combo(people.list)
Combo(Role.list)
Maybe I should start from Studies2People but I don't know how to show the "inline" forms involved.
Thanks in advance
C.
waiting someone that is able to explain with some examples the relationship m2m with through (model & view), I sorted out my problem in a different way.
I've created three forms.
1 Model Form (study)
2 Form (forms with ModelChoiceField(queryset=TableX.objects.all())
Created a classView to manage the get and post action.(validation form too)
In the post procedure I used "transaction" to avoid "fake" data.
I hope that someone will post an example with complex m2m relationships.
Regards
Cinzia