I created a model object.
This object has several boolean fields.
# models.py
class TeamCharacteristic(models.Model):
team = models.ForeignKey('Teams',on_delete=models.CASCADE)
power1 = models.BooleanField(null=True, blank=True)
power2 = models.BooleanField(null=True, blank=True)
power3 = models.BooleanField(null=True, blank=True)
power4 = models.BooleanField(null=True, blank=True)
power5 = models.BooleanField(null=True, blank=True)
class Meta:
verbose_name = 'Team style'
verbose_name_plural = 'Teams style'
def __str__(self):
return "{} 's style".format(
self.team,
)
Some of them are right and others are wrong.
I want to show only the fields that have the correct value in the template.
How can I do this in a shorter way instead of checking each field individually?
# views.py
from django.shortcuts import render, get_object_or_404
from .models import Matches
from denemee.apps.home.models import TeamCharacteristic
def matches_details(request, page_id=None, team=None, **kwargs):
m_detail = get_object_or_404(Matches, id=page_id)
home_team_chr = get_object_or_404(TeamCharacteristic, team=m_detail.h_team)
away_team_chr = get_object_or_404(TeamCharacteristic, team=m_detail.a_team)
payload = {
'm_detail': m_detail,
'home_team_chr': home_team_chr,
'away_team_chr': away_team_chr
}
return render(request, 'match_detail.html', payload)
You can send your home_team_chr and home_team_chras serialized objects and then iterate over the fields and check for the True values in booleans.
Check out this answer for more details.
Related
I am quite new with Django and I need help.
My problem is quite similar what Mike had in his case:
UpdateView not populating form with existing data, but I have not found solution yet.
My goal is to view owner dropdown selection list only those users who are members of the organization.
models.py
# organizations.models.py
...
from accounts.models import User
from core.models import TimeStampModel
...
class Organization(TimeStampModel, models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(
verbose_name=_('Name'),
max_length=255,
unique=True
)
code = models.CharField(
verbose_name=_('Code'),
max_length=255,
null=True,
blank=True
)
owner = models.ForeignKey(
User,
on_delete=models.PROTECT,
verbose_name=_('Owner'),
related_name='owner',
help_text=_('Organization Owner and Contact Person'),
)
slug = models.SlugField(verbose_name=_('Organization key'), unique=True)
...
class Meta:
verbose_name = _('Organization')
verbose_name_plural = _('Organization')
ordering = ['name', 'code']
def __str__(self):
return f'{self.name}, {self.code}'
# Create automatically slug value from organization name field.
# In case similar is exist then add extra count digit end of slug.
def _get_unique_slug(self):
slug = slugify(self.name)
unique_slug = slug
num = 1
while Organization.objects.filter(slug=unique_slug).exists():
unique_slug = '{}-{}'.format(slug, num)
num += 1
return unique_slug
def save(self, *args, **kwargs):
if not self.slug:
self.slug = self._get_unique_slug()
self.next_update = timezone.now() + relativedelta(
months=self.update_interval)
super(Organization, self).save(*args, **kwargs)
def get_absolute_url(self):
kwargs = {
'slug': self.slug
}
return reverse('organization_main_page', kwargs=kwargs)
class OrganizationMembers(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
organization = models.ForeignKey(
Organization,
on_delete=models.CASCADE,
verbose_name=_('Organization')
)
member = models.ForeignKey(
User,
on_delete=models.CASCADE,
verbose_name=_('Member'),
null=True,
blank=True
)
organization_admin = models.BooleanField(
verbose_name=_('Organization admin'),
default=False
)
class Meta:
verbose_name = _('Organization: Member')
verbose_name_plural = _('Organization: Members')
ordering = ['organization', 'member']
unique_together = ('organization', 'member')
def __str__(self):
return f'{self.member}'
def get_absolute_url(self):
kwargs = {
'slug': self.slug
}
return reverse('organization_detail', kwargs=kwargs)
forms.py
# organizations.forms.py
....
from accounts.models import User
from .models import Organization, OrganizationMembers
...
class OrganizationUpdateForm(forms.ModelForm):
class Meta:
model = Organization
fields = '__all__'
exclude = ('date_created', 'created_by', 'created_by_id',
'last_updated', 'last_updated_by', 'last_updated_by_id',
'next_update', 'slug')
# Restrict user selection lists to view only members of the organization
def __init__(self, *args, **kwargs):
inst = kwargs.get('instance', None)
super(OrganizationUpdateForm, self).__init__(*args, **kwargs)
self.fields['owner'].queryset = OrganizationMembers.objects.\ # <--- !!!
filter(organization_id=inst.id)
In the forms.py, if I comment out self.field['owner]... line, then owner field will show saved value from database, but then I can see all users in the dropdown list. When queryset is enabled then selection list show correct users, but saved value is not visible.
views.py
# organizations.views.py
from .forms import OrganizationUpdateForm
from accounts.models import User
from .models import Organization, OrganizationMembers
class OrganizationUpdateView(LoginRequiredMixin, UpdateView):
model = Organization
form_class = OrganizationUpdateForm
template_name = 'organizations/organization_update.html'
success_url = reverse_lazy('organizations')
# Save data and set current user to last updated by fields
def form_valid(self, form):
object = form.save(commit=False)
object.last_updated_by = self.request.user.get_full_name()
object.last_updated_by_id = self.request.user
return super(OrganizationUpdateView, self).form_valid(form)
def get_queryset(self):
criteria1 = Q(owner=self.request.user)
criteria2 = Q(organizationmembers__member=self.request.user)
criteria3 = Q(organizationmembers__organization_admin=1)
org_list = Organization.objects.\
filter(criteria1 | (criteria2 & criteria3)).distinct()
if org_list.count() != 0:
return org_list
else:
raise Http404('You don\'t have permissions!')
In Mikes case Chiheb has commented that "With UpdateView it's a little bit tricky. So, in order to initialize your form's data, you need to do it in the view itself not in the form."
What is the reason that cannot add filter to UpdateView?
Please can someone help me to solve my problem. Thanks.
UPDATE
Not filtered. Value from database is visible
Not filtered. Dropdown list show all users in the system
Filter enabled. Value is not visible
Filter enabled. Dropdown list show correct valeus
The problem is that owner in your models is a FK to User model, but you are filtering queryset in form by OrganizationMembers. Make it the same and the problem should be gone.
I am trying to save data from my Django Admin to my database but somehow it is not happening. I have created a form in one of my apps which my admin uses.I am new to Django and any help would be greatly appreciated.
Below is the relevant code:
models.py
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django_countries.fields import CountryField
from django.db import models
class UserProfile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=100)
bio = models.TextField(max_length=1000, blank=True, null=True)
image = models.FileField()
country = CountryField()
city = models.CharField(max_length=100)
twitter = models.CharField(max_length=100, null=True, blank=True)
linkedin = models.CharField(max_length=100, null=True, blank=True)
location = models.TextField()
def __unicode__(self):
return self.name
def __str__(self):
return self.name
class Mentor(models.Model):
mentor = models.CharField(max_length=100)
mentee = models.CharField(max_length=100)
def __unicode__(self):
return self.mentee
def __str__(self):
return self.mentee
forms.py
from django import forms
from models import UserProfile, Mentor
from django_countries.fields import CountryField
from django.contrib.auth.models import User
from reports.models import Reports
class UserProfileForm(forms.ModelForm):
name = forms.CharField(max_length=100)
bio = forms.Textarea()
image = forms.FileField(label='Profile Photo')
country = CountryField(blank_label='(Select Country)')
city = forms.CharField(max_length=100)
twitter = forms.CharField(max_length=100, required=False)
linkedin = forms.CharField(max_length=100, required=False)
class Meta:
model = UserProfile
exclude = ('user',)
class MentorForm(forms.ModelForm):
mentor_choices = tuple(UserProfile.objects.filter(user__is_staff=1).order_by('name').values_list('name', 'name'))
mentee_choices = tuple(UserProfile.objects.exclude(user__is_staff=1).order_by('name').values_list('name', 'name'))
mentor_name = forms.ChoiceField(choices=mentor_choices)
mentee_name = forms.ChoiceField(choices=mentee_choices)
def save(self, commit=True):
mentor_name = self.cleaned_data.get('mentor_name', None)
mentor_name = self.cleaned_data.get('mentee_name', None)
return super(MentorForm, self).save(commit=commit)
class Meta:
model = Mentor
fields= ('mentor_name', 'mentee_name')
admin.py
from django.contrib import admin
from .models import UserProfile, Mentor
from.forms import MentorForm
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('user',)
search_fields = ['user']
def save_model(self, request, obj, form, change):
obj.created_by = request.user
obj.save()
admin.site.register(UserProfile, UserProfileAdmin )
class MentorAdmin(admin.ModelAdmin):
list_display = ('__unicode__','mentee')
search_fields = ['mentee', 'mentor']
form = MentorForm
fieldsets = (
(None,{
'fields': ('mentor_name', 'mentee_name'),
}),
)
def save_model(self, request, obj, form, change):
super(MentorAdmin, self).save_model(request, obj, form, change)
admin.site.register(Mentor, MentorAdmin )
The UserProfile works perfectly but the Mentor form in admin doesn't save anything in the database. It creates blank entries into the database, so I know that the front and backend are talking but no data is being passed. Any help will be very helpful
def save(self, commit=True):
# here you define `mentor_name`. OK.
mentor_name = self.cleaned_data.get('mentor_name', None)
# here you redefine `mentor_name`. I guess it is a typo and should be `mentee_name`.
mentor_name = self.cleaned_data.get('mentee_name', None)
# And... you don't do anything with these variables.
return super(MentorForm, self).save(commit=commit)
This method is equivalent to:
def save(self, commit=True):
return super(MentorForm, self).save(commit=commit)
Which is equivalent to not overriding the save method at all.
And what about this?
def save_model(self, request, obj, form, change):
super(MentorAdmin, self).save_model(request, obj, form, change)
What is the purpose of overriding a method and only calling the parent method with the exact same arguments?
But the actual issue is here:
mentor_choices = tuple(UserProfile.objects.filter(user__is_staff=1).order_by('name').values_list('name', 'name'))
mentee_choices = tuple(UserProfile.objects.exclude(user__is_staff=1).order_by('name').values_list('name', 'name'))
mentor_name = forms.ChoiceField(choices=mentor_choices)
mentee_name = forms.ChoiceField(choices=mentee_choices)
class Meta:
model = Mentor
fields = ('mentor_name', 'mentee_name')
You use a ModelForm but none of the Mentor's fields is in fields. What are you expecting this to do other than saving a row with Mentor.mentor = None and Mentor.mentee = None. You don't even mention those fields.
And why are you using CharField for Mentor.mentor and Mentor.mentee while you likely want a foreign key.
class Mentor(models.Model):
mentor = models.ForeignKey(UserProfile, models.PROTECT,
related_name='mentees')
mentee = models.ForeignKey(UserProfile, models.PROTECT,
related_name='mentors')
class MentorForm(forms.ModelForm):
class Meta:
model = Mentor
fields = ('mentor', 'mentee')
mentor = forms.ModelChoiceField(queryset=UserProfile.objects.filter(
user__is_staff=True).order_by('name'))
mentee = forms.ModelChoiceField(queryset=UserProfile.objects.exclude(
user__is_staff=True).order_by('name'))
Or even better:
class Mentor(models.Model):
mentor = models.ForeignKey(
UserProfile, models.PROTECT, related_name='mentees',
limit_choices_to={'user__is_staff': True},
)
mentee = models.ForeignKey(
UserProfile, models.PROTECT, related_name='mentors',
limit_choices_to={'user__is_staff': False},
)
Which avoids you to create a form.
I have the following code:
models.py
from django.db import models
from parler.models import TranslatableModel, TranslatedFields
class Federation(TranslatableModel):
translations = TranslatedFields(
name = models.CharField('name', max_length=50)
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Athlete(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
federation = models.ForeignKey('Federation', on_delete=models.SET_NULL, null=True)
height = models.IntegerField();
weight = models.IntegerField();
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
admin.py
from django.contrib import admin
from parler.admin import TranslatableAdmin
from .models import Athlete, Federation
class AthleteAdmin(admin.ModelAdmin):
list_display = ['first_name', 'last_name', 'height', 'weight', 'get_federation_name']
fields = ['first_name', 'last_name', 'height', 'weight', 'federation']
def get_federation_name(self, obj):
obj.federation.set_current_language('en')
return obj.federation.name
get_federation_name.short_description = 'Federation'
class FederationAdmin(TranslatableAdmin):
search_fields = ['translations__name']
list_display = ['name']
fields = ['name']
admin.site.register(Federation, FederationAdmin)
admin.site.register(Athlete, AthleteAdmin)
The federation field is shown as a list but the text in the select menu is shown as "Federation object." For the list, I created a function to fetch the data from related Federation model's translation relation. I want to do the same with the form fields. If I get this to work in form fields without a function, I will also change the list display to work the same way.
I am new to Python and Django (first time) and I can't seem to find a solution to this problem.
Thank you!
By default it uses the __str__() method of the object. So the easiest way to change this is to set this method. For instance:
class Federation(models.Model):
...
def __str__(self):
return "{0} ({1})".format(self.translation, self.created_at)
Another way — if you don't want to override the __str__ method — would be to override the label_from_instance of the form Field itself. But it's more tricky.
def _federation_label_from_instance(self, obj):
return "{0} ({1})".format(obj.translation, obj.created_at)
class AthleteAdmin(admin.ModelAdmin):
...
def formfield_for_foreignkey(self, db_field, request, **kwargs):
formfield = super().form_field(db_field, request, **kwargs)
if db_field.name == 'federation':
formfield.label_from_instance = _federation_label_from_instance
return formfield
I tried to find out how to set the initial value of a ModelChoiceField, I found many answers to this question but I don't really get them. I understand that I can set "initial" when calling the form in admin.py but then a model instance is mentioned and I am lost.
This is my models.py
class Articles(models.Model):
headline = models.CharField('Rubrik', max_length=200)
category = models.CharField('Kategori', max_length=200, blank=True)
extract = models.TextField('Utdrag')
image = ImageField('Bild', upload_to='articles', blank=True, default="")
text = RichTextUploadingField('Text', blank=True, default="")
added = models.DateTimeField('Publicerad', default=timezone.now, blank=True)
updated = models.DateTimeField('Uppdaterad',auto_now=True)
frontpage = models.BooleanField('Visa på startsida', default=True)
active = models.BooleanField('Aktiv', default=False)
def save(self, *args, **kwargs):
if self.added is None:
self.added = timezone.now
super(Articles, self).save(*args, **kwargs)
def __unicode__(self):
return '%s' % (self.headline)
class Meta:
verbose_name = "artikel"
verbose_name_plural = "Artiklar"
This is my forms.py
class ArticleForm(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Menu.objects.order_by('name').filter(category=True))
This is my admin.py
class ArticlesAdmin(admin.ModelAdmin):
form = ArticleForm
list_display = ('headline','category', 'extract', 'image', 'added', 'updated', 'frontpage', 'active')
admin.site.register(Articles, ArticlesAdmin)
When I edit the article in the admin section I want the stored value of the category to be the initial value for the ModelChoiceField. Do you get what I mean?
In admin.py there should be something like:
form = ArticleForm(initial = {'category': instance.something})
*EDIT: I added ForeignKey as suggested
category = models.ForeignKey(Menu)
and admin.py looks like this:
class ArticlesAdmin(admin.ModelAdmin):
form = ArticleForm
list_display = ('headline','category', 'extract', 'image', 'added', 'updated', 'frontpage', 'active')
And now it's working as expected!
This code should work:
form = ArticleForm(initial = {'category': pk})
pk is the stored value, pk = primary key
It's a sort of cms type application
I have an article model and some specializations in models.py
class Article(models.Model):
foo = models.CharField(max_length=50)
bar = models.CharField(max_length=100,blank=True)
DISPLAY_CHOICES = (
('N', 'None'),
('C','Carousel'),
('M','Marketing'),
('F','Featurette')
)
display = models.CharField(max_length=1, choices = DISPLAY_CHOICES)
def __unicode__(self):
return self.title
class Artist(Article):
website = models.URLField(max_length=200,blank=True)
class Venue(Article):
location = models.CharField(max_length=150)
map_link = models.URLField(max_length=200,blank=True)
class Event(Article):
time = models.DateTimeField()
venue = models.ForeignKey(Venue)
performers = models.ManyToManyField(Artist)
I want to render these in different ways depending on the value of article.display but when I call
articles.objects.all()
I still need the extra attributes form the subclasses so I wrote
#views.py
def castToSubClass(article):
try:
return Artist.objects.get(article_ptr_id = article.id)
except:
try:
return Event.objects.get(article_ptr_id = article.id)
except:
try:
return Venue.objects.get(article_ptr_id = article.id)
except:
return article
def index(request):
carousel = [castToSubClass(article) for article in Article.objects.filter(display='C']
marketing = [castToSubClass(article) for article in Article.objects.filter(display='M'[:3]]
featurettes = [castToSubClass(article) for article in Article.objects.filter(display='F']
return render_to_response('frontpage.html',
{
'carousel': carousel,
'marketing':marketing,
'featurettes': featurettes
})
to turn them all in the appropriate subclass object, this apart from seeming clunky seems to mean I'm hitting the database twice for every (or nearly every) item in the queryset.
Is there a way to do this in the initial calls to the manager instead?
Thanks.
Use one model to store everything, and add a field to distinguish the article type, so that you can render different look for every type combine with display in the template(Like tumblr do).
class Article(models.Model):
foo = models.CharField(max_length=50)
bar = models.CharField(max_length=100,blank=True)
DISPLAY_CHOICES = (
('N', 'None'),
('C','Carousel'),
('M','Marketing'),
('F','Featurette')
)
display = models.CharField(max_length=1, choices = DISPLAY_CHOICES)
ARTICLE_TYPE_CHOICES = (
('artist', 'Artist'),
('venue', 'Venue'),
('event', 'Event'),
)
type = models.CharField(max_length=32, choices = ARTICLE_TYPE_CHOICES)
website = models.URLField(max_length=200,blank=True, null=True)
location = models.CharField(max_length=150, blank=True, null=True)
map_link = models.URLField(max_length=200,blank=True, null=True)
time = models.DateTimeField(null=True)
venue = models.ForeignKey('self', null=True)
performers = models.ManyToManyField('self', null=True)
def __unicode__(self):
return self.title
#views.py
def index(request):
carousel = Article.objects.filter(display='C')
marketing = Article.objects.filter(display='M')
featurettes = Article.objects.filter(display='F')
return render_to_response('frontpage.html',{'carousel': carousel, 'marketing':marketing, 'featurettes': featurettes})