I have a list of countries, they all have there own url www.example.com/al/ for example. There is a list of cities for every country but the object_list is empty
My View:
class CityOverview(generic.ListView):
template_name = 'shisha/pages/country_index.html'
model = City
def get_queryset(self, *args, **kwargs):
country_id = self.kwargs.get('country_id')
return City.objects.filter(country__name=country_id)
My Model:
class Country(models.Model):
COUNTRY_CHOICES = (
('al', 'Albania'),
('ad', 'Andorra'),
#etc. etc.
)
name = models.CharField(max_length=255, choices=COUNTRY_CHOICES, default='nl')
def __str__(self):
return self.name
class City(models.Model):
country = models.ForeignKey(Country, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
def __str__(self):
return self.name
My Urls:
path('<str:country_id>', views.CityOverview.as_view(), name='country'),
My Template:
{{ object_list }}
It returns an empty QuerySet
<QuerySet []>
Does anyone know what the problem is?
The problem is you are trying to match country__name to country_id. Alter the last line in get_queryset to become return City.objects.filter(country__id=country_id) which will now filter the country_id supplied against City's country id.
May be your returning query is wrong,
class Country(Models.model):
country_id=Autofield()
country_name=CharaField()
in Views.py
def get_queryset(self, *args, **kwargs):
country_id = self.kwargs.get('country_id')
return City.objects.filter(country_id=country_id)
Related
My task is to change the value of one field in the form (drop-down list with Foreignkey connection). I need to exclude the values of technology that the user already has.
I use CreateView and ModelForm.
forms.py
class SkillCreateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(SkillCreateForm, self).__init__(*args, **kwargs)
employee_current_technology = Technology.objects.filter(??? --- How can I get editing user pk ????-----)
self.fields['technology'].queryset = Technology.objects.exclude(name__in=employee_current_technology)
I know that somehow I can get pk from url using kwarg and get_form_kwarg values, but I can't figure out how to do that.
urls.py
path('profile/<int:pk>/skill/create/', SkillCreateView.as_view(), name='skill_create'),
views.py
class SkillCreateView(AuthorizedMixin, CreateView):
"""
Create new course instances
"""
model = Skill
form_class = SkillCreateForm
template_name = 'employee_info_create.html'
def get_form_kwargs(self):
kwargs = super(SkillCreateView, self).get_form_kwargs()
Employee.objects.get(pk=self.kwargs['pk']) -->get me pk
????
return kwargs
.....
models.py
class Employee(models.Model):
"""Employee information."""
user = models.OneToOneField(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='employee')
summary = models.TextField("summary", blank=True, default='')
skills = models.ManyToManyField(
Technology, through="Skill", verbose_name="skills", blank=True)
class Skill(models.Model):
"""Information about an employee's skills."""
employee = models.ForeignKey(
Employee, on_delete=models.CASCADE, related_name="employee_skills")
technology = models.ForeignKey(Technology, on_delete=models.CASCADE)
class Technology(models.Model):
"""Technologies."""
tech_set = models.ForeignKey(Skillset, on_delete=models.CASCADE, related_name="skillset")
name = models.CharField('technology name', max_length=32, unique=True)
group = models.ForeignKey(Techgroup, on_delete=models.CASCADE, related_name="group")
You can inject the pk in the form, like:
class SkillCreateView(AuthorizedMixin, CreateView):
"""
Create new course instances
"""
model = Skill
form_class = SkillCreateForm
template_name = 'employee_info_create.html'
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update(employee_pk=self.kwargs['pk'])
return kwargs
You can then update the queryset in the form like:
class SkillCreateForm(forms.ModelForm):
def __init__(self, *args, employee_pk=None, **kwargs):
super().__init__(*args, **kwargs)
if employee_pk is not None:
self.fields['technology'].queryset = Technology.objects.exclude(
skill__employee_id=employee_pk
)
I would like to get the total amount of followers attached to the models using in models :
class Project(models.Model):
owner = models.ForeignKey(User, related_name='project_created_by', on_delete=models.CASCADE)
name = models.CharField(max_length=100)
description = models.TextField(max_length=150, blank=True, null=True)
followers = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='followers', blank=True)
created = models.DateTimeField(auto_now_add=True)
last_modefied = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
Here is the class
class ProjectListView(ListView):
template_name = 'projectmanagement/project.html'
context_object_name = 'projects'
def get_queryset(self):
queryset = Project.objects.filter(owner=self.request.user).order_by("name")
return queryset
def get_context_data(self, *args, **kwargs):
context = super(ProjectListView, self).get_context_data(*args, **kwargs)
project = Project.objects.get(pk=12) <-- HERE -->
context['followers'] = project.followers.filter(followers=project).count()
return context
You can .annotate(..) [Django-doc] the queryset of your Product with the number of followers:
from django.db.models import Count
class ProjectListView(ListView):
model = Project
template_name = 'projectmanagement/project.html'
context_object_name = 'projects'
def get_queryset(self):
return super().get_queryset().annotate(
nfollowers=Count('followers')
).filter(
owner=self.request.user
).order_by('name')
Now all projects in the context data will have an extra attribute nfollowers with the number of followers.
You can thus render this for example with:
{% for project in projects %}
{{ project.name }}, followers: {{ project.nfollowers }}<br>
{% endfor %}
I am trying to joint two models in django-rest-framework.
My code isn't throwing any error but also it isn't showing other model fields that need to be joined.
Below is my code snippet:
Serializer:
class CompaniesSerializer(serializers.ModelSerializer):
class Meta:
model = Companies
fields = ('id', 'title', 'category')
class JobhistorySerializer(serializers.ModelSerializer):
companies = CompaniesSerializer(many=True,read_only=True)
class Meta:
model = Jobhistory
fields = ('id', 'title', 'company_id', 'companies')
View .
class UserJobs(generics.ListAPIView):
serializer_class = JobhistorySerializer()
def get_queryset(self):
user_id = self.kwargs['user_id']
data = Jobhistory.objects.filter(user_id=user_id)
return data
model:
class Companies(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=100, blank=True, default='')
category = models.CharField(max_length=30, blank=True, default='')
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('created',)
def save(self, *args, **kwargs):
title = self.title or False
category = self.category or False
super(Companies, self).save(*args, **kwargs)
class Jobhistory(models.Model):
id = models.AutoField(primary_key=True)
company_id = models.ForeignKey(Companies)
title = models.CharField(max_length=100, blank=True, default='')
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('created',)
def save(self, *args, **kwargs):
company_id = self.company_id or False
title = self.title or False
super(Jobhistory, self).save(*args, **kwargs)
Thanks in advance. Any help will be appreciated.
In your views, you have
serializer_class = JobHistorySerializer()
Remove the parenthesis from this.
The reason for this is apparent in the GenericAPIView, specifically the get_serializer() and get_serializer_class() methods:
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def get_serializer_class(self):
"""
Return the class to use for the serializer.
Defaults to using `self.serializer_class`.
You may want to override this if you need to provide different
serializations depending on the incoming request.
(Eg. admins get full serialization, others get basic serialization)
"""
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
)
return self.serializer_class
As you can see in get_serializer, it initializes that serializer class with args and kwargs that aren't provided in your view code.
Django 1.8:
As shown below, I have Location model with a foreign key to the Study model.
I want to display Studies that include country='usa' and is_active=True.
The problem with using the default filter is that if I have:
study1:
country='usa', is_active=False
country='canada', is_active=True
The filter displays this study but it should not so here is what I've tried:
##### models.py:
class Study(models.Model):
title = models.CharField(max_length=30)
def __unicode__(self):
return self.title
class Location(models.Model):
is_active = models.BooleanField()
country = models.CharField(max_length=30)
study = models.ForeignKey(Study, related_name='location')
def __unicode__(self):
return self.country
##### admin.py
class ActiveCountryFilter(admin.SimpleListFilter):
title = _('Active Country Filter')
parameter_name = 'country'
def lookups(self, request, model_admin):
# distinct keyword is not supported on sqlite
unique_countries = []
if DATABASES['default']['ENGINE'].endswith('sqlite3'):
countries = Location.objects.values_list('country')
for country in countries:
if country not in unique_countries:
unique_countries.append(country)
else:
unique_countries = Location.objects.distinct('country').values_list('country')
return tuple([(country, _('active in %s' % country)) for country in unique_countries])
def queryset(self, request, queryset):
if self.value():
return queryset.filter(location__country=self.value(), location__is_active=True)
else:
return queryset
#admin.register(Study)
class StudyAdmin(admin.ModelAdmin):
list_display = ('title',)
list_filter = ('location__country', ActiveCountryFilter)
The filter is not displaying anything.
Any ideas how to achieve what I want?
I've also read the doc about RelatedFieldListFilter but it's pretty confusing.
I figured out.
Just a minor bug in the lookups. I had to pick the country at index zero:
Correction:
return tuple([(country[0], _('active in %s' % country[0])) for country in unique_countries])
I hope this sample helps others.
Sorry for bad English and less information
# Models.py #
class Course(models.Model):
course_code = models.CharField(max_length=100)
title = models.CharField(max_length=200)
short = models.CharField(max_length=50)
elective_group = models.CharField(max_length=100)
def __unicode__(self):
return self.course_code
class Lecturer(models.Model):
username = models.ForeignKey(User)
assigned_course = models.ManyToManyField(Course)
#admin.py#
from django.contrib import admin
from mysite.question_bank.models import *
class CourseAdmin(admin.ModelAdmin):
list_display = ('course_code', 'title', 'short' )
def queryset(self, request):
qs = super(CourseAdmin, self).queryset(request)
if request.user.is_superuser:
return qs #(all the courses)
else:
return qs.filter( ????? ) # particular courses for a username
A lecturer can be assigned as many as course.I want to return a queryset with courses assigned for a particular username.
return qs.filter( ????? ) # particular courses for a username
You can do
return request.user.lecturer_set.get().course_set.all()