Here my models:
django_zoom2/meetings/models.py
from django.db import models
from participants.models import Participant
class Meeting(models.Model):
topic = models.CharField(max_length=100)
uuid = models.CharField(max_length=100, default='xxxx')
participants = models.ManyToManyField(Participant)
def __str__(self):
return self.topic
django_zoom2/participants/models.py
from django.db import models
# from meetings.models import Meeting
class Participant(models.Model):
name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
def __str__(self):
return self.email
..and the admin views:
django_zoom2/meetings/admin.py
from django.contrib import admin
from .models import Meeting
#admin.register(Meeting)
class MeetingAdmin(admin.ModelAdmin):
list_display = ['topic', 'uuid']
django_zoom2/meetings/admin.py
from django.contrib import admin
from .models import Participant
#admin.register(Participant)
class ParticipantAdmin(admin.ModelAdmin):
list_display = ['name', 'email']
I have a single association with the meeting blarg:
>>> from meetings.models import Meeting
>>> m= Meeting.objects.get(id=1)
>>> m
<Meeting: blarg>
>>> m.participants.all()
<QuerySet [<Participant: molly#myorg.org>]>
...but in the view here is what I see:
Why am I seeing all the participants email addresses in this view? I only want to see the associated email addresses; in this case, there should be one. Molly.
Ok, this should give you a list of Participants for each meeting as a Tabular inline. You can edit the extra=0 as needed.
In meetings/admin.py:
class AttendanceInline(admin.TabularInline):
model = Meeting.participants.through
extra = 0
#admin.register(Meeting)
class MeetingAdmin(admin.ModelAdmin):
inlines = [
AttendanceInline,
]
exclude = ('participants',)
More in the docs.
Related
I was wondering what the correct way is to serialize data in Django REST API from 2 models connected with ForeignKey.
The situation is: i have a 1st table called NewUsers with the user registrations, and a 2nd table called Ticker with data saved from an external API.
The goal is: create a 3rd table with parts of the 2 tables interconnected - one part is the user loggedin, and the other part is the selection of one crypto object. This new table will then be displayed via Django REST API serializer.
The problem is: this new 3rd table does not display the complete list of values selected by the user.
I have gone through the documentation here https://books.agiliq.com/projects/django-admin-cookbook/en/latest/override_save.html and here https://www.django-rest-framework.org/tutorial/1-serialization/ but could not find a complete solution. What am i missing?
views.py:
from rest_framework import generics
from .serializers import WatchlistSerializer
from ticker.serializers import TickerSerializer
from watchlist.models import SectionWatchlist
from ticker.models import Ticker
import requests
from rest_framework.views import APIView
from rest_framework.decorators import api_view
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
class CreateSectionWatchlist(generics.CreateAPIView):
queryset = SectionWatchlist.objects.all()
serializer_class = WatchlistSerializer
class ListSectionWatchlist(generics.ListAPIView):
queryset = SectionWatchlist.objects.all()
serializer_class = WatchlistSerializer
def get_queryset(self):
queryset = SectionWatchlist.objects.all()
author = self.request.query_params.get('author')
if author:
queryset = queryset.filter(author=author)
return queryset
class DeleteSectionWatchlist(generics.RetrieveDestroyAPIView):
queryset = SectionWatchlist.objects.all()
serializer_class = WatchlistSerializer
models.py:
from django.db import models
from django.conf import settings
from ticker.models import Ticker
class SectionWatchlist(models.Model):
id = models.AutoField(primary_key=True) # auto increment field
tickerlist = models.ForeignKey(Ticker, related_name="tickerinfo", on_delete=models.CASCADE)
crypto = models.CharField(blank=True, null=True, max_length=40)
c_0 = models.FloatField(null=True, blank=True, default=None)
o_0 = models.FloatField(null=True, blank=True, default=None)
percentage = models.FloatField(null=True, blank=True, default=None)
user_name = models.CharField(blank=True, null=True, max_length=40)
author = models.ForeignKey(
settings.AUTH_USER_MODEL, blank=True, null=True,
on_delete=models.CASCADE,
)
serializers.py:
from rest_framework import serializers
from watchlist.models import SectionWatchlist
from ticker.models import Ticker
from ticker.serializers import TickerSerializer
class WatchlistSerializer(serializers.ModelSerializer):
crypto = TickerSerializer()
class Meta:
model = SectionWatchlist
fields = ('id','tickerlist','author', 'crypto')
the Django REST API incomplete response
{
"id": 88,
"tickerlist": 36,
"author": 6,
"crypto": {
"crypto": null,
"c_0": null,
"o_0": null
}
}
]
admin.py:
from django.contrib import admin
from django import forms
from . import models
from ticker.models import Ticker
#admin.register(models.SectionWatchlist)
class WatchlistAdmin(admin.ModelAdmin):
list_display = (
'id',
# 'percentage',
'tickerlist',
# 'user_name',
'author',
'get_crypto',
'get_c_0',
'get_o_0',
)
#admin.display(ordering='watchlist__tickerlist', description='get_crypto')
def get_crypto(self, obj):
return obj.tickerlist.crypto
#admin.display(ordering='watchlist__tickerlist', description='c_0')
def get_c_0(self, obj):
return obj.tickerlist.c_0
#admin.display(ordering='watchlist__tickerlist', description='o_0')
def get_o_0(self, obj):
return obj.tickerlist.o_0
Actually my admin displays the response correctly with complete values:
.
How can I have the serialized response in Django REST API complete?
I think you need to set the serializer for the foreign key fields.
class WatchlistSerializer(serializers.ModelSerializer):
tickerlist= TickerSerializer()
author = UserSerializer()
class Meta:
model = SectionWatchlist
fields = ('id', 'tickerlist', 'author', 'crypto')
My task was
**Create a actor model, List should return all the movies of him, Aggregate total movies he worked
Create a genre model, List should return all the movies under the genre, Aggregate total movies
Create a movie model, that have name, actors and genre fields. Here actors and genre should be a manytomany relationship **
I have done this
models.py
from django.db import models
class Actor(models.Model):
actors = models.CharField(max_length=100)
def __str__(self):
return self.actors
class Genre(models.Model):
genre = models.CharField(max_length=100)
def __str__(self):
return self.genre
class Movie(models.Model):
name = models.CharField(max_length=100)
actors = models.ManyToManyField(Actor)
genre = models.ManyToManyField(Genre)
def __str__(self):
return self.name
serializer.py
from rest_framework import serializers
from .models import Movie,Genre,Actor
class ActorSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Actor
fields = ['url','actors']
class GenreSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Genre
fields = ['genre']
class MovieSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Movie
fields = ['url','name','actors','genre']
views.py
from django.shortcuts import render
from rest_framework import viewsets
# Create your views here.
from .serializers import MovieSerializer,ActorSerializer,GenreSerializer
from .models import Movie,Actor,Genre
from django.db.models import Count
class movie(viewsets.ModelViewSet):
queryset = Movie.objects.all()
serializer_class = MovieSerializer
class actor(viewsets.ModelViewSet):
queryset = Actor.objects.all()
serializer_class = ActorSerializer
class genre(viewsets.ModelViewSet):
queryset = Genre.objects.all()
serializer_class=GenreSerializer
urls.py
from django.urls import include, path
from rest_framework import routers
from .views import *
# define the router
router = routers.DefaultRouter()
# define the router path and viewset to be used
router.register(r'movie', movie)
router.register(r'actor', actor)
router.register(r'genre',genre)
urlpatterns = [
path('', include(router.urls)),
]
I cant able to do this part ** List should return all the movies of him, Aggregate total movies he worked **
You need to set the related_name field if you want to get the related fields.
class Movie(models.Model):
name = models.CharField(max_length=100)
actors = models.ManyToManyField(Actor, related_to = "actor_movies")
genre = models.ManyToManyField(Genre, related_to = "genre_movies")
def __str__(self):
return self.name
And then you need to add the RelatedField in serialzers.py file,
class ActorSerializer(serializers.HyperlinkedModelSerializer):
actor_movies = serializers.RelatedField(many = True, read_only = True)
class Meta:
model = Actor
fields = ['url','actors', 'actor_movies']
class GenreSerializer(serializers.HyperlinkedModelSerializer):
genre_movies = serializers.RelatedField(many = True, read_only = True)
class Meta:
model = Genre
fields = ['genre', 'genre_movies']
Then in JSON, you can get the movies of him, movies of the genre, etc.
Hope it could help.
class ActorSerializer(serializers.HyperlinkedModelSerializer):
count_actor_movies = serializers.SerializerMethodField()
def get_count_actor_movies(self, instance):
return instance.actor_movies.count()
class Meta:
model = Actor
fields = ['id','actors','count_actor_movies']
now it work fine it show the count of actors in the movie
i have field "car" that contains values "Benz, Nissan, Kia"
using ==> list_filter ["car"] how can i filter by Both values like "Nissan" and "Kia" . Both not one of them
Car objects
You could use MultipleChoiceListFilter from django-admin-multiple-choice-list-filter package, since there is no multi-choice filter built into Django. Example:
models.py
class CarModel(models.Model):
name = models.CharField(max_length=255)
class Car(models.Model):
car_model = models.ForeignKey(CarModel, on_delete=models.CASCADE)
admin.py
from django.contrib import admin
from django_admin_multiple_choice_list_filter.list_filters import MultipleChoiceListFilter
from .models import Car
class CarModelListFilter(MultipleChoiceListFilter):
title = 'Car Model'
parameter_name = 'car_model__in'
def lookups(self, request, model_admin):
return CarModel.objects.values_list('pk', 'name')
class CarAdmin(admin.ModelAdmin):
list_display = ('car_model',)
list_filter = (CarModelListFilter,)
admin.site.register(Car, CarAdmin)
I currently have 2 relevant classes in my model: A UserProfile class and a FriendInvite class in models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
username = models.TextField()
friends = models.ManyToManyField('self',through='FriendInvite',
symmetrical=False)
class FriendInvite(models.Model):
sender = models.ForeignKey(UserProfile,related_name='fi_sender')
invitee = models.ForeignKey(UserProfile,related_name='fi_invitee')
status = models.IntegerField(default=0)
def __str__(self):
return '%s invites %s' % (self.sender.username,self.invitee.username)
In serializers.py:
from rest_framework import serializers
from myapp.models import UserProfile
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
And in views.py:
from rest_framework import generics
from myapp.models import UserProfile
from myapp.serializers import UserProfileSerializer
class UserProfileList(generics.ListAPIView):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
I generated 5 different users and 3 different friend relationships. However, when I received the JSON response from the server, it only included the users who sent the invites, not the ones who received them:
[{"id":1,"username":"U1","user":1,"friends":[5]},
{"id":2,"username":"U2","user":2,"friends":[]},
{"id":3,"username":"U3","user":3,"friends":[4]},
{"id":4,"username":"U4","user":4,"friends":[]},
{"id":5,"username":"U5","user":5,"friends":[2]}]
In this case, U1 sent an invite to U5, U3 to U4, and U5 to U2. How can I get results for both sent and received invites for users?
My current solution is to define a method in the UserProfile class and use queries to get the set of objects I want. I still want to know if there are other ways to do this, though.
...
from itertools import chain
from django.db.models import Q
class UserProfile(models.Model):
...
def get_friends_both(self):
invitees_list = FriendInvite.objects.filter(Q(sender=self)).values('invitee')
sender_list = FriendInvite.objects.filter(Q(invitee=self)).values('sender')
return chain(sender_list, invitees_list)
class UserProfileSerializer(serializers.ModelSerializer):
friend_list = serializers.ReadOnlyField(source='get_friends_both')
class Meta:
model = UserProfile
fields = ('friend_list','username','id')
depth = 1
For academic purposes, I am creating software that can manage a company's clients, project, and staff members. I figured out that by referencing a foreignkey in a separate model, you can get two models to display next to each other and be related. The problem is, is that it only displays one item for each model.
For example: You have a project your company is working on. In the admin section, it displays the project name and a single staff member. However, it should be displaying 2+ staff members.
Here's the file layout (I tried creating a separate app for different fields clients being the primary and projects the secondary):
clients.admin:
from django.contrib import admin
from django.db import models
from clients.models import Status, Project, Staff_Member, Client
class StatusInline(admin.TabularInline):
model = Status
extra = 0
class Staff_MemberInline(admin.TabularInline):
model = Staff_Member
extra = 5
project = models.ForeignKey(Project)
class ProjectInline(admin.TabularInline):
model = Project
extra = 1
class ClientAdmin(admin.ModelAdmin):
fieldsets = [
(None, {'fields': ['name']}),
]
inlines = [ProjectInline, StatusInline]
search_fields = ['name']
admin.site.register(Client, ClientAdmin)
#admin.site.register(Project)
admin.site.register(Staff_Member)
next file
clients.models:
from django.db import models
import datetime
from django.utils import timezone
# Create your models here.
class Client(models.Model):
name = models.CharField(max_length=200)
def __unicode__(self):
return self.name
#def was_published_recently(self):
# return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
#was_published_recently.admin_order_filed = 'pub_date'
#was_published_recently.boolean = True
#was_published_recently.short_description = 'Published recently?'
class Status(models.Model):
client = models.ForeignKey(Client)
#staff_member = models.ForeignKey(Staff_Member)
#project = models.ForeignKey(Project)
status_text = models.CharField(max_length=200)
def stat(self):
return self.status_text
def __unicode__(self):
return self.status_text
class Staff_Member(models.Model):
#status = models.ForeignKey(Status)
#project = models.ForeignKey(Project)
#client = models.ForeignKey(Client)
staff_member_text = models.CharField(max_length=200)
def __unicode__(self):
return self.staff_member_text
def mem(self):
return self.staff_member_text
class Project(models.Model):
client = models.ForeignKey(Client)
project_text = models.CharField(max_length=200)
staff_member = models.ForeignKey(Staff_Member)
#status = models.ForeignKey(Status)
def __unicode__(self):
full_name = self.client.name +'\'s '+ self.project_text
return full_name
def project_name(self):
return self.project_text
name = client.name
next file
projects.admin:
from django.contrib import admin
from django.db import models
from clients.models import Project, Status, Client
from clients.admin import StatusInline, Staff_MemberInline
class ClientInline(admin.TabularInline):
model = Client
extra = 1
#class ProjectAdmin(admin.ModelAdmin):
# inlines = [Staff_MemberInline, ClientInline]
#admin.site.unregister(Project)
admin.site.register(Project)#, ProjectAdmin)
next file
projects.models
from django.db import models
import datetime
from django.utils import timezone
from django.db import models
from clients.models import *
# Create your models here.
I'm pretty new to stackoverflow, so if there's a way I'm missing to make this more eye-friendly let me know.
Thanks!
Change extra = 1 to a higher number. More info in the docs.