Connection of 3 Models with Foreign Key - django

I am a newbie in Django. I have 3 models: Continent, Country, Region
Here is the code:
from django.db import models
# Create your models here.
class Continent(models.Model):
continent = models.CharField(max_length=50, unique=True)
class Meta:
ordering = ['continent']
def __str__(self):
return self.continent
class Country(models.Model):
country = models.CharField(max_length=50, unique=True)
continent = models.ForeignKey(Continent)
class Meta:
ordering = ['country']
verbose_name_plural = 'Countries'
def __str__(self):
return self.country
class Region(models.Model):
country = models.ForeignKey(Country)
region = models.CharField(max_length=50)
class Meta:
ordering = ['region']
def __str__(self):
return self.region
def get_continent(self):
return self.get_continent()
my admin.py looks like this:
from django.contrib import admin
from location.models import Continent, Country, Region
# Register your models here.
class MyAdmin1(admin.ModelAdmin):
list_display = ['continent']
#list_display_links = None
#actions = None
class MyAdmin2(admin.ModelAdmin):
list_display = ['country', 'continent']
class MyAdmin3(admin.ModelAdmin):
model = Region
list_display = ['region', 'country', 'get_continent']
admin.site.register(Continent, MyAdmin1)
admin.site.register(Country, MyAdmin2)
admin.site.register(Region, MyAdmin3)
But in admin panel when I click on table regions it doesn't show 3 attributes in 3 columns. Please, help.

You get a infinite recursion in the Region.get_continent() method:
class Region(models.Model):
...
def get_continent(self):
return self.get_continent()
Change it to:
def get_continent(self):
return self.country.continent

Related

How to write query with in a model with foreign key relation?

class Categorie(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(max_length=2000)
status = models.BooleanField(default=True)
added_date = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return u'%s' % self.name
class GroupQuestion(models.Model):
category = models.ForeignKey(Categorie, related_name='%(class)s_name_related', null=True)
name = models.CharField(max_length=200)
added_date = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=True)
class Meta:
verbose_name = 'Group of Questions'
verbose_name_plural = 'Group of Questions'
def __unicode__(self):
return u'%s' % self.name
class Question(models.Model):
category = models.ForeignKey(Categorie, related_name='%(class)s_name_related', null=True)
group = models.ForeignKey(GroupQuestion, related_name='%(class)s_name_related')
name = models.TextField(max_length=200)
added_date = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=True)
#select_choice = models.CharField(max_length=5, choices=QUESTION_CHOICES, null=True)
positive_answer = models.PositiveIntegerField()
negative_answer = models.PositiveIntegerField()
def __unicode__(self):
return u'%s' % self.name
I have these three model. When I pass category_id from my API wants to get QuestionGroups and Questions related to that group?
Some thing like this
"data": [
{
id:1
name = ABC
"question":[
{
"id":1
"name":ABC
}
{
"id":1
"name":ABC
}
]
}
{
id:1
name = ABC
"question":[
{
"id":1
"name":ABC
}
{
"id":1
"name":ABC
}
]
}
}
I am new in django some can help me how to write query in view and how to serialize data.
You are looking for a nested serialization.
You should create two serializers. One for your GroupQuestion model and one for your Question model. You will use in your QuestionSerializer inside your GroupQuestionSerializer in order to perform a nested serialization.
In your serializers.py:
from rest_framework import serializers
from .models import GroupQuestion, Question
# Serializer for the Question model
class QuestionSerializer(serializers.ModelSerializer):
class Meta:
model = Question
fields = ('id', 'name')
# Serializer for the GroupQuestion model
class GroupQuestionSerializer(serializers.ModelSerializer):
question_name_related = QuestionSerializer(read_only=True, many=True)
# The magic happens here ^
# You use your QuestionSerializer inside your GroupQuestionSerializer
# In order to serialize the related Questions for this GroupQuestion
class Meta:
model = GroupQuestion
fields = ('id', 'question_name_related')
Then let's say you have a simple ListAPIView for listing your GroupQuestion entries.
In your views.py:
from rest_framework import generics
from .models import GroupQuestion
from .serializers import GroupQuestionSerializer
# Import the serializer that we have just created
class GroupQuestionList(generics.ListAPIView):
serializer_class = GroupQuestionSerializer
def get_queryset(self):
category_id = self.kwargs['category_id']
category = generics.get_object_or_404(Categorie, id=category_id)
return GroupQuestion.objects.filter(category=category)
This view will simply serialize all your GroupQuestion models, which have related Categorie with the given id.
Finally, map this view in your urls and when you access this endpoint, you should get the expected result.
In your urls.py:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^groups/(?P<category_id>[0-9]+)/$', views.GroupQuestionList.as_view(), name='group_question_list')
]
Note: I am not sure that question_name_related is the valid related_name for the Question model in your GroupQuestion.

Django Tabular in Line example

I really need somebody to explain/show me how I can achieve a TabularInline display in the django admin console of my example. Could somebody help me out?
My models are as follows:
from django.db import models
class Player(models.Model):
player_id = models.IntegerField(primary_key=True)
team = models.ForeignKey(Team)
player_name = models.CharField(max_length=140)
position = models.CharField(max_length=10)
def __str__(self):
return '%s' % (self.player_name)
class MatchdayStats(models.Model):
MATCHDAY_STATS_ID = models.AutoField(primary_key=True)
appeared = models.BooleanField(default=False)
goal = models.IntegerField(default=0)
minutes_under_60 = models.BooleanField(default=False)
minutes_60 = models.BooleanField(default=False)
assist = models.IntegerField(default=0)
def __str__(self):
return '%s' % (self.MATCHDAY_STATS_ID)
class PlayerGameweekStats(models.Model):
PLAYER_GAMEWEEK_ALLSTATS_ID = models.AutoField(primary_key=True)
player = models.ForeignKey(Player)
gameweek = models.ForeignKey('fixturesresults.Gameweek')
matchday_stats = models.ForeignKey(MatchdayStats)
def __str__(self):
return '%s (gw=%s,msid=%s)' % (self.player.player_name,self.gameweek.GAMEWEEK_ID,self.matchday_stats.MATCHDAY_STATS_ID)
I would like there to be a tabular display for the PlayerGameweekStats model, where you can enter MatchdayStats fields for each player.
The admin code below causes a Foreign Key error <class 'playerteamstats.models.MatchdayStats'> has no ForeignKey to <class 'playerteamstats.models.PlayerGameweekStats'>
class StatsInLine(admin.TabularInline):
model = MatchdayStats
class PlayerGameweekStatsAdmin(admin.ModelAdmin):
list_display = ('player', 'gameweek')
exclude = ('gameweek')
inlines = [
StatsInLine,
]
admin.site.register(PlayerGameweekStats, PlayerGameweekStatsAdmin)
To build TabularInline models need to be connected with ForeignKey.
From Django docs example:
models.py:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100)
admin.py:
from django.contrib import admin
class BookInline(admin.TabularInline):
model = Book
class AuthorAdmin(admin.ModelAdmin):
inlines = [
BookInline,
]
In you case you need to have ForeignKey to PlayerGameweekStats in MatchdayStats.

list_display of the model with foreign key

I have the following django model.
In the django admin model of TestCase table, in its list_display, i want to display the most recent comment and the modifier name of Remark table.
models.py
from django.db import models
class Release(models.Model):
title = models.CharField(max_length=128)
start_time = models.DateField('Release Start Date')
release_date = models.DateField('Release Ended Date')
def __str__(self):
return self.title
class TestCase(models.Model):
query = models.CharField(max_length=256)
ksq_id = models.IntegerField()
status = models.CharField(max_length=64)
release = models.ForeignKey(Release) # Release can have many test cases
def __str__(self):
return self.query
class Remark(models.Model):
owner = models.CharField(max_length=64)
module = models.CharField(max_length=64)
comment = models.CharField(max_length=1024)
modified_ts = models.DateTimeField('date modified', auto_now=True)
modifier = models.CharField(max_length=64)
testcase = models.ForeignKey(TestCase) # Testcase can have many Re
admin.py
from django.contrib import admin
from kramer_release.models import Release, TestCase, Remark
class RemarksInline(admin.TabularInline):
model = Remark
extra = 0
class RemarkAdmin(admin.ModelAdmin):
list_display = ('owner', 'module', 'testcase_query')
def testcase_query(self, obj):
return obj.testcase.query
class TestCaseAdmin(admin.ModelAdmin):
inlines = [RemarksInline]
list_display = ('query', 'status')
admin.site.register(Release)
admin.site.register(TestCase, TestCaseAdmin)
admin.site.register(Remark, RemarkAdmin)
You can defined a function to get the latest comment as part of you admin class, something like:
class TestCaseAdmin(admin.ModelAdmin):
inlines = [RemarksInline]
list_display = ('query', 'status', 'latest_comment')
def latest_comment(self, obj):
remarks = Remark.objects.filter(testcase=obj).order_by('-modified_ts')
if remarks:
return '%s - %s' % (remarks[0].comment, remarks[0].modifier)
return None
see the docs

how to chain field?

This my engine models
from django.db import models
class Colors(models.Model):
color_name = models.CharField(max_length=50)
def __unicode__(self):
return self.color_name
This my Cars models
from django.db import models
class Cars(models.Model):
car_model = models.CharField(max_length=50)
car_colors = models.ManytoManyField(Colors, related_name='Car Colors')
def __unicode__(self):
return self.car_model
O.K. Let's see my CarsData Model.
This my CarsData models
from django.db import models
class CarsData(models.Model):
car_barcode= models.CharField(max_length=50)
available_color = ChainedForeignKey(
Cars,
chained_field="car_model",
chained_model_field="car_colors",
show_all=False,
auto_choose=True
)
def __unicode__(self):
return self.car_barcode
My admin.py looks like that:
from django.contrib import admin
from django import forms
from myapp.models import *
class CarsDataAdminForm(forms.ModelForm):
class Meta:
model = CarsData
def __init__(self, *arg, **kwargs):
super(CarsDataAdminForm, self).__init__(*arg, **kwargs)
self.fields['available_color'].choices = [(csc.id,csc.car_colors) for csc in Cars.objects.all()
class CarsDataAdmin(admin.ModelAdmin):
form = CarsDataAdminForm
admin.site.register(CarsData,CarsDataAdmin)
Is there anyway to show in the ChoiceField 'just' color_name field datas? I see just car_model because i have to set it :
def __unicode__(self):
return self.car_model
How can i chain available_colors field to color_name field? I want to show in available_colors choices just color names like red, blue, black, white...
Can you please give me an example?
I think I don't get your code:
class CarsData(models.Model):
car_barcode = models.CharField(max_length=50)
available_color = ChainedForeignKey(
Cars,
chained_field="car_model", # should be a field in THIS model
chained_model_field="car_colors", # should be the matching field
# in the Cars model
show_all=False,
auto_choose=True
)
And both referenced fields must be ForeignKeys to the same (third) model.
Maybe this works, even without changing the AdminForm (I also changed the model names to singular and remove some repetitions, as the most common use dictates):
class Color(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class CarModel(models.Model):
model = models.CharField(max_length=50)
available_colors = models.ManytoManyField(Color, through='AvailableColor')
def __unicode__(self):
return self.model
class AvailableColor(models.Model):
car_model = models.ForeignKey(CarModel)
color = models.ForeignKey(Color)
def __unicode__(self):
return unicode(self.color)
class CarData(models.Model):
car_barcode = models.CharField(max_length=50)
car_model = models.ForeignKey(CarModel)
car_color = ChainedForeignKey(
AvailableColor,
chained_field="car_model", # field in CarData
chained_model_field="car_model", # field in AvailableColor
show_all=False,
auto_choose=True
)
You can't do otherwise because you need two models with a matching FK. Using Cars.car_colors.through (that is a valid model on which to query etc) you don't have a good display. With a (dummy) explicit intermediate model you define unicode and the admin should show the correct data.

Django Inline Forms newly added Foreign Key Field but not showing in newly added inline rows

I am quite newbie in Django world. My question is I ve two models shown below. It works quite well with Grapelli and inline-sortables. Only problem is whenever I add a new foreign key for "equipment" or "image type" fields. They don't show up in the drop down menu of newly added inline rows. I went through internet but couldn't find a smilar problem and a solution.
I would appreciate some help with this.
My model is:
from django.db import models
from datetime import datetime
from thumbs import ImageWithThumbsField
from positions.fields import PositionField
class Artist(models.Model):
name = models.CharField(max_length=55)
def __unicode__(self):
return self.name
class ImageType(models.Model):
name = models.CharField(max_length=55)
def __unicode__(self):
return self.name
class Equipment(models.Model):
name = models.CharField(max_length=55)
def __unicode__(self):
return self.name
class Image(models.Model):
name = models.CharField(max_length=255)
image_file = models.ImageField(upload_to = "images/%Y-%m-%d")
Image_Type = models.ForeignKey(ImageType)
upload_date = models.DateTimeField('date_published',default=datetime.now)
artist = models.ForeignKey(Artist)
equipment = models.ForeignKey(Equipment)
order = PositionField(collection='artist')
def __unicode__(self):
return self.name
class Meta:
ordering = ['order']
And My admin.py is:
from gallery.models import Image,ImageType,Artist,Equipment
from django.contrib import admin
class ImageUploadAdmin(admin.ModelAdmin):
fields = ['name','artist','equipment','image_file','Image_Type','upload_date']
list_filter = ['upload_date']
date_hierarchy = 'upload_date'
class ImageInline(admin.TabularInline):
model = Image
list_display = ('name','equipment','image_file','Image_Type','upload_date')
sortable_field_name = "order"
exclude = ('upload_date',)
extra = 0
class ArtistAdmin(admin.ModelAdmin):
inlines = [
ImageInline,
]
admin.site.register(Artist,ArtistAdmin)
admin.site.register(Image, ImageUploadAdmin)
admin.site.register(ImageType)
admin.site.register(Equipment)